2016-02-12 16:00:36 +00:00
/ * *
* @ author Richard Davey < rich @ photonstorm . com >
2016-04-14 12:23:44 +00:00
* @ copyright 2016 Photon Storm Ltd .
2016-02-12 16:00:36 +00:00
* @ license { @ link https : //github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*
* @ overview
*
* Phaser - http : //phaser.io
*
2016-06-02 22:23:23 +00:00
* v2 . 4.9 "Four Kings" - Built : Thu Jun 02 2016 23 : 22 : 01
2016-02-12 16:00:36 +00:00
*
* By Richard Davey http : //www.photonstorm.com @photonstorm
*
* Phaser is a fun , free and fast 2 D game framework for making HTML5 games
* for desktop and mobile web browsers , supporting Canvas and WebGL rendering .
*
* Phaser uses Pixi . js for rendering , created by Mat Groves http : //matgroves.com @Doormat23
* Phaser uses p2 . js for full - body physics , created by Stefan Hedman https : //github.com/schteppe/p2.js @schteppe
* Phaser contains a port of N + Physics , converted by Richard Davey , original by http : //www.metanetsoftware.com
*
* Many thanks to Adam Saltsman ( @ ADAMATOMIC ) for releasing Flixel , from which both Phaser
* and my love of framework development originate .
*
* Follow development at http : //phaser.io and on our forum
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
* -- Albert Einstein
* /
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
( function ( ) {
var root = this ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* The [ pixi . js ] ( http : //www.pixijs.com/) module/namespace.
*
* @ module PIXI
* /
/ * *
* Namespace - class for [ pixi . js ] ( http : //www.pixijs.com/).
*
* Contains assorted static properties and enumerations .
*
* @ class PIXI
* @ static
* /
var PIXI = PIXI || { } ;
/ * *
* A reference to the Phaser Game instance that owns this Pixi renderer .
* @ property { Phaser . Game } game
* @ static
* /
PIXI . game = null ;
/ * *
* @ property { Number } WEBGL _RENDERER
* @ protected
* @ static
* /
PIXI . WEBGL _RENDERER = 0 ;
/ * *
* @ property { Number } CANVAS _RENDERER
* @ protected
* @ static
* /
PIXI . CANVAS _RENDERER = 1 ;
/ * *
* Version of pixi that is loaded .
* @ property { String } VERSION
* @ static
* /
PIXI . VERSION = "v2.2.9" ;
// used to create uids for various pixi objects.
PIXI . _UID = 0 ;
if ( typeof ( Float32Array ) != 'undefined' )
{
PIXI . Float32Array = Float32Array ;
PIXI . Uint16Array = Uint16Array ;
// Uint32Array and ArrayBuffer only used by WebGL renderer
// We can suppose that if WebGL is supported then typed arrays are supported too
// as they predate WebGL support for all browsers:
// see typed arrays support: http://caniuse.com/#search=TypedArrays
// see WebGL support: http://caniuse.com/#search=WebGL
PIXI . Uint32Array = Uint32Array ;
PIXI . ArrayBuffer = ArrayBuffer ;
}
else
{
PIXI . Float32Array = Array ;
PIXI . Uint16Array = Array ;
}
/ * *
* @ property { Number } PI _2
* @ static
* /
PIXI . PI _2 = Math . PI * 2 ;
/ * *
* @ property { Number } RAD _TO _DEG
* @ static
* /
PIXI . RAD _TO _DEG = 180 / Math . PI ;
/ * *
* @ property { Number } DEG _TO _RAD
* @ static
* /
PIXI . DEG _TO _RAD = Math . PI / 180 ;
/ * *
* @ property { String } RETINA _PREFIX
* @ protected
* @ static
* /
PIXI . RETINA _PREFIX = "@2x" ;
/ * *
* 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
PIXI . defaultRenderOptions = {
view : null ,
transparent : false ,
antialias : false ,
preserveDrawingBuffer : false ,
resolution : 1 ,
clearBeforeRender : true ,
autoResize : false
} ;
* /
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* The base class for all objects that are rendered on the screen .
* This is an abstract class and should not be used on its own rather it should be extended .
*
* @ 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 ( 0 , 0 ) ;
/ * *
* The scale factor of the object .
*
* @ property scale
* @ type Point
* /
this . scale = new PIXI . Point ( 1 , 1 ) ;
/ * *
* 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 ;
/ * *
* 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 ] Current transform of the object based on world ( parent ) factors
*
* @ property worldTransform
* @ type Matrix
* @ readOnly
* @ private
* /
this . worldTransform = new PIXI . Matrix ( ) ;
/ * *
* The position of the Display Object based on the world transform .
* This value is updated at the end of updateTransform and takes all parent transforms into account .
*
* @ property worldPosition
* @ type Point
* @ readOnly
* /
this . worldPosition = new PIXI . Point ( 0 , 0 ) ;
/ * *
* The scale of the Display Object based on the world transform .
* This value is updated at the end of updateTransform and takes all parent transforms into account .
*
* @ property worldScale
* @ type Point
* @ readOnly
* /
this . worldScale = new PIXI . Point ( 1 , 1 ) ;
/ * *
* The rotation of the Display Object , in radians , based on the world transform .
* This value is updated at the end of updateTransform and takes all parent transforms into account .
*
* @ property worldRotation
* @ type Number
* @ readOnly
* /
this . worldRotation = 0 ;
/ * *
* cached sin rotation and cos rotation
*
* @ property _sr
* @ type Number
* @ private
* /
this . _sr = 0 ;
/ * *
* cached sin rotation and cos rotation
*
* @ property _cr
* @ type Number
* @ private
* /
this . _cr = 1 ;
/ * *
* 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
*
* @ property filterArea
* @ type Rectangle
* /
this . filterArea = null ;
/ * *
* The original , cached bounds of the object
*
* @ property _bounds
* @ type Rectangle
* @ private
* /
this . _bounds = new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
/ * *
* The most up - to - date bounds of the object
*
* @ property _currentBounds
* @ type Rectangle
* @ private
* /
this . _currentBounds = null ;
/ * *
* The original , cached mask of the object
*
* @ property _mask
* @ type Rectangle
* @ private
* /
this . _mask = null ;
/ * *
* Cached internal flag .
*
* @ property _cacheAsBitmap
* @ type Boolean
* @ private
* /
this . _cacheAsBitmap = false ;
/ * *
* Cached internal flag .
*
* @ property _cacheIsDirty
* @ type Boolean
* @ private
* /
this . _cacheIsDirty = false ;
} ;
// constructor
PIXI . DisplayObject . prototype . constructor = PIXI . DisplayObject ;
/ * *
* Destroy this DisplayObject .
* Removes all references to transformCallbacks , its parent , the stage , filters , bounds , mask and cached Sprites .
*
* @ method destroy
* /
PIXI . DisplayObject . prototype . destroy = function ( )
{
if ( this . children )
{
var i = this . children . length ;
while ( i -- )
{
this . children [ i ] . destroy ( ) ;
}
this . children = [ ] ;
}
this . hitArea = null ;
this . parent = null ;
this . stage = null ;
this . worldTransform = null ;
this . filterArea = null ;
this . _bounds = null ;
this . _currentBounds = null ;
this . _mask = null ;
// In case Pixi is still going to try and render it even though destroyed
this . renderable = false ;
this . _destroyCachedSprite ( ) ;
} ;
/ * *
* [ read - only ] Indicates if the sprite is globally visible .
*
* @ 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' .
*
* You cannot have a filter and a multiply blend mode active at the same time . Setting a filter will reset
* this objects blend mode to NORMAL .
*
* @ property filters
* @ type Array ( Filter )
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'filters' , {
get : function ( ) {
return this . _filters ;
} ,
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 ;
if ( this . blendMode && this . blendMode === PIXI . blendModes . MULTIPLY )
{
this . blendMode = PIXI . blendModes . NORMAL ;
}
}
} ) ;
/ * *
* 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'
* @ property cacheAsBitmap
* @ type Boolean
* /
Object . defineProperty ( PIXI . DisplayObject . prototype , 'cacheAsBitmap' , {
get : function ( ) {
return this . _cacheAsBitmap ;
} ,
set : function ( value ) {
if ( this . _cacheAsBitmap === value )
{
return ;
}
if ( value )
{
this . _generateCachedSprite ( ) ;
}
else
{
this . _destroyCachedSprite ( ) ;
}
this . _cacheAsBitmap = value ;
}
} ) ;
/ *
* Updates the object transform for rendering .
*
* If the object has no parent , and no parent parameter is provided , it will default to Phaser . Game . World as the parent .
* If that is unavailable the transform fails to take place .
*
* The ` parent ` parameter has priority over the actual parent . Use it as a parent override .
* Setting it does * * not * * change the actual parent of this DisplayObject , it just uses the parent for the transform update .
*
* @ method updateTransform
* @ param { DisplayObject } [ parent ] - Optional parent to parent this DisplayObject transform from .
* /
PIXI . DisplayObject . prototype . updateTransform = function ( parent )
{
if ( ! parent && ! this . parent && ! this . game )
{
return ;
}
var p = this . parent ;
if ( parent )
{
p = parent ;
}
else if ( ! this . parent )
{
p = this . game . world ;
}
// create some matrix refs for easy access
var pt = p . worldTransform ;
var wt = this . worldTransform ;
// temporary matrix variables
var a , b , c , d , tx , ty ;
// 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 ;
}
// 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 ;
tx = this . position . x - this . pivot . x * a ;
ty = this . position . y - this . pivot . y * d ;
wt . a = a * pt . a ;
wt . b = a * pt . b ;
wt . c = d * pt . c ;
wt . d = d * pt . d ;
wt . tx = tx * pt . a + ty * pt . c + pt . tx ;
wt . ty = tx * pt . b + ty * pt . d + pt . ty ;
}
// multiply the alphas..
this . worldAlpha = this . alpha * p . worldAlpha ;
this . worldPosition . set ( wt . tx , wt . ty ) ;
2016-05-23 12:18:30 +00:00
this . worldScale . set ( Math . sqrt ( wt . a * wt . a + wt . b * wt . b ) , Math . sqrt ( wt . c * wt . c + wt . d * wt . d ) ) ;
2016-05-19 11:36:51 +00:00
this . worldRotation = Math . atan2 ( wt . c , wt . d ) ;
2016-02-12 16:00:36 +00:00
// reset the bounds each time this is called!
this . _currentBounds = null ;
// Custom callback?
if ( this . transformCallback )
{
this . transformCallback . call ( this . transformCallbackContext , wt , pt ) ;
}
} ;
// performance increase to avoid using call.. (10x faster)
PIXI . DisplayObject . prototype . displayObjectUpdateTransform = PIXI . DisplayObject . prototype . updateTransform ;
/ * *
* Retrieves the bounds of the displayObject as a rectangle object
*
* @ method getBounds
* @ param matrix { Matrix }
* @ return { Rectangle } the rectangular bounding area
* /
PIXI . DisplayObject . prototype . getBounds = function ( matrix )
{
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 ;
} ;
/ * *
* Empty , to be overridden by classes that require it .
*
* @ method preUpdate
* /
PIXI . DisplayObject . prototype . preUpdate = function ( )
{
} ;
/ * *
* 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
* @ 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
* @ param renderer { CanvasRenderer | WebGLRenderer } The renderer used to generate the texture .
2016-05-19 11:36:51 +00:00
* @ return { RenderTexture } a texture of the graphics object
2016-02-12 16:00:36 +00:00
* /
PIXI . DisplayObject . prototype . generateTexture = function ( resolution , scaleMode , renderer )
{
var bounds = this . getLocalBounds ( ) ;
var renderTexture = new PIXI . RenderTexture ( bounds . width | 0 , bounds . height | 0 , renderer , scaleMode , resolution ) ;
PIXI . DisplayObject . _tempMatrix . tx = - bounds . x ;
PIXI . DisplayObject . _tempMatrix . ty = - bounds . y ;
renderTexture . render ( this , PIXI . DisplayObject . _tempMatrix ) ;
return renderTexture ;
} ;
/ * *
* Generates and updates the cached sprite for this object .
*
* @ method updateCache
* /
PIXI . DisplayObject . prototype . updateCache = function ( )
{
this . _generateCachedSprite ( ) ;
} ;
/ * *
* 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
* /
PIXI . DisplayObject . prototype . toGlobal = function ( position )
{
// don't need to u[date the lot
this . displayObjectUpdateTransform ( ) ;
return this . worldTransform . apply ( position ) ;
} ;
/ * *
* Calculates the local position of the display object relative to another point
*
* @ method toLocal
* @ 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
* /
PIXI . DisplayObject . prototype . toLocal = function ( position , from )
{
if ( from )
{
position = from . toGlobal ( position ) ;
}
// don't need to u[date the lot
this . displayObjectUpdateTransform ( ) ;
return this . worldTransform . applyInverse ( position ) ;
} ;
/ * *
* Internal method .
*
* @ method _renderCachedSprite
* @ param renderSession { Object } The render session
* @ private
* /
PIXI . DisplayObject . prototype . _renderCachedSprite = function ( renderSession )
{
this . _cachedSprite . worldAlpha = this . worldAlpha ;
if ( renderSession . gl )
{
PIXI . Sprite . prototype . _renderWebGL . call ( this . _cachedSprite , renderSession ) ;
}
else
{
PIXI . Sprite . prototype . _renderCanvas . call ( this . _cachedSprite , renderSession ) ;
}
} ;
/ * *
* Internal method .
*
* @ method _generateCachedSprite
* @ private
* /
PIXI . DisplayObject . prototype . _generateCachedSprite = function ( )
{
this . _cacheAsBitmap = false ;
var bounds = this . getLocalBounds ( ) ;
2016-02-17 13:27:09 +00:00
// Round it off and force non-zero dimensions
bounds . width = Math . max ( 1 , Math . ceil ( bounds . width ) ) ;
bounds . height = Math . max ( 1 , Math . ceil ( bounds . height ) ) ;
2016-02-12 16:00:36 +00:00
this . updateTransform ( ) ;
if ( ! this . _cachedSprite )
{
2016-02-17 13:27:09 +00:00
var renderTexture = new PIXI . RenderTexture ( bounds . width , bounds . height ) ;
2016-02-12 16:00:36 +00:00
this . _cachedSprite = new PIXI . Sprite ( renderTexture ) ;
this . _cachedSprite . worldTransform = this . worldTransform ;
}
else
{
2016-02-17 13:27:09 +00:00
this . _cachedSprite . texture . resize ( bounds . width , bounds . height ) ;
2016-02-12 16:00:36 +00:00
}
// Remove filters
var tempFilters = this . _filters ;
this . _filters = null ;
this . _cachedSprite . filters = tempFilters ;
// PIXI.DisplayObject._tempMatrix.identity();
PIXI . DisplayObject . _tempMatrix . tx = - bounds . x ;
PIXI . DisplayObject . _tempMatrix . ty = - bounds . y ;
this . _cachedSprite . texture . render ( this , PIXI . DisplayObject . _tempMatrix , true ) ;
2016-02-17 13:27:09 +00:00
this . _cachedSprite . anchor . x = - ( bounds . x / bounds . width ) ;
this . _cachedSprite . anchor . y = - ( bounds . y / bounds . height ) ;
2016-02-12 16:00:36 +00:00
this . _filters = tempFilters ;
this . _cacheAsBitmap = true ;
} ;
/ * *
* Destroys the cached sprite .
*
* @ method _destroyCachedSprite
* @ private
* /
PIXI . DisplayObject . prototype . _destroyCachedSprite = function ( )
{
if ( ! this . _cachedSprite ) return ;
this . _cachedSprite . texture . destroy ( true ) ;
// TODO could be object pooled!
this . _cachedSprite = null ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ private
* /
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
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . DisplayObject . prototype . _renderCanvas = function ( renderSession )
{
// OVERWRITE;
// this line is just here to pass jshinting :)
renderSession = renderSession ;
} ;
/ * *
* 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
* @ type Array ( DisplayObject )
* @ readOnly
* /
this . children = [ ] ;
} ;
// constructor
PIXI . DisplayObjectContainer . prototype = Object . create ( PIXI . DisplayObject . prototype ) ;
PIXI . DisplayObjectContainer . prototype . constructor = PIXI . DisplayObjectContainer ;
/ * *
* 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 ) {
var width = this . getLocalBounds ( ) . width ;
if ( width !== 0 )
{
this . scale . x = value / width ;
}
else
{
this . scale . x = 1 ;
}
this . _width = value ;
}
} ) ;
/ * *
* 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 ) {
var height = this . getLocalBounds ( ) . height ;
if ( height !== 0 )
{
this . scale . y = value / height ;
}
else
{
this . scale . y = 1 ;
}
this . _height = value ;
}
} ) ;
/ * *
* Adds a child to the container .
*
* @ method addChild
* @ param child { DisplayObject } The DisplayObject to add to the container
* @ return { DisplayObject } The child that was added .
* /
PIXI . DisplayObjectContainer . prototype . addChild = function ( child )
{
return this . addChildAt ( child , this . children . length ) ;
} ;
/ * *
* 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
* @ return { DisplayObject } The child that was added .
* /
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 ) ;
return child ;
}
else
{
throw new Error ( child + 'addChildAt: The index ' + index + ' supplied is out of bounds ' + this . children . length ) ;
}
} ;
/ * *
* Swaps the position of 2 Display Objects within this container .
*
* @ method swapChildren
* @ param child { DisplayObject }
* @ param child2 { DisplayObject }
* /
PIXI . DisplayObjectContainer . prototype . swapChildren = function ( child , child2 )
{
if ( child === child2 ) {
return ;
}
var index1 = this . getChildIndex ( child ) ;
var index2 = this . getChildIndex ( child2 ) ;
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 ;
} ;
/ * *
* 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
} ;
/ * *
* Returns the child at the specified index
*
* @ method getChildAt
* @ param index { Number } The index to get the child from
* @ return { DisplayObject } The child at the given index , if any .
* /
PIXI . DisplayObjectContainer . prototype . getChildAt = function ( index )
{
if ( index < 0 || index >= this . children . length )
{
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' ) ;
}
return this . children [ index ] ;
} ;
/ * *
* Removes a child from the container .
*
* @ method removeChild
* @ param child { DisplayObject } The DisplayObject to remove
* @ return { DisplayObject } The child that was removed .
* /
PIXI . DisplayObjectContainer . prototype . removeChild = function ( child )
{
var index = this . children . indexOf ( child ) ;
if ( index === - 1 ) return ;
return this . removeChildAt ( index ) ;
} ;
/ * *
* Removes a child from the specified index position .
*
* @ method removeChildAt
* @ param index { Number } The index to get the child from
* @ return { DisplayObject } The child that was removed .
* /
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 ;
} ;
/ * *
* Removes all children from this container that are within the begin and end indexes .
*
* @ method removeChildren
* @ param beginIndex { Number } The beginning position . Default value is 0.
* @ param endIndex { Number } The ending position . Default value is size of the container .
* /
PIXI . DisplayObjectContainer . prototype . removeChildren = function ( beginIndex , endIndex )
{
var begin = beginIndex || 0 ;
var end = typeof endIndex === 'number' ? endIndex : this . children . length ;
var range = end - begin ;
if ( range > 0 && range <= end )
{
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 ;
}
else if ( range === 0 && this . children . length === 0 )
{
return [ ] ;
}
else
{
throw new Error ( 'removeChildren: Range Error, numeric values are outside the acceptable range' ) ;
}
} ;
/ *
* Updates the transform on all children of this container for rendering
*
* @ method updateTransform
* @ private
* /
PIXI . DisplayObjectContainer . prototype . updateTransform = function ( )
{
if ( ! this . visible )
{
return ;
}
this . displayObjectUpdateTransform ( ) ;
if ( this . _cacheAsBitmap )
{
return ;
}
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . updateTransform ( ) ;
}
} ;
// performance increase to avoid using call.. (10x faster)
PIXI . DisplayObjectContainer . prototype . displayObjectContainerUpdateTransform = PIXI . DisplayObjectContainer . prototype . updateTransform ;
/ * *
* Retrieves the bounds of the displayObjectContainer as a rectangle . The bounds calculation takes all visible children into consideration .
*
* @ method getBounds
* @ return { Rectangle } The rectangular bounding area
* /
PIXI . DisplayObjectContainer . prototype . getBounds = function ( )
{
2016-04-14 12:23:44 +00:00
if ( this . children . length === 0 )
{
return PIXI . EmptyRectangle ;
}
2016-02-12 16:00:36 +00:00
var minX = Infinity ;
var minY = Infinity ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var childBounds ;
var childMaxX ;
var childMaxY ;
var childVisible = false ;
2016-04-14 12:23:44 +00:00
for ( var i = 0 ; i < this . children . length ; i ++ )
2016-02-12 16:00:36 +00:00
{
var child = this . children [ i ] ;
2016-04-14 12:23:44 +00:00
if ( ! child . visible )
{
continue ;
}
2016-02-12 16:00:36 +00:00
childVisible = true ;
childBounds = this . children [ i ] . getBounds ( ) ;
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 ;
}
2016-04-14 12:23:44 +00:00
if ( ! childVisible )
{
2016-02-12 16:00:36 +00:00
return PIXI . EmptyRectangle ;
2016-04-14 12:23:44 +00:00
}
2016-02-12 16:00:36 +00:00
var bounds = this . _bounds ;
bounds . x = minX ;
bounds . y = minY ;
bounds . width = maxX - minX ;
bounds . height = maxY - minY ;
return bounds ;
} ;
/ * *
* 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
* /
PIXI . DisplayObjectContainer . prototype . getLocalBounds = function ( )
{
var matrixCache = this . worldTransform ;
this . worldTransform = PIXI . identityMatrix ;
2016-04-14 12:23:44 +00:00
for ( var i = 0 ; i < this . children . length ; i ++ )
2016-02-12 16:00:36 +00:00
{
this . children [ i ] . updateTransform ( ) ;
}
var bounds = this . getBounds ( ) ;
this . worldTransform = matrixCache ;
2016-04-14 12:23:44 +00:00
for ( i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . updateTransform ( ) ;
}
2016-02-12 16:00:36 +00:00
return bounds ;
} ;
/ * *
* Sets the containers Stage reference . This is the Stage that this object , and all of its children , is connected to .
*
* @ 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 ;
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . setStageReference ( stage )
}
} ;
/ * *
* Removes the current stage reference from the container and all of its children .
*
* @ method removeStageReference
* /
PIXI . DisplayObjectContainer . prototype . removeStageReference = function ( )
{
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . removeStageReference ( ) ;
}
this . stage = null ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . DisplayObjectContainer . prototype . _renderWebGL = function ( renderSession )
{
if ( ! this . visible || this . alpha <= 0 ) return ;
if ( this . _cacheAsBitmap )
{
this . _renderCachedSprite ( renderSession ) ;
return ;
}
var i ;
if ( this . _mask || this . _filters )
{
// 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 ) ;
}
if ( this . _mask )
{
renderSession . spriteBatch . stop ( ) ;
renderSession . maskManager . pushMask ( this . mask , renderSession ) ;
renderSession . spriteBatch . start ( ) ;
}
// simple render children!
for ( i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
renderSession . spriteBatch . stop ( ) ;
if ( this . _mask ) renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
if ( this . _filters ) renderSession . filterManager . popFilter ( ) ;
renderSession . spriteBatch . start ( ) ;
}
else
{
// simple render children!
for ( i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
}
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
* @ param renderSession { RenderSession }
* @ 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 )
{
renderSession . maskManager . pushMask ( this . _mask , renderSession ) ;
}
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderCanvas ( renderSession ) ;
}
if ( this . _mask )
{
renderSession . maskManager . popMask ( renderSession ) ;
}
} ;
/ * *
* @ 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
*
* A sprite can be created directly from an image like this :
* var sprite = new PIXI . Sprite . fromImage ( 'assets/image.png' ) ;
* 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
* Setting than anchor to 0.5 , 0.5 means the textures origin is centered
* 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 || PIXI . Texture . emptyTexture ;
/ * *
* 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 ;
/ * *
* The tint applied to the sprite . This is a hex value . A value of 0xFFFFFF will remove any tint effect .
*
* @ property tint
* @ type Number
* @ default 0xFFFFFF
* /
this . tint = 0xFFFFFF ;
/ * *
* The tint applied to the sprite . This is a hex value . A value of 0xFFFFFF will remove any tint effect .
*
* @ property cachedTint
* @ private
* @ type Number
* @ default - 1
* /
this . cachedTint = - 1 ;
/ * *
* A canvas that contains the tinted version of the Sprite ( in Canvas mode , WebGL doesn ' t populate this )
*
* @ property tintedTexture
* @ type Canvas
* @ default null
* /
this . tintedTexture = null ;
/ * *
* The blend mode to be applied to the sprite . Set to PIXI . blendModes . NORMAL to remove any blend mode .
*
* Warning : You cannot have a blend mode and a filter active on the same Sprite . Doing so will render the sprite invisible .
*
* @ property blendMode
* @ type Number
* @ default PIXI . blendModes . NORMAL ;
* /
this . blendMode = PIXI . blendModes . NORMAL ;
/ * *
* The shader that will be used to render the texture to the stage . Set to null to remove a current shader .
*
* @ property shader
* @ type AbstractFilter
* @ default null
* /
this . shader = null ;
if ( this . texture . baseTexture . hasLoaded )
{
this . onTextureUpdate ( ) ;
}
this . renderable = true ;
} ;
// 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 . Be warned that this doesn ' t remove or destroy the previous
* texture this Sprite was using .
*
* @ method setTexture
* @ param texture { Texture } The PIXI texture that is displayed by the sprite
* @ param [ destroy = false ] { boolean } Call Texture . destroy on the current texture before replacing it with the new one ?
* /
PIXI . Sprite . prototype . setTexture = function ( texture , destroyBase )
{
if ( destroyBase !== undefined )
{
this . texture . baseTexture . destroy ( ) ;
}
// Over-ridden by loadTexture as needed
this . texture . baseTexture . skipRender = false ;
this . texture = texture ;
this . texture . valid = true ;
2016-04-14 12:23:44 +00:00
this . cachedTint = - 1 ;
2016-02-12 16:00:36 +00:00
} ;
/ * *
* 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 ;
} ;
/ * *
2016-04-14 12:23:44 +00:00
* Returns the bounds of the Sprite as a rectangle .
* The bounds calculation takes the worldTransform into account .
*
* It is important to note that the transform is not updated when you call this method .
* So if this Sprite is the child of a Display Object which has had its transform
* updated since the last render pass , those changes will not yet have been applied
* to this Sprites worldTransform . If you need to ensure that all parent transforms
* are factored into this getBounds operation then you should call ` updateTransform `
* on the root most object in this Sprites display list first .
2016-02-12 16:00:36 +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 ;
var b = worldTransform . b ;
var c = worldTransform . c ;
var d = worldTransform . d ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var minX = Infinity ;
var minY = Infinity ;
if ( b === 0 && c === 0 )
{
// scale may be negative!
if ( a < 0 )
{
a *= - 1 ;
var temp = w0 ;
w0 = - w1 ;
w1 = - temp ;
}
if ( d < 0 )
{
d *= - 1 ;
var temp = h0 ;
h0 = - h1 ;
h1 = - temp ;
}
// 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 ;
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 ;
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ param { Matrix } [ matrix ] - Optional matrix . If provided the Display Object will be rendered using this matrix , otherwise it will use its worldTransform .
* @ private
* /
PIXI . Sprite . prototype . _renderWebGL = function ( renderSession , matrix )
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if ( ! this . visible || this . alpha <= 0 || ! this . renderable ) return ;
// They provided an alternative rendering matrix, so use it
var wt = this . worldTransform ;
if ( matrix )
{
wt = matrix ;
}
// A quick check to see if this element has a mask or a filter.
if ( this . _mask || this . _filters )
{
var spriteBatch = renderSession . spriteBatch ;
// 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 ) ;
}
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 ( var i = 0 ; i < this . children . length ; 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 ( ) ;
if ( this . _mask ) renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
if ( this . _filters ) renderSession . filterManager . popFilter ( ) ;
spriteBatch . start ( ) ;
}
else
{
renderSession . spriteBatch . render ( this ) ;
// Render children!
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession , wt ) ;
}
}
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
* @ param renderSession { RenderSession }
* @ param { Matrix } [ matrix ] - Optional matrix . If provided the Display Object will be rendered using this matrix , otherwise it will use its worldTransform .
* @ private
* /
PIXI . Sprite . prototype . _renderCanvas = function ( renderSession , matrix )
{
// If the sprite is not visible or the alpha is 0 then no need to render this element
if ( ! this . visible || this . alpha === 0 || ! this . renderable || this . texture . crop . width <= 0 || this . texture . crop . height <= 0 )
{
return ;
}
var wt = this . worldTransform ;
// If they provided an alternative rendering matrix then use it
if ( matrix )
{
wt = matrix ;
}
if ( this . blendMode !== renderSession . currentBlendMode )
{
renderSession . currentBlendMode = this . blendMode ;
renderSession . context . globalCompositeOperation = PIXI . blendModesCanvas [ renderSession . currentBlendMode ] ;
}
if ( this . _mask )
{
renderSession . maskManager . pushMask ( this . _mask , renderSession ) ;
}
// Ignore null sources
if ( this . texture . valid )
{
var resolution = this . texture . baseTexture . resolution / renderSession . resolution ;
renderSession . context . globalAlpha = this . worldAlpha ;
2016-06-02 22:23:23 +00:00
// If smoothingEnabled is supported and we need to change the smoothing property for this texture
2016-02-12 16:00:36 +00:00
if ( renderSession . smoothProperty && renderSession . scaleMode !== this . texture . baseTexture . scaleMode )
{
renderSession . scaleMode = this . texture . baseTexture . scaleMode ;
renderSession . context [ renderSession . smoothProperty ] = ( renderSession . scaleMode === PIXI . scaleModes . LINEAR ) ;
}
// 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 ;
2016-04-22 13:45:11 +00:00
var tx = ( wt . tx * renderSession . resolution ) + renderSession . shakeX ;
var ty = ( wt . ty * renderSession . resolution ) + renderSession . shakeY ;
2016-02-12 16:00:36 +00:00
// Allow for pixel rounding
if ( renderSession . roundPixels )
{
2016-04-22 13:45:11 +00:00
renderSession . context . setTransform ( wt . a , wt . b , wt . c , wt . d , tx | 0 , ty | 0 ) ;
2016-02-12 16:00:36 +00:00
dx |= 0 ;
dy |= 0 ;
}
else
{
2016-04-22 13:45:11 +00:00
renderSession . context . setTransform ( wt . a , wt . b , wt . c , wt . d , tx , ty ) ;
2016-02-12 16:00:36 +00:00
}
var cw = this . texture . crop . width ;
var ch = this . texture . crop . height ;
dx /= resolution ;
dy /= resolution ;
if ( this . tint !== 0xFFFFFF )
{
if ( this . texture . requiresReTint || this . cachedTint !== this . tint )
{
this . tintedTexture = PIXI . CanvasTinter . getTintedTexture ( this , this . tint ) ;
this . cachedTint = this . tint ;
2016-05-19 11:36:51 +00:00
this . texture . requiresReTint = false ;
2016-02-12 16:00:36 +00:00
}
renderSession . context . drawImage ( this . tintedTexture , 0 , 0 , cw , ch , dx , dy , cw / resolution , ch / resolution ) ;
}
else
{
var cx = this . texture . crop . x ;
var cy = this . texture . crop . y ;
renderSession . context . drawImage ( this . texture . baseTexture . source , cx , cy , cw , ch , dx , dy , cw / resolution , ch / resolution ) ;
}
}
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderCanvas ( renderSession ) ;
}
if ( this . _mask )
{
renderSession . maskManager . popMask ( renderSession ) ;
}
} ;
// 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/
* /
/ * *
* The SpriteBatch class is a really fast version of the DisplayObjectContainer
* built solely for speed , so use when you need a lot of sprites or particles .
* And it ' s extremely easy to use :
var container = new PIXI . SpriteBatch ( ) ;
stage . addChild ( container ) ;
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 }
* /
PIXI . SpriteBatch = function ( texture )
{
PIXI . DisplayObjectContainer . call ( this ) ;
this . textureThing = texture ;
this . ready = false ;
} ;
PIXI . SpriteBatch . prototype = Object . create ( PIXI . DisplayObjectContainer . prototype ) ;
PIXI . SpriteBatch . prototype . constructor = PIXI . SpriteBatch ;
/ *
* 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 ( )
{
// TODO don't need to!
this . displayObjectUpdateTransform ( ) ;
// PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . SpriteBatch . prototype . _renderWebGL = function ( renderSession )
{
if ( ! this . visible || this . alpha <= 0 || ! this . children . length ) return ;
if ( ! this . ready )
{
this . initWebGL ( renderSession . gl ) ;
}
if ( this . fastSpriteBatch . gl !== renderSession . gl )
{
this . fastSpriteBatch . setContext ( renderSession . gl ) ;
}
renderSession . spriteBatch . stop ( ) ;
renderSession . shaderManager . setShader ( renderSession . shaderManager . fastShader ) ;
this . fastSpriteBatch . begin ( this , renderSession ) ;
this . fastSpriteBatch . render ( this ) ;
renderSession . spriteBatch . start ( ) ;
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . SpriteBatch . prototype . _renderCanvas = function ( renderSession )
{
if ( ! this . visible || this . alpha <= 0 || ! this . children . length ) return ;
var context = renderSession . context ;
context . globalAlpha = this . worldAlpha ;
this . displayObjectUpdateTransform ( ) ;
var transform = this . worldTransform ;
var isRotated = true ;
for ( var i = 0 ; i < this . children . length ; i ++ )
{
var child = this . children [ i ] ;
if ( ! child . visible ) continue ;
var texture = child . texture ;
var frame = texture . frame ;
context . globalAlpha = this . worldAlpha * child . alpha ;
if ( child . rotation % ( Math . PI * 2 ) === 0 )
{
if ( isRotated )
{
context . setTransform ( transform . a , transform . b , transform . c , transform . d , transform . tx , transform . ty ) ;
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 ,
2016-04-22 13:45:11 +00:00
( ( child . anchor . x ) * ( - frame . width * child . scale . x ) + child . position . x + 0.5 + renderSession . shakeX ) | 0 ,
( ( child . anchor . y ) * ( - frame . height * child . scale . y ) + child . position . y + 0.5 + renderSession . shakeY ) | 0 ,
2016-02-12 16:00:36 +00:00
frame . width * child . scale . x ,
frame . height * child . scale . y ) ;
}
else
{
if ( ! isRotated ) isRotated = true ;
child . displayObjectUpdateTransform ( ) ;
var childTransform = child . worldTransform ;
2016-04-22 13:45:11 +00:00
var tx = ( childTransform . tx * renderSession . resolution ) + renderSession . shakeX ;
var ty = ( childTransform . ty * renderSession . resolution ) + renderSession . shakeY ;
2016-02-12 16:00:36 +00:00
// allow for trimming
if ( renderSession . roundPixels )
{
2016-04-22 13:45:11 +00:00
context . setTransform ( childTransform . a , childTransform . b , childTransform . c , childTransform . d , tx | 0 , ty | 0 ) ;
2016-02-12 16:00:36 +00:00
}
else
{
2016-04-22 13:45:11 +00:00
context . setTransform ( childTransform . a , childTransform . b , childTransform . c , childTransform . d , tx , ty ) ;
2016-02-12 16:00:36 +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 ) ;
}
}
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* 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 ) ;
} ;
/ * *
* Checks whether the Canvas BlendModes are supported by the current browser for drawImage
*
* @ method canUseNewCanvasBlendModes
* @ return { Boolean } whether they are supported
* /
PIXI . canUseNewCanvasBlendModes = function ( )
{
if ( document === undefined ) return false ;
var pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/' ;
var pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==' ;
var magenta = new Image ( ) ;
magenta . src = pngHead + 'AP804Oa6' + pngEnd ;
var yellow = new Image ( ) ;
yellow . src = pngHead + '/wCKxvRF' + pngEnd ;
var canvas = PIXI . CanvasPool . create ( this , 6 , 1 ) ;
var context = canvas . getContext ( '2d' ) ;
context . globalCompositeOperation = 'multiply' ;
context . drawImage ( magenta , 0 , 0 ) ;
context . drawImage ( yellow , 2 , 0 ) ;
if ( ! context . getImageData ( 2 , 0 , 1 , 1 ) )
{
return false ;
}
var data = context . getImageData ( 2 , 0 , 1 , 1 ) . data ;
PIXI . CanvasPool . remove ( this ) ;
return ( data [ 0 ] === 255 && data [ 1 ] === 0 && data [ 2 ] === 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 ;
}
} ;
/ * *
* checks if the given width and height make a power of two texture
* @ method isPowerOfTwo
* @ param width { Number }
* @ param height { Number }
* @ return { Boolean }
* /
PIXI . isPowerOfTwo = function ( width , height )
{
return ( width > 0 && ( width & ( width - 1 ) ) === 0 && height > 0 && ( height & ( height - 1 ) ) === 0 ) ;
} ;
/ * *
* @ author Richard Davey < rich @ photonstorm . com >
2016-04-14 12:23:44 +00:00
* @ copyright 2016 Photon Storm Ltd .
2016-02-12 16:00:36 +00:00
* @ license { @ link https : //github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
* /
/ * *
* The CanvasPool is a global static object that allows Pixi and Phaser to pool canvas DOM elements .
*
* @ class CanvasPool
* @ static
* /
PIXI . CanvasPool = {
/ * *
* Creates a new Canvas DOM element , or pulls one from the pool if free .
*
* @ method create
* @ static
* @ param parent { any } The parent of the canvas element .
* @ param width { number } The width of the canvas element .
* @ param height { number } The height of the canvas element .
* @ return { HTMLCanvasElement } The canvas element .
* /
create : function ( parent , width , height ) {
var idx = PIXI . CanvasPool . getFirst ( ) ;
var canvas ;
if ( idx === - 1 )
{
var container = {
parent : parent ,
canvas : document . createElement ( 'canvas' )
}
PIXI . CanvasPool . pool . push ( container ) ;
canvas = container . canvas ;
}
else
{
PIXI . CanvasPool . pool [ idx ] . parent = parent ;
canvas = PIXI . CanvasPool . pool [ idx ] . canvas ;
}
if ( width !== undefined )
{
canvas . width = width ;
canvas . height = height ;
}
return canvas ;
} ,
/ * *
* Gets the first free canvas index from the pool .
*
* @ method getFirst
* @ static
* @ return { number }
* /
getFirst : function ( ) {
var pool = PIXI . CanvasPool . pool ;
for ( var i = 0 ; i < pool . length ; i ++ )
{
if ( pool [ i ] . parent === null )
{
return i ;
}
}
return - 1 ;
} ,
/ * *
* Removes the parent from a canvas element from the pool , freeing it up for re - use .
*
* @ method remove
* @ param parent { any } The parent of the canvas element .
* @ static
* /
remove : function ( parent ) {
var pool = PIXI . CanvasPool . pool ;
for ( var i = 0 ; i < pool . length ; i ++ )
{
if ( pool [ i ] . parent === parent )
{
pool [ i ] . parent = null ;
}
}
} ,
/ * *
* Removes the parent from a canvas element from the pool , freeing it up for re - use .
*
* @ method removeByCanvas
* @ param canvas { HTMLCanvasElement } The canvas element to remove
* @ static
* /
removeByCanvas : function ( canvas ) {
var pool = PIXI . CanvasPool . pool ;
for ( var i = 0 ; i < pool . length ; i ++ )
{
if ( pool [ i ] . canvas === canvas )
{
pool [ i ] . parent = null ;
}
}
} ,
/ * *
* Gets the total number of used canvas elements in the pool .
*
* @ method getTotal
* @ static
* @ return { number } The number of in - use ( parented ) canvas elements in the pool .
* /
getTotal : function ( ) {
var pool = PIXI . CanvasPool . pool ;
var c = 0 ;
for ( var i = 0 ; i < pool . length ; i ++ )
{
if ( pool [ i ] . parent !== null )
{
c ++ ;
}
}
return c ;
} ,
/ * *
* Gets the total number of free canvas elements in the pool .
*
* @ method getFree
* @ static
* @ return { number } The number of free ( un - parented ) canvas elements in the pool .
* /
getFree : function ( ) {
var pool = PIXI . CanvasPool . pool ;
var c = 0 ;
for ( var i = 0 ; i < pool . length ; i ++ )
{
if ( pool [ i ] . parent === null )
{
c ++ ;
}
}
return c ;
}
} ;
/ * *
* The pool into which the canvas dom elements are placed .
*
* @ property pool
* @ type Array
* @ static
* /
PIXI . CanvasPool . pool = [ ] ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ method initDefaultShaders
* @ static
* @ private
* /
PIXI . initDefaultShaders = function ( )
{
} ;
/ * *
* @ method CompileVertexShader
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ return { Any }
* /
PIXI . CompileVertexShader = function ( gl , shaderSrc )
{
return PIXI . _CompileShader ( gl , shaderSrc , gl . VERTEX _SHADER ) ;
} ;
/ * *
* @ method CompileFragmentShader
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ return { Any }
* /
PIXI . CompileFragmentShader = function ( gl , shaderSrc )
{
return PIXI . _CompileShader ( gl , shaderSrc , gl . FRAGMENT _SHADER ) ;
} ;
/ * *
* @ method _CompileShader
* @ static
* @ private
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param shaderSrc { Array }
* @ param shaderType { Number }
* @ return { Any }
* /
PIXI . _CompileShader = function ( gl , shaderSrc , shaderType )
{
var src = shaderSrc ;
if ( Array . isArray ( shaderSrc ) )
{
src = shaderSrc . join ( "\n" ) ;
}
var shader = gl . createShader ( shaderType ) ;
gl . shaderSource ( shader , src ) ;
gl . compileShader ( shader ) ;
if ( ! gl . getShaderParameter ( shader , gl . COMPILE _STATUS ) )
{
window . console . log ( gl . getShaderInfoLog ( shader ) ) ;
return null ;
}
return shader ;
} ;
/ * *
* @ method compileProgram
* @ static
* @ param gl { WebGLContext } the current WebGL drawing context
* @ param vertexSrc { Array }
* @ param fragmentSrc { Array }
* @ return { Any }
* /
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 ) ;
if ( ! gl . getProgramParameter ( shaderProgram , gl . LINK _STATUS ) )
{
2016-05-19 11:36:51 +00:00
window . console . log ( gl . getProgramInfoLog ( shaderProgram ) ) ;
2016-02-12 16:00:36 +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
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . PixiShader = function ( gl )
{
/ * *
* @ property _UID
* @ type Number
* @ private
* /
this . _UID = PIXI . _UID ++ ;
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
* The WebGL program .
* @ property program
* @ type Any
* /
this . program = null ;
/ * *
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision lowp float;' ,
'varying vec2 vTextureCoord;' ,
'varying vec4 vColor;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;' ,
'}'
] ;
/ * *
* A local texture counter for multi - texture shaders .
* @ property textureCount
* @ type Number
* /
this . textureCount = 0 ;
/ * *
* 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
* /
this . attributes = [ ] ;
this . init ( ) ;
} ;
PIXI . PixiShader . prototype . constructor = PIXI . PixiShader ;
/ * *
* Initialises the shader .
*
* @ method init
* /
PIXI . PixiShader . prototype . init = function ( )
{
var gl = this . gl ;
var program = PIXI . compileProgram ( gl , this . vertexSrc || PIXI . PixiShader . defaultVertexSrc , 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 . 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.
// 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
// 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 .
*
* 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 ] ) ;
if ( uniform . value . baseTexture . _dirty [ gl . id ] )
{
PIXI . instances [ gl . id ] . updateTexture ( uniform . value . baseTexture ) ;
}
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));
gl . uniform1i ( uniform . uniformLocation , this . textureCount ) ;
this . textureCount ++ ;
}
else
{
this . initSampler2D ( uniform ) ;
}
}
}
} ;
/ * *
* Destroys the shader .
*
* @ method destroy
* /
PIXI . PixiShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attributes = null ;
} ;
/ * *
* The Default Vertex shader source .
*
* @ property defaultVertexSrc
* @ type String
* /
PIXI . PixiShader . defaultVertexSrc = [
'attribute vec2 aVertexPosition;' ,
'attribute vec2 aTextureCoord;' ,
'attribute vec4 aColor;' ,
'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;' ,
' vColor = vec4(aColor.rgb * aColor.a, aColor.a);' ,
'}'
] ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class PixiFastShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . PixiFastShader = function ( gl )
{
/ * *
* @ property _UID
* @ type Number
* @ private
* /
this . _UID = PIXI . _UID ++ ;
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
* The WebGL program .
* @ property program
* @ type Any
* /
this . program = null ;
/ * *
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision lowp float;' ,
'varying vec2 vTextureCoord;' ,
'varying float vColor;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;' ,
'}'
] ;
/ * *
* The vertex shader .
* @ property vertexSrc
* @ type Array
* /
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;' ,
'}'
] ;
/ * *
* A local texture counter for multi - texture shaders .
* @ property textureCount
* @ type Number
* /
this . textureCount = 0 ;
this . init ( ) ;
} ;
PIXI . PixiFastShader . prototype . constructor = PIXI . PixiFastShader ;
/ * *
* Initialises the shader .
*
* @ method init
* /
PIXI . PixiFastShader . 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 . 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' ) ;
// 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 ] ;
// End worst hack eva //
this . program = program ;
} ;
/ * *
* Destroys the shader .
*
* @ 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
* /
/ * *
* @ class StripShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . StripShader = function ( gl )
{
/ * *
* @ property _UID
* @ type Number
* @ private
* /
this . _UID = PIXI . _UID ++ ;
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
* The WebGL program .
* @ property program
* @ type Any
* /
this . program = null ;
/ * *
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision mediump float;' ,
'varying vec2 vTextureCoord;' ,
// 'varying float vColor;',
'uniform float alpha;' ,
'uniform sampler2D uSampler;' ,
'void main(void) {' ,
' gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * alpha;' ,
// ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);',//gl_FragColor * alpha;',
'}'
] ;
/ * *
* The vertex shader .
* @ property vertexSrc
* @ type Array
* /
this . vertexSrc = [
'attribute vec2 aVertexPosition;' ,
'attribute vec2 aTextureCoord;' ,
'uniform mat3 translationMatrix;' ,
'uniform vec2 projectionVector;' ,
'uniform vec2 offsetVector;' ,
// 'uniform float alpha;',
// 'uniform vec3 tint;',
'varying vec2 vTextureCoord;' ,
// '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);' ,
' vTextureCoord = aTextureCoord;' ,
// ' vColor = aColor * vec4(tint * alpha, alpha);',
'}'
] ;
this . init ( ) ;
} ;
PIXI . StripShader . prototype . constructor = PIXI . StripShader ;
/ * *
* Initialises the shader .
*
* @ method init
* /
PIXI . StripShader . 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 . 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' ) ;
this . attributes = [ this . aVertexPosition , this . aTextureCoord ] ;
this . translationMatrix = gl . getUniformLocation ( program , 'translationMatrix' ) ;
this . alpha = gl . getUniformLocation ( program , 'alpha' ) ;
this . program = program ;
} ;
/ * *
* Destroys the shader .
*
* @ method destroy
* /
PIXI . StripShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attribute = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class PrimitiveShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . PrimitiveShader = function ( gl )
{
/ * *
* @ property _UID
* @ type Number
* @ private
* /
this . _UID = PIXI . _UID ++ ;
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
* The WebGL program .
* @ property program
* @ type Any
* /
this . program = null ;
/ * *
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision mediump float;' ,
'varying vec4 vColor;' ,
'void main(void) {' ,
' gl_FragColor = vColor;' ,
'}'
] ;
/ * *
* The vertex shader .
* @ 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 float flipY;' ,
'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 * -flipY) + flipY , 0.0, 1.0);' ,
' vColor = aColor * vec4(tint * alpha, alpha);' ,
'}'
] ;
this . init ( ) ;
} ;
PIXI . PrimitiveShader . prototype . constructor = PIXI . PrimitiveShader ;
/ * *
* Initialises the shader .
*
* @ 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' ) ;
this . flipY = gl . getUniformLocation ( program , 'flipY' ) ;
// 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 ;
} ;
/ * *
* Destroys the shader .
*
* @ method destroy
* /
PIXI . PrimitiveShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attributes = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class ComplexPrimitiveShader
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . ComplexPrimitiveShader = function ( gl )
{
/ * *
* @ property _UID
* @ type Number
* @ private
* /
this . _UID = PIXI . _UID ++ ;
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
/ * *
* The WebGL program .
* @ property program
* @ type Any
* /
this . program = null ;
/ * *
* The fragment shader .
* @ property fragmentSrc
* @ type Array
* /
this . fragmentSrc = [
'precision mediump float;' ,
'varying vec4 vColor;' ,
'void main(void) {' ,
' gl_FragColor = vColor;' ,
'}'
] ;
/ * *
* The vertex shader .
* @ 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;' ,
'uniform float flipY;' ,
'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 * -flipY) + flipY , 0.0, 1.0);' ,
' vColor = vec4(color * alpha * tint, alpha);' , //" * vec4(tint * alpha, alpha);',
'}'
] ;
this . init ( ) ;
} ;
PIXI . ComplexPrimitiveShader . prototype . constructor = PIXI . ComplexPrimitiveShader ;
/ * *
* Initialises the shader .
*
* @ 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' ) ;
this . flipY = gl . getUniformLocation ( program , 'flipY' ) ;
// 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 ;
} ;
/ * *
* Destroys the shader .
*
* @ method destroy
* /
PIXI . ComplexPrimitiveShader . prototype . destroy = function ( )
{
this . gl . deleteProgram ( this . program ) ;
this . uniforms = null ;
this . gl = null ;
this . attribute = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
PIXI . glContexts = [ ] ; // this is where we store the webGL contexts for easy access.
PIXI . instances = [ ] ;
/ * *
* 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 : )
*
* @ class WebGLRenderer
* @ constructor
* @ param game { Phaser . Game } A reference to the Phaser Game instance
* /
PIXI . WebGLRenderer = function ( game ) {
/ * *
* @ property { Phaser . Game } game - A reference to the Phaser Game instance .
* /
this . game = game ;
if ( ! PIXI . defaultRenderer )
{
PIXI . defaultRenderer = this ;
}
/ * *
* @ property type
* @ type Number
* /
this . type = PIXI . WEBGL _RENDERER ;
/ * *
* The resolution of the renderer
*
* @ property resolution
* @ type Number
* @ default 1
* /
this . resolution = game . resolution ;
/ * *
* Whether the render view is transparent
*
* @ property transparent
* @ type Boolean
* /
this . transparent = game . transparent ;
/ * *
* Whether the render view should be resized automatically
*
* @ property autoResize
* @ type Boolean
* /
this . autoResize = false ;
/ * *
* The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering .
*
* @ property preserveDrawingBuffer
* @ type Boolean
* /
this . preserveDrawingBuffer = game . preserveDrawingBuffer ;
/ * *
* 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 = game . clearBeforeRender ;
/ * *
* The width of the canvas view
*
* @ property width
* @ type Number
* /
this . width = game . width ;
/ * *
* The height of the canvas view
*
* @ property height
* @ type Number
* /
this . height = game . height ;
/ * *
* The canvas element that everything is drawn to
*
* @ property view
* @ type HTMLCanvasElement
* /
this . view = game . canvas ;
/ * *
* @ property _contextOptions
* @ type Object
* @ private
* /
this . _contextOptions = {
alpha : this . transparent ,
antialias : game . antialias ,
premultipliedAlpha : this . transparent && this . transparent !== 'notMultiplied' ,
stencil : true ,
preserveDrawingBuffer : this . preserveDrawingBuffer
} ;
/ * *
* @ property projection
* @ type Point
* /
this . projection = new PIXI . Point ( ) ;
/ * *
* @ property offset
* @ type Point
* /
this . offset = new PIXI . Point ( ) ;
// time to create the render managers! each one focuses on managing a state in webGL
/ * *
* Deals with managing the shader programs and their attribs
* @ property shaderManager
* @ type WebGLShaderManager
* /
this . shaderManager = new PIXI . WebGLShaderManager ( ) ;
/ * *
* Manages the rendering of sprites
* @ property spriteBatch
* @ type WebGLSpriteBatch
* /
this . spriteBatch = new PIXI . WebGLSpriteBatch ( ) ;
/ * *
* Manages the masks using the stencil buffer
* @ property maskManager
* @ type WebGLMaskManager
* /
this . maskManager = new PIXI . WebGLMaskManager ( ) ;
/ * *
* Manages the filters
* @ property filterManager
* @ type WebGLFilterManager
* /
this . filterManager = new PIXI . WebGLFilterManager ( ) ;
/ * *
* Manages the stencil buffer
* @ property stencilManager
* @ type WebGLStencilManager
* /
this . stencilManager = new PIXI . WebGLStencilManager ( ) ;
/ * *
* Manages the blendModes
* @ property blendModeManager
* @ type WebGLBlendModeManager
* /
this . blendModeManager = new PIXI . WebGLBlendModeManager ( ) ;
/ * *
* @ property renderSession
* @ type Object
* /
this . renderSession = { } ;
// Needed?
this . renderSession . game = this . game ;
this . renderSession . gl = this . gl ;
this . renderSession . drawCount = 0 ;
this . renderSession . shaderManager = this . shaderManager ;
this . renderSession . maskManager = this . maskManager ;
this . renderSession . filterManager = this . filterManager ;
this . renderSession . blendModeManager = this . blendModeManager ;
this . renderSession . spriteBatch = this . spriteBatch ;
this . renderSession . stencilManager = this . stencilManager ;
this . renderSession . renderer = this ;
this . renderSession . resolution = this . resolution ;
// time init the context..
this . initContext ( ) ;
// map some webGL blend modes..
this . mapBlendModes ( ) ;
} ;
// constructor
PIXI . WebGLRenderer . prototype . constructor = PIXI . WebGLRenderer ;
/ * *
* @ 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 ;
PIXI . instances [ this . glContextId ] = this ;
// 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 ) ;
} ;
/ * *
* Renders the stage to its webGL view
*
* @ method render
* @ param stage { Stage } the Stage element to be rendered
* /
PIXI . WebGLRenderer . prototype . render = function ( stage )
{
// no point rendering if our context has been blown up!
if ( this . contextLost )
{
return ;
}
var gl = this . gl ;
// -- 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 ) ;
if ( this . game . clearBeforeRender )
{
gl . clearColor ( stage . _bgColor . r , stage . _bgColor . g , stage . _bgColor . b , stage . _bgColor . a ) ;
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
}
2016-04-22 13:45:11 +00:00
this . offset . x = this . game . camera . _shake . x ;
this . offset . y = this . game . camera . _shake . y ;
2016-02-12 16:00:36 +00:00
this . renderDisplayObject ( stage , this . projection ) ;
} ;
/ * *
* Renders a Display Object .
*
* @ method renderDisplayObject
* @ param displayObject { DisplayObject } The DisplayObject to render
* @ param projection { Point } The projection
* @ param buffer { Array } a standard WebGL buffer
* /
PIXI . WebGLRenderer . prototype . renderDisplayObject = function ( displayObject , projection , buffer , matrix )
{
this . renderSession . blendModeManager . setBlendMode ( PIXI . blendModes . NORMAL ) ;
// reset the render session data..
this . renderSession . drawCount = 0 ;
// make sure to flip the Y if using a render texture..
this . renderSession . flipY = buffer ? - 1 : 1 ;
// set the default projection
this . renderSession . projection = projection ;
//set the default offset
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 , matrix ) ;
// finish the sprite batch
this . spriteBatch . end ( ) ;
} ;
/ * *
* Resizes the webGL view to the specified width and height .
*
* @ 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 )
{
this . width = width * this . resolution ;
this . height = height * this . resolution ;
this . view . width = this . width ;
this . view . height = this . height ;
if ( this . autoResize ) {
this . view . style . width = this . width / this . resolution + 'px' ;
this . view . style . height = this . height / this . resolution + 'px' ;
}
this . gl . viewport ( 0 , 0 , this . width , this . height ) ;
this . projection . x = this . width / 2 / this . resolution ;
this . projection . y = - this . height / 2 / this . resolution ;
} ;
/ * *
* Updates and Creates a WebGL texture for the renderers context .
*
* @ method updateTexture
* @ param texture { Texture } the texture to update
* @ return { boolean } True if the texture was successfully bound , otherwise false .
* /
PIXI . WebGLRenderer . prototype . updateTexture = function ( texture )
{
if ( ! texture . hasLoaded )
{
return false ;
}
var gl = this . gl ;
if ( ! texture . _glTextures [ gl . id ] )
{
texture . _glTextures [ gl . id ] = gl . createTexture ( ) ;
}
gl . bindTexture ( gl . TEXTURE _2D , texture . _glTextures [ gl . id ] ) ;
gl . pixelStorei ( gl . UNPACK _PREMULTIPLY _ALPHA _WEBGL , texture . premultipliedAlpha ) ;
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED _BYTE , texture . source ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MAG _FILTER , texture . scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
if ( texture . mipmap && PIXI . isPowerOfTwo ( texture . width , texture . height ) )
{
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , texture . scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR _MIPMAP _LINEAR : gl . NEAREST _MIPMAP _NEAREST ) ;
gl . generateMipmap ( gl . TEXTURE _2D ) ;
}
else
{
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , texture . scaleMode === PIXI . scaleModes . LINEAR ? gl . LINEAR : gl . NEAREST ) ;
}
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 ) ;
}
else
{
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , gl . REPEAT ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , gl . REPEAT ) ;
}
texture . _dirty [ gl . id ] = false ;
// return texture._glTextures[gl.id];
return true ;
} ;
/ * *
* Removes everything from the renderer ( event listeners , spritebatch , etc ... )
*
* @ method destroy
* /
PIXI . WebGLRenderer . prototype . destroy = function ( )
{
PIXI . glContexts [ this . glContextId ] = null ;
this . projection = null ;
this . offset = null ;
this . shaderManager . destroy ( ) ;
this . spriteBatch . destroy ( ) ;
this . maskManager . destroy ( ) ;
this . filterManager . destroy ( ) ;
this . shaderManager = null ;
this . spriteBatch = null ;
this . maskManager = null ;
this . filterManager = null ;
this . gl = null ;
this . renderSession = null ;
PIXI . CanvasPool . remove ( this ) ;
PIXI . instances [ this . glContextId ] = null ;
PIXI . WebGLRenderer . glContextId -- ;
} ;
/ * *
* Maps Pixi blend modes to WebGL blend modes .
*
* @ method mapBlendModes
* /
PIXI . WebGLRenderer . prototype . mapBlendModes = function ( )
{
var gl = this . gl ;
if ( ! PIXI . blendModesWebGL )
{
var b = [ ] ;
var modes = PIXI . blendModes ;
b [ modes . NORMAL ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . ADD ] = [ gl . SRC _ALPHA , gl . DST _ALPHA ] ;
b [ modes . MULTIPLY ] = [ gl . DST _COLOR , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . SCREEN ] = [ gl . SRC _ALPHA , gl . ONE ] ;
b [ modes . OVERLAY ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . DARKEN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . LIGHTEN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . COLOR _DODGE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . COLOR _BURN ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . HARD _LIGHT ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . SOFT _LIGHT ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . DIFFERENCE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . EXCLUSION ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . HUE ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . SATURATION ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . COLOR ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
b [ modes . LUMINOSITY ] = [ gl . ONE , gl . ONE _MINUS _SRC _ALPHA ] ;
PIXI . blendModesWebGL = b ;
}
} ;
PIXI . WebGLRenderer . glContextId = 0 ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLBlendModeManager
* @ constructor
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLBlendModeManager = function ( )
{
/ * *
* @ property currentBlendMode
* @ type Number
* /
this . currentBlendMode = 99999 ;
} ;
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 ;
} ;
/ * *
* Sets - up the given blendMode from WebGL ' s point of view .
*
* @ 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 ;
this . currentBlendMode = blendMode ;
var blendModeWebGL = PIXI . blendModesWebGL [ this . currentBlendMode ] ;
if ( blendModeWebGL )
{
this . gl . blendFunc ( blendModeWebGL [ 0 ] , blendModeWebGL [ 1 ] ) ;
}
return true ;
} ;
/ * *
* Destroys this object .
*
* @ method destroy
* /
PIXI . WebGLBlendModeManager . prototype . destroy = function ( )
{
this . gl = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLMaskManager
* @ constructor
* @ private
* /
PIXI . WebGLMaskManager = function ( )
{
} ;
PIXI . WebGLMaskManager . prototype . constructor = PIXI . WebGLMaskManager ;
/ * *
* Sets the drawing context to the one given in parameter .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLMaskManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
} ;
/ * *
* Applies the Mask and adds it to the current filter stack .
*
* @ method pushMask
* @ param maskData { Array }
* @ param renderSession { Object }
* /
PIXI . WebGLMaskManager . prototype . pushMask = function ( maskData , renderSession )
{
var gl = renderSession . gl ;
if ( maskData . dirty )
{
PIXI . WebGLGraphics . updateGraphics ( maskData , gl ) ;
}
if ( maskData . _webGL [ gl . id ] === undefined || maskData . _webGL [ gl . id ] . data === undefined || maskData . _webGL [ gl . id ] . data . length === 0 )
{
return ;
}
renderSession . stencilManager . pushStencil ( maskData , maskData . _webGL [ gl . id ] . data [ 0 ] , renderSession ) ;
} ;
/ * *
* Removes the last filter from the filter stack and doesn ' t return it .
*
* @ method popMask
* @ param maskData { Array }
* @ param renderSession { Object } an object containing all the useful parameters
* /
PIXI . WebGLMaskManager . prototype . popMask = function ( maskData , renderSession )
{
var gl = this . gl ;
if ( maskData . _webGL [ gl . id ] === undefined || maskData . _webGL [ gl . id ] . data === undefined || maskData . _webGL [ gl . id ] . data . length === 0 )
{
return ;
}
renderSession . stencilManager . popStencil ( maskData , maskData . _webGL [ gl . id ] . data [ 0 ] , renderSession ) ;
} ;
/ * *
* Destroys the mask stack .
*
* @ method destroy
* /
PIXI . WebGLMaskManager . prototype . destroy = function ( )
{
this . gl = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLStencilManager
* @ constructor
* @ private
* /
PIXI . WebGLStencilManager = function ( )
{
this . stencilStack = [ ] ;
this . reverse = true ;
this . count = 0 ;
} ;
/ * *
* Sets the drawing context to the one given in parameter .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLStencilManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
} ;
/ * *
* Applies the Mask and adds it to the current filter stack .
*
* @ method pushMask
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
* /
PIXI . WebGLStencilManager . prototype . pushStencil = function ( graphics , webGLData , renderSession )
{
var gl = this . gl ;
this . bindGraphics ( graphics , webGLData , renderSession ) ;
if ( this . stencilStack . length === 0 )
{
gl . enable ( gl . STENCIL _TEST ) ;
gl . clear ( gl . STENCIL _BUFFER _BIT ) ;
this . reverse = true ;
this . count = 0 ;
}
this . stencilStack . push ( webGLData ) ;
var level = this . count ;
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 )
{
gl . drawElements ( gl . TRIANGLE _FAN , webGLData . indices . length - 4 , gl . UNSIGNED _SHORT , 0 ) ;
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 ) ;
}
// 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 ++ ;
} ;
/ * *
* TODO this does not belong here !
*
* @ method bindGraphics
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
* /
PIXI . WebGLStencilManager . prototype . bindGraphics = function ( graphics , webGLData , renderSession )
{
//if(this._currentGraphics === graphics)return;
this . _currentGraphics = graphics ;
var gl = this . gl ;
// bind the graphics object..
var projection = renderSession . projection ,
offset = renderSession . offset ,
shader ; // = renderSession.shaderManager.primitiveShader;
if ( webGLData . mode === 1 )
{
shader = renderSession . shaderManager . complexPrimitiveShader ;
renderSession . shaderManager . setShader ( shader ) ;
gl . uniform1f ( shader . flipY , renderSession . flipY ) ;
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 . uniform1f ( shader . flipY , renderSession . flipY ) ;
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 ) ;
}
} ;
/ * *
* @ method popStencil
* @ param graphics { Graphics }
* @ param webGLData { Array }
* @ param renderSession { Object }
* /
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 ) ;
}
} ;
/ * *
* Destroys the mask stack .
*
* @ method destroy
* /
PIXI . WebGLStencilManager . prototype . destroy = function ( )
{
this . stencilStack = null ;
this . gl = null ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLShaderManager
* @ constructor
* @ private
* /
PIXI . WebGLShaderManager = function ( )
{
/ * *
* @ property maxAttibs
* @ type Number
* /
this . maxAttibs = 10 ;
/ * *
* @ property attribState
* @ type Array
* /
this . attribState = [ ] ;
/ * *
* @ property tempAttribState
* @ type Array
* /
this . tempAttribState = [ ] ;
for ( var i = 0 ; i < this . maxAttibs ; i ++ )
{
this . attribState [ i ] = false ;
}
/ * *
* @ property stack
* @ type Array
* /
this . stack = [ ] ;
} ;
PIXI . WebGLShaderManager . prototype . constructor = PIXI . WebGLShaderManager ;
/ * *
* Initialises the context and the properties .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLShaderManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
// the next one is used for rendering primitives
this . primitiveShader = new PIXI . PrimitiveShader ( gl ) ;
// the next one is used for rendering triangle strips
this . complexPrimitiveShader = new PIXI . ComplexPrimitiveShader ( gl ) ;
// 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 ) ;
2016-05-19 11:36:51 +00:00
2016-02-12 16:00:36 +00:00
this . setShader ( this . defaultShader ) ;
} ;
/ * *
* Takes the attributes given in parameters .
*
* @ method setAttribs
* @ param attribs { Array } attribs
* /
PIXI . WebGLShaderManager . prototype . setAttribs = function ( attribs )
{
// 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 ;
}
var gl = this . gl ;
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 ) ;
}
}
}
} ;
/ * *
* Sets the current shader .
*
* @ method setShader
* @ param shader { Any }
* /
PIXI . WebGLShaderManager . prototype . setShader = function ( shader )
{
if ( this . _currentId === shader . _UID ) return false ;
this . _currentId = shader . _UID ;
this . currentShader = shader ;
this . gl . useProgram ( shader . program ) ;
this . setAttribs ( shader . attributes ) ;
return true ;
} ;
/ * *
* Destroys this object .
*
* @ method destroy
* /
PIXI . WebGLShaderManager . prototype . destroy = function ( )
{
this . attribState = null ;
this . tempAttribState = null ;
this . primitiveShader . destroy ( ) ;
this . complexPrimitiveShader . destroy ( ) ;
this . defaultShader . destroy ( ) ;
this . fastShader . destroy ( ) ;
this . stripShader . destroy ( ) ;
this . gl = null ;
} ;
/ * *
* @ author Mat Groves
*
* Big thanks to the very clever Matt DesLauriers < mattdesl > https : //github.com/mattdesl/
* for creating the original pixi version !
* Also a thanks to https : //github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
*
* 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
* /
PIXI . WebGLSpriteBatch = function ( )
{
/ * *
* @ property vertSize
* @ type Number
* /
this . vertSize = 5 ;
/ * *
* The number of images in the SpriteBatch before it flushes
* @ property size
* @ type Number
* /
this . size = 2000 ; //Math.pow(2, 16) / this.vertSize;
//the total number of bytes in our batch
var numVerts = this . size * 4 * 4 * this . vertSize ;
//the total number of indices in our batch
var numIndices = this . size * 6 ;
/ * *
* Holds the vertices
*
* @ property vertices
* @ type ArrayBuffer
* /
this . vertices = new PIXI . ArrayBuffer ( numVerts ) ;
/ * *
* View on the vertices as a Float32Array
*
* @ property positions
* @ type Float32Array
* /
this . positions = new PIXI . Float32Array ( this . vertices ) ;
/ * *
* View on the vertices as a Uint32Array
*
* @ property colors
* @ type Uint32Array
* /
this . colors = new PIXI . Uint32Array ( this . vertices ) ;
/ * *
* Holds the indices
*
* @ property indices
* @ type Uint16Array
* /
this . indices = new PIXI . Uint16Array ( numIndices ) ;
/ * *
* @ property lastIndexCount
* @ type Number
* /
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 ;
}
/ * *
* @ property drawing
* @ type Boolean
* /
this . drawing = false ;
/ * *
* @ property currentBatchSize
* @ type Number
* /
this . currentBatchSize = 0 ;
/ * *
* @ property currentBaseTexture
* @ type BaseTexture
* /
this . currentBaseTexture = null ;
/ * *
* @ property dirty
* @ type Boolean
* /
this . dirty = true ;
/ * *
* @ property textures
* @ type Array
* /
this . textures = [ ] ;
/ * *
* @ property blendModes
* @ type Array
* /
this . blendModes = [ ] ;
/ * *
* @ 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 ;' ,
'}'
] ) ;
} ;
/ * *
* @ 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 ;
var shader = new PIXI . PixiShader ( gl ) ;
shader . fragmentSrc = this . defaultShader . fragmentSrc ;
shader . uniforms = { } ;
shader . init ( ) ;
this . defaultShader . shaders [ gl . id ] = shader ;
} ;
/ * *
* @ method begin
* @ param renderSession { Object } The RenderSession object
* /
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
* @ param { Matrix } [ matrix ] - Optional matrix . If provided the Display Object will be rendered using this matrix , otherwise it will use its worldTransform .
* /
PIXI . WebGLSpriteBatch . prototype . render = function ( sprite , matrix )
{
var texture = sprite . texture ;
// They provided an alternative rendering matrix, so use it
var wt = sprite . worldTransform ;
if ( matrix )
{
wt = matrix ;
}
// check texture..
if ( this . currentBatchSize >= this . size )
{
this . flush ( ) ;
this . currentBaseTexture = texture . baseTexture ;
}
// get the uvs for the texture
var uvs = texture . _uvs ;
// if the uvs have not updated then no point rendering just yet!
if ( ! uvs )
{
return ;
}
var aX = sprite . anchor . x ;
var aY = sprite . anchor . y ;
var w0 , w1 , h0 , h1 ;
if ( texture . trim )
{
// if the sprite is trimmed then we need to add the extra space before transforming the sprite coords.
var trim = texture . trim ;
w1 = trim . x - aX * trim . width ;
w0 = w1 + texture . crop . width ;
h1 = trim . y - aY * trim . height ;
h0 = h1 + texture . crop . height ;
}
else
{
w0 = ( texture . frame . width ) * ( 1 - aX ) ;
w1 = ( texture . frame . width ) * - aX ;
h0 = texture . frame . height * ( 1 - aY ) ;
h1 = texture . frame . height * - aY ;
}
var i = this . currentBatchSize * 4 * this . vertSize ;
var resolution = texture . baseTexture . resolution ;
var a = wt . a / resolution ;
var b = wt . b / resolution ;
var c = wt . c / resolution ;
var d = wt . d / resolution ;
var tx = wt . tx ;
var ty = wt . ty ;
var colors = this . colors ;
var positions = this . positions ;
if ( this . renderSession . roundPixels )
{
// xy
positions [ i ] = a * w1 + c * h1 + tx | 0 ;
positions [ i + 1 ] = d * h1 + b * w1 + ty | 0 ;
// xy
positions [ i + 5 ] = a * w0 + c * h1 + tx | 0 ;
positions [ i + 6 ] = d * h1 + b * w0 + ty | 0 ;
// xy
positions [ i + 10 ] = a * w0 + c * h0 + tx | 0 ;
positions [ i + 11 ] = d * h0 + b * w0 + ty | 0 ;
// xy
positions [ i + 15 ] = a * w1 + c * h0 + tx | 0 ;
positions [ i + 16 ] = d * h0 + b * w1 + ty | 0 ;
}
else
{
// xy
positions [ i ] = a * w1 + c * h1 + tx ;
positions [ i + 1 ] = d * h1 + b * w1 + ty ;
// xy
positions [ i + 5 ] = a * w0 + c * h1 + tx ;
positions [ i + 6 ] = d * h1 + b * w0 + ty ;
// xy
positions [ i + 10 ] = a * w0 + c * h0 + tx ;
positions [ i + 11 ] = d * h0 + b * w0 + ty ;
// xy
positions [ i + 15 ] = a * w1 + c * h0 + tx ;
positions [ i + 16 ] = d * h0 + b * w1 + ty ;
}
// uv
positions [ i + 2 ] = uvs . x0 ;
positions [ i + 3 ] = uvs . y0 ;
// uv
positions [ i + 7 ] = uvs . x1 ;
positions [ i + 8 ] = uvs . y1 ;
// uv
positions [ i + 12 ] = uvs . x2 ;
positions [ i + 13 ] = uvs . y2 ;
// uv
positions [ i + 17 ] = uvs . x3 ;
positions [ i + 18 ] = uvs . y3 ;
// color and alpha
var tint = sprite . tint ;
colors [ i + 4 ] = colors [ i + 9 ] = colors [ i + 14 ] = colors [ i + 19 ] = ( tint >> 16 ) + ( tint & 0xff00 ) + ( ( tint & 0xff ) << 16 ) + ( sprite . worldAlpha * 255 << 24 ) ;
// increment the batchsize
this . sprites [ this . currentBatchSize ++ ] = sprite ;
} ;
/ * *
* Renders a TilingSprite using the spriteBatch .
*
* @ method renderTilingSprite
* @ param sprite { TilingSprite } the sprite to render
* /
PIXI . WebGLSpriteBatch . prototype . renderTilingSprite = function ( sprite )
{
var texture = sprite . tilingTexture ;
// check texture..
if ( this . currentBatchSize >= this . size )
{
this . flush ( ) ;
this . currentBaseTexture = texture . baseTexture ;
}
// set the textures uvs temporarily
if ( ! sprite . _uvs )
{
sprite . _uvs = new PIXI . TextureUvs ( ) ;
}
var uvs = sprite . _uvs ;
var w = texture . baseTexture . width ;
var h = texture . baseTexture . height ;
// var w = sprite._frame.sourceSizeW;
// var h = sprite._frame.sourceSizeH;
// w = 16;
// h = 16;
sprite . tilePosition . x %= w * sprite . tileScaleOffset . x ;
sprite . tilePosition . y %= h * sprite . tileScaleOffset . y ;
var offsetX = sprite . tilePosition . x / ( w * sprite . tileScaleOffset . x ) ;
var offsetY = sprite . tilePosition . y / ( h * sprite . tileScaleOffset . y ) ;
var scaleX = ( sprite . width / w ) / ( sprite . tileScale . x * sprite . tileScaleOffset . x ) ;
var scaleY = ( sprite . height / h ) / ( sprite . tileScale . y * sprite . 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 sprites current alpha and tint and combine them into a single color
var tint = sprite . tint ;
var color = ( tint >> 16 ) + ( tint & 0xff00 ) + ( ( tint & 0xff ) << 16 ) + ( sprite . worldAlpha * 255 << 24 ) ;
var positions = this . positions ;
var colors = this . colors ;
var width = sprite . width ;
var height = sprite . height ;
// TODO trim??
var aX = sprite . anchor . x ;
var aY = sprite . anchor . y ;
var w0 = width * ( 1 - aX ) ;
var w1 = width * - aX ;
var h0 = height * ( 1 - aY ) ;
var h1 = height * - aY ;
var i = this . currentBatchSize * 4 * this . vertSize ;
var resolution = texture . baseTexture . resolution ;
var wt = sprite . worldTransform ;
var a = wt . a / resolution ;
var b = wt . b / resolution ;
var c = wt . c / resolution ;
var d = wt . d / resolution ;
var tx = wt . tx ;
var ty = wt . ty ;
// xy
positions [ i ++ ] = a * w1 + c * h1 + tx ;
positions [ i ++ ] = d * h1 + b * w1 + ty ;
// uv
positions [ i ++ ] = uvs . x0 ;
positions [ i ++ ] = uvs . y0 ;
// color
colors [ i ++ ] = color ;
// xy
positions [ i ++ ] = ( a * w0 + c * h1 + tx ) ;
positions [ i ++ ] = d * h1 + b * w0 + ty ;
// uv
positions [ i ++ ] = uvs . x1 ;
positions [ i ++ ] = uvs . y1 ;
// color
colors [ i ++ ] = color ;
// xy
positions [ i ++ ] = a * w0 + c * h0 + tx ;
positions [ i ++ ] = d * h0 + b * w0 + ty ;
// uv
positions [ i ++ ] = uvs . x2 ;
positions [ i ++ ] = uvs . y2 ;
// color
colors [ i ++ ] = color ;
// xy
positions [ i ++ ] = a * w1 + c * h0 + tx ;
positions [ i ++ ] = d * h0 + b * w1 + ty ;
// uv
positions [ i ++ ] = uvs . x3 ;
positions [ i ++ ] = uvs . y3 ;
// color
colors [ i ++ ] = color ;
// increment the batchsize
this . sprites [ this . currentBatchSize ++ ] = sprite ;
} ;
/ * *
* Renders the content and empties the current batch .
*
* @ 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 ;
var shader ;
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 ) ;
shader = this . defaultShader . shaders [ gl . id ] ;
// this is the same for each shader?
var stride = this . vertSize * 4 ;
gl . vertexAttribPointer ( shader . aVertexPosition , 2 , gl . FLOAT , false , stride , 0 ) ;
gl . vertexAttribPointer ( shader . aTextureCoord , 2 , gl . FLOAT , false , stride , 2 * 4 ) ;
// color attributes will be interpreted as unsigned bytes and normalized
gl . vertexAttribPointer ( shader . colorAttribute , 4 , gl . UNSIGNED _BYTE , true , stride , 4 * 4 ) ;
}
// upload the verts to the buffer
if ( this . currentBatchSize > ( this . size * 0.5 ) )
{
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertices ) ;
}
else
{
var view = this . positions . subarray ( 0 , this . currentBatchSize * 4 * this . vertSize ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , view ) ;
}
var nextTexture , nextBlendMode , nextShader ;
var batchSize = 0 ;
var start = 0 ;
var currentBaseTexture = null ;
var currentBlendMode = this . renderSession . blendModeManager . currentBlendMode ;
var currentShader = null ;
var blendSwap = false ;
var shaderSwap = false ;
var sprite ;
for ( var i = 0 , j = this . currentBatchSize ; i < j ; i ++ ) {
sprite = this . sprites [ i ] ;
if ( sprite . tilingTexture )
{
nextTexture = sprite . tilingTexture . baseTexture ;
}
else
{
nextTexture = sprite . texture . baseTexture ;
}
nextBlendMode = sprite . blendMode ;
nextShader = sprite . shader || this . defaultShader ;
blendSwap = currentBlendMode !== nextBlendMode ;
shaderSwap = currentShader !== nextShader ; // should I use _UIDS???
var skip = nextTexture . skipRender ;
if ( skip && sprite . children . length > 0 )
{
skip = false ;
}
if ( ( currentBaseTexture !== nextTexture && ! skip ) || blendSwap || shaderSwap )
{
this . renderBatch ( currentBaseTexture , batchSize , start ) ;
start = i ;
batchSize = 0 ;
currentBaseTexture = nextTexture ;
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 these 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 temporary!
var offsetVector = this . renderSession . offset ;
gl . uniform2f ( shader . offsetVector , offsetVector . x , offsetVector . y ) ;
// set the pointers
}
}
batchSize ++ ;
}
this . renderBatch ( currentBaseTexture , batchSize , start ) ;
// then reset the batch!
this . currentBatchSize = 0 ;
} ;
/ * *
* @ method renderBatch
* @ param texture { Texture }
* @ param size { Number }
* @ param startIndex { Number }
* /
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 ] )
{
if ( ! this . renderSession . renderer . updateTexture ( texture ) )
{
// If updateTexture returns false then we cannot render it, so bail out now
return ;
}
}
else
{
// bind the current texture
gl . bindTexture ( gl . TEXTURE _2D , texture . _glTextures [ gl . id ] ) ;
}
// now draw those suckas!
gl . drawElements ( gl . TRIANGLES , size * 6 , gl . UNSIGNED _SHORT , startIndex * 6 * 2 ) ;
// increment the draw count
this . renderSession . drawCount ++ ;
} ;
/ * *
* @ method stop
* /
PIXI . WebGLSpriteBatch . prototype . stop = function ( )
{
this . flush ( ) ;
this . dirty = true ;
} ;
/ * *
* @ method start
* /
PIXI . WebGLSpriteBatch . prototype . start = function ( )
{
this . dirty = true ;
} ;
/ * *
* Destroys the SpriteBatch .
*
* @ method destroy
* /
PIXI . WebGLSpriteBatch . prototype . destroy = function ( )
{
this . vertices = null ;
this . indices = null ;
this . gl . deleteBuffer ( this . vertexBuffer ) ;
this . gl . deleteBuffer ( this . indexBuffer ) ;
this . currentBaseTexture = null ;
this . gl = null ;
} ;
/ * *
* @ author Mat Groves
*
* 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 WebGLFastSpriteBatch
* @ constructor
* /
PIXI . WebGLFastSpriteBatch = function ( gl )
{
/ * *
* @ property vertSize
* @ type Number
* /
this . vertSize = 10 ;
/ * *
* @ property maxSize
* @ type Number
* /
this . maxSize = 6000 ; //Math.pow(2, 16) / this.vertSize;
/ * *
* @ property size
* @ type Number
* /
this . size = this . maxSize ;
//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 . maxSize * 6 ;
/ * *
* Vertex data
* @ property vertices
* @ type Float32Array
* /
this . vertices = new PIXI . Float32Array ( numVerts ) ;
/ * *
* Index data
* @ property indices
* @ type Uint16Array
* /
this . indices = new PIXI . Uint16Array ( numIndices ) ;
/ * *
* @ property vertexBuffer
* @ type Object
* /
this . vertexBuffer = null ;
/ * *
* @ property indexBuffer
* @ type Object
* /
this . indexBuffer = null ;
/ * *
* @ property lastIndexCount
* @ type Number
* /
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 ;
}
/ * *
* @ property drawing
* @ type Boolean
* /
this . drawing = false ;
/ * *
* @ property currentBatchSize
* @ type Number
* /
this . currentBatchSize = 0 ;
/ * *
* @ property currentBaseTexture
* @ type BaseTexture
* /
this . currentBaseTexture = null ;
/ * *
* @ property currentBlendMode
* @ type Number
* /
this . currentBlendMode = 0 ;
/ * *
* @ property renderSession
* @ type Object
* /
this . renderSession = null ;
/ * *
* @ property shader
* @ type Object
* /
this . shader = null ;
/ * *
* @ property matrix
* @ type Matrix
* /
this . matrix = null ;
this . setContext ( gl ) ;
} ;
PIXI . WebGLFastSpriteBatch . prototype . constructor = PIXI . WebGLFastSpriteBatch ;
/ * *
* Sets the WebGL Context .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
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 ) ;
} ;
/ * *
* @ method begin
* @ param spriteBatch { WebGLSpriteBatch }
* @ param renderSession { Object }
* /
PIXI . WebGLFastSpriteBatch . prototype . begin = function ( spriteBatch , renderSession )
{
this . renderSession = renderSession ;
this . shader = this . renderSession . shaderManager . fastShader ;
this . matrix = spriteBatch . worldTransform . toArray ( true ) ;
this . start ( ) ;
} ;
/ * *
* @ method end
* /
PIXI . WebGLFastSpriteBatch . prototype . end = function ( )
{
this . flush ( ) ;
} ;
/ * *
* @ method render
* @ param spriteBatch { WebGLSpriteBatch }
* /
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!
// check texture.
if ( ! sprite . texture . _uvs ) return ;
this . currentBaseTexture = sprite . texture . baseTexture ;
// check blend mode
if ( sprite . blendMode !== this . renderSession . blendModeManager . currentBlendMode )
{
this . flush ( ) ;
this . renderSession . blendModeManager . setBlendMode ( sprite . blendMode ) ;
}
for ( var i = 0 , j = children . length ; i < j ; i ++ )
{
this . renderSprite ( children [ i ] ) ;
}
this . flush ( ) ;
} ;
/ * *
* @ method renderSprite
* @ param sprite { Sprite }
* /
PIXI . WebGLFastSpriteBatch . prototype . renderSprite = function ( sprite )
{
//sprite = children[i];
if ( ! sprite . visible ) return ;
// TODO trim??
if ( sprite . texture . baseTexture !== this . currentBaseTexture && ! sprite . texture . baseTexture . skipRender )
{
this . flush ( ) ;
this . currentBaseTexture = sprite . texture . baseTexture ;
if ( ! sprite . texture . _uvs ) return ;
}
var uvs , vertices = 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 ;
w0 = w1 + sprite . texture . crop . width ;
h1 = trim . y - sprite . anchor . y * trim . height ;
h0 = h1 + sprite . texture . crop . height ;
}
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
vertices [ index ++ ] = w1 ;
vertices [ index ++ ] = h1 ;
vertices [ index ++ ] = sprite . position . x ;
vertices [ index ++ ] = sprite . position . y ;
//scale
vertices [ index ++ ] = sprite . scale . x ;
vertices [ index ++ ] = sprite . scale . y ;
//rotation
vertices [ index ++ ] = sprite . rotation ;
// uv
vertices [ index ++ ] = uvs . x0 ;
vertices [ index ++ ] = uvs . y1 ;
// color
vertices [ index ++ ] = sprite . alpha ;
// xy
vertices [ index ++ ] = w0 ;
vertices [ index ++ ] = h1 ;
vertices [ index ++ ] = sprite . position . x ;
vertices [ index ++ ] = sprite . position . y ;
//scale
vertices [ index ++ ] = sprite . scale . x ;
vertices [ index ++ ] = sprite . scale . y ;
//rotation
vertices [ index ++ ] = sprite . rotation ;
// uv
vertices [ index ++ ] = uvs . x1 ;
vertices [ index ++ ] = uvs . y1 ;
// color
vertices [ index ++ ] = sprite . alpha ;
// xy
vertices [ index ++ ] = w0 ;
vertices [ index ++ ] = h0 ;
vertices [ index ++ ] = sprite . position . x ;
vertices [ index ++ ] = sprite . position . y ;
//scale
vertices [ index ++ ] = sprite . scale . x ;
vertices [ index ++ ] = sprite . scale . y ;
//rotation
vertices [ index ++ ] = sprite . rotation ;
// uv
vertices [ index ++ ] = uvs . x2 ;
vertices [ index ++ ] = uvs . y2 ;
// color
vertices [ index ++ ] = sprite . alpha ;
// xy
vertices [ index ++ ] = w1 ;
vertices [ index ++ ] = h0 ;
vertices [ index ++ ] = sprite . position . x ;
vertices [ index ++ ] = sprite . position . y ;
//scale
vertices [ index ++ ] = sprite . scale . x ;
vertices [ index ++ ] = sprite . scale . y ;
//rotation
vertices [ index ++ ] = sprite . rotation ;
// uv
vertices [ index ++ ] = uvs . x3 ;
vertices [ index ++ ] = uvs . y3 ;
// color
vertices [ index ++ ] = sprite . alpha ;
// increment the batchs
this . currentBatchSize ++ ;
if ( this . currentBatchSize >= this . size )
{
this . flush ( ) ;
}
} ;
/ * *
* @ method flush
* /
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 ;
// bind the current texture
if ( ! this . currentBaseTexture . _glTextures [ gl . id ] ) this . renderSession . renderer . updateTexture ( this . currentBaseTexture , gl ) ;
gl . bindTexture ( gl . TEXTURE _2D , this . currentBaseTexture . _glTextures [ gl . id ] ) ;
// upload the verts to the buffer
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 ) ;
}
// now draw those suckas!
gl . drawElements ( gl . TRIANGLES , this . currentBatchSize * 6 , gl . UNSIGNED _SHORT , 0 ) ;
// then reset the batch!
this . currentBatchSize = 0 ;
// increment the draw count
this . renderSession . drawCount ++ ;
} ;
/ * *
* @ method stop
* /
PIXI . WebGLFastSpriteBatch . prototype . stop = function ( )
{
this . flush ( ) ;
} ;
/ * *
* @ method start
* /
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 ) ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* @ class WebGLFilterManager
* @ constructor
* /
PIXI . WebGLFilterManager = function ( )
{
/ * *
* @ property filterStack
* @ type Array
* /
this . filterStack = [ ] ;
/ * *
* @ property offsetX
* @ type Number
* /
this . offsetX = 0 ;
/ * *
* @ property offsetY
* @ type Number
* /
this . offsetY = 0 ;
} ;
PIXI . WebGLFilterManager . prototype . constructor = PIXI . WebGLFilterManager ;
/ * *
* Initialises the context and the properties .
*
* @ method setContext
* @ param gl { WebGLContext } the current WebGL drawing context
* /
PIXI . WebGLFilterManager . prototype . setContext = function ( gl )
{
this . gl = gl ;
this . texturePool = [ ] ;
this . initShaderBuffers ( ) ;
} ;
/ * *
* @ method begin
* @ param renderSession { RenderSession }
* @ param buffer { ArrayBuffer }
* /
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 ;
} ;
/ * *
* Applies the filter and adds it to the current filter stack .
*
* @ 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 ;
filterBlock . _filterArea = filterBlock . target . filterArea || filterBlock . target . getBounds ( ) ;
// >>> modify by nextht
filterBlock . _previous _stencil _mgr = this . renderSession . stencilManager ;
this . renderSession . stencilManager = new PIXI . WebGLStencilManager ( ) ;
this . renderSession . stencilManager . setContext ( gl ) ;
gl . disable ( gl . STENCIL _TEST ) ;
// <<< modify by nextht
// filter program
// OPTIMISATION - the first filter is free if its a simple color change?
this . filterStack . push ( filterBlock ) ;
var filter = filterBlock . filterPasses [ 0 ] ;
this . offsetX += filterBlock . _filterArea . x ;
this . offsetY += filterBlock . _filterArea . y ;
var texture = this . texturePool . pop ( ) ;
if ( ! texture )
{
texture = new PIXI . FilterTexture ( this . gl , this . width * this . renderSession . resolution , this . height * this . renderSession . resolution ) ;
}
else
{
texture . resize ( this . width * this . renderSession . resolution , this . height * this . renderSession . resolution ) ;
}
gl . bindTexture ( gl . TEXTURE _2D , texture . texture ) ;
var filterArea = filterBlock . _filterArea ; // filterBlock.target.getBounds();///filterBlock.target.filterArea;
var padding = filter . padding ;
filterArea . x -= padding ;
filterArea . y -= padding ;
filterArea . width += padding * 2 ;
filterArea . height += padding * 2 ;
// 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 * this . renderSession . resolution , filterArea . height * this . renderSession . resolution ) ;
projection . x = filterArea . width / 2 ;
projection . y = - filterArea . height / 2 ;
offset . x = - filterArea . x ;
offset . y = - filterArea . y ;
// update projection
// now restore the regular shader..
// 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);
gl . colorMask ( true , true , true , true ) ;
gl . clearColor ( 0 , 0 , 0 , 0 ) ;
gl . clear ( gl . COLOR _BUFFER _BIT ) ;
filterBlock . _glFilterTexture = texture ;
} ;
/ * *
* Removes the last filter from the filter stack and doesn ' t return it .
*
* @ method popFilter
* /
PIXI . WebGLFilterManager . prototype . popFilter = function ( )
{
var gl = this . gl ;
var filterBlock = this . filterStack . pop ( ) ;
var filterArea = filterBlock . _filterArea ;
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 * this . renderSession . resolution , filterArea . height * this . renderSession . resolution ) ;
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 . renderSession . resolution , this . height * this . renderSession . resolution ) ;
outputTexture . resize ( this . width * this . renderSession . resolution , this . height * this . renderSession . resolution ) ;
// 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 ] ;
filterArea = currentFilter . _filterArea ;
sizeX = filterArea . width ;
sizeY = filterArea . height ;
offsetX = filterArea . x ;
offsetY = filterArea . y ;
buffer = currentFilter . _glFilterTexture . frameBuffer ;
}
// TODO need to remove these global elements..
projection . x = sizeX / 2 ;
projection . y = - sizeY / 2 ;
offset . x = offsetX ;
offset . y = offsetY ;
filterArea = filterBlock . _filterArea ;
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 * this . renderSession . resolution , sizeY * this . renderSession . resolution ) ;
// bind the buffer
gl . bindFramebuffer ( gl . FRAMEBUFFER , buffer ) ;
// set the blend mode!
//gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
// set texture
gl . activeTexture ( gl . TEXTURE0 ) ;
gl . bindTexture ( gl . TEXTURE _2D , texture . texture ) ;
// >>> modify by nextht
if ( this . renderSession . stencilManager ) {
this . renderSession . stencilManager . destroy ( ) ;
}
this . renderSession . stencilManager = filterBlock . _previous _stencil _mgr ;
filterBlock . _previous _stencil _mgr = null ;
if ( this . renderSession . stencilManager . count > 0 ) {
gl . enable ( gl . STENCIL _TEST ) ;
}
else {
gl . disable ( gl . STENCIL _TEST ) ;
}
// <<< modify by nextht
// apply!
this . applyFilterPass ( filter , filterArea , sizeX , sizeY ) ;
// 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);
// return the texture to the pool
this . texturePool . push ( texture ) ;
filterBlock . _glFilterTexture = null ;
} ;
/ * *
* Applies the filter to the specified area .
*
* @ method applyFilterPass
* @ param filter { AbstractFilter } the filter that needs to be applied
* @ param filterArea { Texture } TODO - might need an update
* @ 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
this . renderSession . shaderManager . setShader ( shader ) ;
// gl.useProgram(shader.program);
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 ++ ;
} ;
/ * *
* Initialises the shader buffers .
*
* @ 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..
this . vertexArray = new PIXI . Float32Array ( [ 0.0 , 0.0 ,
1.0 , 0.0 ,
0.0 , 1.0 ,
1.0 , 1.0 ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . vertexBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . vertexArray , gl . STATIC _DRAW ) ;
// bind and upload the uv buffer
this . uvArray = new PIXI . Float32Array ( [ 0.0 , 0.0 ,
1.0 , 0.0 ,
0.0 , 1.0 ,
1.0 , 1.0 ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . uvBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . uvArray , gl . STATIC _DRAW ) ;
this . colorArray = new PIXI . Float32Array ( [ 1.0 , 0xFFFFFF ,
1.0 , 0xFFFFFF ,
1.0 , 0xFFFFFF ,
1.0 , 0xFFFFFF ] ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , this . colorBuffer ) ;
gl . bufferData ( gl . ARRAY _BUFFER , this . colorArray , gl . STATIC _DRAW ) ;
// bind and upload the index
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , this . indexBuffer ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , new Uint16Array ( [ 0 , 1 , 2 , 1 , 3 , 2 ] ) , gl . STATIC _DRAW ) ;
} ;
/ * *
* Destroys the filter and removes it from the filter stack .
*
* @ method destroy
* /
PIXI . WebGLFilterManager . prototype . destroy = function ( )
{
var gl = this . gl ;
this . filterStack = null ;
this . offsetX = 0 ;
this . offsetY = 0 ;
// destroy textures
for ( var i = 0 ; i < this . texturePool . length ; i ++ ) {
this . texturePool [ i ] . destroy ( ) ;
}
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
* @ 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
* /
PIXI . FilterTexture = function ( gl , width , height , scaleMode )
{
/ * *
* @ property gl
* @ type WebGLContext
* /
this . gl = gl ;
// next time to create a frame buffer and texture
/ * *
* @ property frameBuffer
* @ type Any
* /
this . frameBuffer = gl . createFramebuffer ( ) ;
/ * *
* @ property texture
* @ type Any
* /
this . texture = gl . createTexture ( ) ;
/ * *
* @ property scaleMode
* @ type Number
* /
scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
gl . bindTexture ( gl . TEXTURE _2D , this . texture ) ;
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 ) ;
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 ) ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . frameBuffer ) ;
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . frameBuffer ) ;
gl . framebufferTexture2D ( gl . FRAMEBUFFER , gl . COLOR _ATTACHMENT0 , gl . TEXTURE _2D , this . texture , 0 ) ;
// 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 ) ;
this . resize ( width , height ) ;
} ;
PIXI . FilterTexture . prototype . constructor = PIXI . FilterTexture ;
/ * *
* Clears the filter texture .
*
* @ method clear
* /
PIXI . FilterTexture . prototype . clear = function ( )
{
var gl = this . gl ;
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 ) ;
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , width , height , 0 , gl . RGBA , gl . UNSIGNED _BYTE , null ) ;
// update the stencil buffer width and height
gl . bindRenderbuffer ( gl . RENDERBUFFER , this . renderBuffer ) ;
gl . renderbufferStorage ( gl . RENDERBUFFER , gl . DEPTH _STENCIL , width , height ) ;
} ;
/ * *
* Destroys the filter texture .
*
* @ 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 ;
} ;
/ * *
* @ 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 = PIXI . CanvasPool . create ( this , this . width , this . height ) ;
/ * *
* 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 ( )
{
this . context . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
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 ;
} ;
/ * *
* Frees the canvas up for use again .
*
* @ method destroy
* /
PIXI . CanvasBuffer . prototype . destroy = function ( )
{
PIXI . CanvasPool . remove ( this ) ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* A set of functions used to handle masking .
*
* @ class CanvasMaskManager
* @ constructor
* /
PIXI . CanvasMaskManager = function ( )
{
} ;
PIXI . CanvasMaskManager . prototype . constructor = PIXI . CanvasMaskManager ;
/ * *
* This method adds it to the current stack of masks .
*
* @ method pushMask
* @ param maskData { Object } the maskData that will be pushed
* @ param renderSession { Object } The renderSession whose context will be used for this mask manager .
* /
PIXI . CanvasMaskManager . prototype . pushMask = function ( maskData , renderSession ) {
var context = renderSession . context ;
context . save ( ) ;
var cacheAlpha = maskData . alpha ;
var transform = maskData . worldTransform ;
var resolution = renderSession . resolution ;
context . setTransform ( transform . a * resolution ,
transform . b * resolution ,
transform . c * resolution ,
transform . d * resolution ,
transform . tx * resolution ,
transform . ty * resolution ) ;
PIXI . CanvasGraphics . renderGraphicsMask ( maskData , context ) ;
context . clip ( ) ;
maskData . worldAlpha = cacheAlpha ;
} ;
/ * *
* Restores the current drawing context to the state it was before the mask was applied .
*
* @ method popMask
* @ param renderSession { Object } The renderSession whose context will be used for this mask manager .
* /
PIXI . CanvasMaskManager . prototype . popMask = function ( renderSession )
{
renderSession . context . restore ( ) ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* Utility methods for Sprite / Texture tinting .
*
* @ class CanvasTinter
* @ static
* /
PIXI . CanvasTinter = function ( ) { } ;
/ * *
* Basically this method just needs a sprite and a color and tints the sprite with the given color .
*
* @ method getTintedTexture
* @ static
* @ param sprite { Sprite } the sprite to tint
* @ param color { Number } the color to use to tint the sprite with
* @ return { HTMLCanvasElement } The tinted canvas
* /
PIXI . CanvasTinter . getTintedTexture = function ( sprite , color )
{
var canvas = sprite . tintedTexture || PIXI . CanvasPool . create ( this ) ;
PIXI . CanvasTinter . tintMethod ( sprite . texture , color , canvas ) ;
return canvas ;
} ;
/ * *
* Tint a texture using the "multiply" operation .
*
* @ method tintWithMultiply
* @ static
* @ param texture { Texture } the texture to tint
* @ 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" ) ;
var crop = texture . crop ;
if ( canvas . width !== crop . width || canvas . height !== crop . height )
{
canvas . width = crop . width ;
canvas . height = crop . height ;
}
context . clearRect ( 0 , 0 , crop . width , crop . height ) ;
context . fillStyle = "#" + ( "00000" + ( color | 0 ) . toString ( 16 ) ) . substr ( - 6 ) ;
context . fillRect ( 0 , 0 , crop . width , crop . height ) ;
context . globalCompositeOperation = "multiply" ;
context . drawImage ( texture . baseTexture . source , crop . x , crop . y , crop . width , crop . height , 0 , 0 , crop . width , crop . height ) ;
context . globalCompositeOperation = "destination-atop" ;
context . drawImage ( texture . baseTexture . source , crop . x , crop . y , crop . width , crop . height , 0 , 0 , crop . width , crop . height ) ;
} ;
/ * *
* Tint a texture pixel per pixel .
*
* @ method tintPerPixel
* @ static
* @ param texture { Texture } the texture to tint
* @ 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" ) ;
var crop = texture . crop ;
canvas . width = crop . width ;
canvas . height = crop . height ;
context . globalCompositeOperation = "copy" ;
context . drawImage ( texture . baseTexture . source , crop . x , crop . y , crop . width , crop . height , 0 , 0 , crop . width , crop . height ) ;
var rgbValues = PIXI . hex2rgb ( color ) ;
var r = rgbValues [ 0 ] , g = rgbValues [ 1 ] , b = rgbValues [ 2 ] ;
var pixelData = context . getImageData ( 0 , 0 , crop . width , crop . height ) ;
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 ;
if ( ! PIXI . CanvasTinter . canHandleAlpha )
{
var alpha = pixels [ i + 3 ] ;
pixels [ i + 0 ] /= 255 / alpha ;
pixels [ i + 1 ] /= 255 / alpha ;
pixels [ i + 2 ] /= 255 / alpha ;
}
}
context . putImageData ( pixelData , 0 , 0 ) ;
} ;
/ * *
* Checks if the browser correctly supports putImageData alpha channels .
*
* @ method checkInverseAlpha
* @ static
* /
PIXI . CanvasTinter . checkInverseAlpha = function ( )
{
var canvas = new PIXI . CanvasBuffer ( 2 , 1 ) ;
canvas . context . fillStyle = "rgba(10, 20, 30, 0.5)" ;
// Draw a single pixel
canvas . context . fillRect ( 0 , 0 , 1 , 1 ) ;
// Get the color values
var s1 = canvas . context . getImageData ( 0 , 0 , 1 , 1 ) ;
if ( s1 === null )
{
return false ;
}
// Plot them to x2
canvas . context . putImageData ( s1 , 1 , 0 ) ;
// Get those values
var s2 = canvas . context . getImageData ( 1 , 0 , 1 , 1 ) ;
// Compare and return
return ( s2 . data [ 0 ] === s1 . data [ 0 ] && s2 . data [ 1 ] === s1 . data [ 1 ] && s2 . data [ 2 ] === s1 . data [ 2 ] && s2 . data [ 3 ] === s1 . data [ 3 ] ) ;
} ;
/ * *
* If the browser isn ' t capable of handling tinting with alpha this will be false .
* This property is only applicable if using tintWithPerPixel .
*
* @ property canHandleAlpha
* @ type Boolean
* @ static
* /
PIXI . CanvasTinter . canHandleAlpha = PIXI . CanvasTinter . checkInverseAlpha ( ) ;
/ * *
* Whether or not the Canvas BlendModes are supported , consequently the ability to tint using the multiply method .
*
* @ property canUseMultiply
* @ type Boolean
* @ static
* /
PIXI . CanvasTinter . canUseMultiply = PIXI . canUseNewCanvasBlendModes ( ) ;
/ * *
* The tinting method that will be used .
*
* @ method tintMethod
* @ static
* /
PIXI . CanvasTinter . tintMethod = PIXI . CanvasTinter . canUseMultiply ? PIXI . CanvasTinter . tintWithMultiply : PIXI . CanvasTinter . tintWithPerPixel ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* 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 : )
*
* @ class CanvasRenderer
* @ constructor
* @ param game { Phaser . Game } A reference to the Phaser Game instance
* /
PIXI . CanvasRenderer = function ( game ) {
/ * *
* @ property { Phaser . Game } game - A reference to the Phaser Game instance .
* /
this . game = game ;
if ( ! PIXI . defaultRenderer )
{
PIXI . defaultRenderer = this ;
}
/ * *
* The renderer type .
*
* @ property type
* @ type Number
* /
this . type = PIXI . CANVAS _RENDERER ;
/ * *
* The resolution of the canvas .
*
* @ property resolution
* @ type Number
* /
this . resolution = game . resolution ;
/ * *
* 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
* /
this . clearBeforeRender = game . clearBeforeRender ;
/ * *
* Whether the render view is transparent
*
* @ property transparent
* @ type Boolean
* /
this . transparent = game . transparent ;
/ * *
* Whether the render view should be resized automatically
*
* @ property autoResize
* @ type Boolean
* /
this . autoResize = false ;
/ * *
* The width of the canvas view
*
* @ property width
* @ type Number
* @ default 800
* /
this . width = game . width * this . resolution ;
/ * *
* The height of the canvas view
*
* @ property height
* @ type Number
* @ default 600
* /
this . height = game . height * this . resolution ;
/ * *
* The canvas element that everything is drawn to .
*
* @ property view
* @ type HTMLCanvasElement
* /
this . view = game . canvas ;
/ * *
* The canvas 2 d context that everything is drawn with
* @ property context
* @ type CanvasRenderingContext2D
* /
this . context = this . view . getContext ( "2d" , { alpha : this . transparent } ) ;
/ * *
* Boolean flag controlling canvas refresh .
*
* @ property refresh
* @ type Boolean
* /
this . refresh = true ;
/ * *
* Internal var .
*
* @ property count
* @ type Number
* /
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 ,
smoothProperty : Phaser . Canvas . getSmoothingPrefix ( this . context ) ,
/ * *
* 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
} ;
this . mapBlendModes ( ) ;
this . resize ( this . width , this . height ) ;
} ;
// constructor
PIXI . CanvasRenderer . prototype . constructor = PIXI . CanvasRenderer ;
/ * *
* Renders the Stage to this canvas view
*
* @ method render
* @ param stage { Stage } the Stage element to be rendered
* /
PIXI . CanvasRenderer . prototype . render = function ( stage ) {
this . context . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
this . context . globalAlpha = 1 ;
this . renderSession . currentBlendMode = 0 ;
2016-04-22 13:45:11 +00:00
this . renderSession . shakeX = this . game . camera . _shake . x ;
this . renderSession . shakeY = this . game . camera . _shake . y ;
2016-02-12 16:00:36 +00:00
this . context . globalCompositeOperation = 'source-over' ;
if ( navigator . isCocoonJS && this . view . screencanvas )
{
this . context . fillStyle = "black" ;
this . context . clear ( ) ;
}
if ( this . clearBeforeRender )
{
if ( this . transparent )
{
this . context . clearRect ( 0 , 0 , this . width , this . height ) ;
}
else
{
this . context . fillStyle = stage . _bgColor . rgba ;
this . context . fillRect ( 0 , 0 , this . width , this . height ) ;
}
}
this . renderDisplayObject ( stage ) ;
} ;
/ * *
* 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 .
* /
2016-04-14 12:23:44 +00:00
PIXI . CanvasRenderer . prototype . destroy = function ( removeView ) {
2016-02-12 16:00:36 +00:00
if ( 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 ;
} ;
/ * *
* 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
* /
2016-04-14 12:23:44 +00:00
PIXI . CanvasRenderer . prototype . resize = function ( width , height ) {
2016-02-12 16:00:36 +00:00
this . width = width * this . resolution ;
this . height = height * this . resolution ;
this . view . width = this . width ;
this . view . height = this . height ;
if ( this . autoResize )
{
this . view . style . width = this . width / this . resolution + "px" ;
this . view . style . height = this . height / this . resolution + "px" ;
}
2016-04-14 12:23:44 +00:00
if ( this . renderSession . smoothProperty )
{
this . context [ this . renderSession . smoothProperty ] = ( this . renderSession . scaleMode === PIXI . scaleModes . LINEAR ) ;
}
2016-02-12 16:00:36 +00:00
} ;
/ * *
* Renders a display object
*
* @ method renderDisplayObject
* @ param displayObject { DisplayObject } The displayObject to render
* @ param context { CanvasRenderingContext2D } the context 2 d method of the canvas
* @ param [ matrix ] { Matrix } Optional matrix to apply to the display object before rendering .
* @ private
* /
PIXI . CanvasRenderer . prototype . renderDisplayObject = function ( displayObject , context , matrix ) {
this . renderSession . context = context || this . context ;
this . renderSession . resolution = this . resolution ;
displayObject . _renderCanvas ( this . renderSession , matrix ) ;
} ;
/ * *
* Maps Pixi blend modes to canvas blend modes .
*
* @ method mapBlendModes
* @ private
* /
PIXI . CanvasRenderer . prototype . mapBlendModes = function ( ) {
if ( ! PIXI . blendModesCanvas )
{
var b = [ ] ;
var modes = PIXI . blendModes ;
var useNew = PIXI . canUseNewCanvasBlendModes ( ) ;
b [ modes . NORMAL ] = 'source-over' ;
b [ modes . ADD ] = 'lighter' ;
b [ modes . MULTIPLY ] = ( useNew ) ? 'multiply' : 'source-over' ;
b [ modes . SCREEN ] = ( useNew ) ? 'screen' : 'source-over' ;
b [ modes . OVERLAY ] = ( useNew ) ? 'overlay' : 'source-over' ;
b [ modes . DARKEN ] = ( useNew ) ? 'darken' : 'source-over' ;
b [ modes . LIGHTEN ] = ( useNew ) ? 'lighten' : 'source-over' ;
b [ modes . COLOR _DODGE ] = ( useNew ) ? 'color-dodge' : 'source-over' ;
b [ modes . COLOR _BURN ] = ( useNew ) ? 'color-burn' : 'source-over' ;
b [ modes . HARD _LIGHT ] = ( useNew ) ? 'hard-light' : 'source-over' ;
b [ modes . SOFT _LIGHT ] = ( useNew ) ? 'soft-light' : 'source-over' ;
b [ modes . DIFFERENCE ] = ( useNew ) ? 'difference' : 'source-over' ;
b [ modes . EXCLUSION ] = ( useNew ) ? 'exclusion' : 'source-over' ;
b [ modes . HUE ] = ( useNew ) ? 'hue' : 'source-over' ;
b [ modes . SATURATION ] = ( useNew ) ? 'saturation' : 'source-over' ;
b [ modes . COLOR ] = ( useNew ) ? 'color' : 'source-over' ;
b [ modes . LUMINOSITY ] = ( useNew ) ? 'luminosity' : 'source-over' ;
PIXI . blendModesCanvas = b ;
}
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
PIXI . BaseTextureCache = { } ;
PIXI . BaseTextureCacheIdGenerator = 0 ;
/ * *
* A texture stores the information that represents an image . All textures have a base texture .
*
* @ class BaseTexture
* @ uses EventTarget
* @ constructor
* @ param source { String } the source object ( image or canvas )
* @ 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
* /
PIXI . BaseTexture = function ( source , scaleMode )
{
/ * *
* The Resolution of the texture .
*
* @ property resolution
* @ type Number
* /
this . resolution = 1 ;
/ * *
* [ 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
*
* @ property scaleMode
* @ type { Number }
* @ default PIXI . scaleModes . LINEAR
* /
this . scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
/ * *
* [ read - only ] Set to true once the base texture has loaded
*
* @ property hasLoaded
* @ type Boolean
* @ readOnly
* /
this . hasLoaded = false ;
/ * *
* The image source that is used to create the texture .
*
* @ property source
* @ type Image
* /
this . source = source ;
this . _UID = PIXI . _UID ++ ;
/ * *
* Controls if RGB channels should be pre - multiplied by Alpha ( WebGL only )
*
* @ property premultipliedAlpha
* @ type Boolean
* @ default true
* /
this . premultipliedAlpha = true ;
// used for webGL
/ * *
* @ property _glTextures
* @ type Array
* @ private
* /
this . _glTextures = [ ] ;
/ * *
* Set this to true if a mipmap of this texture needs to be generated . This value needs to be set before the texture is used
* Also the texture must be a power of two size to work
*
* @ property mipmap
* @ type { Boolean }
* /
this . mipmap = false ;
/ * *
* @ property _dirty
* @ type Array
* @ private
* /
this . _dirty = [ true , true , true , true ] ;
if ( ! source )
{
return ;
}
if ( ( this . source . complete || this . source . getContext ) && this . source . width && this . source . height )
{
this . hasLoaded = true ;
this . width = this . source . naturalWidth || this . source . width ;
this . height = this . source . naturalHeight || this . source . height ;
this . dirty ( ) ;
}
/ * *
* A BaseTexture can be set to skip the rendering phase in the WebGL Sprite Batch .
*
* You may want to do this if you have a parent Sprite with no visible texture ( i . e . uses the internal ` __default ` texture )
* that has children that you do want to render , without causing a batch flush in the process .
*
* @ property skipRender
* @ type Boolean
* /
this . skipRender = false ;
/ * *
* @ property imageUrl
* @ type String
* /
this . imageUrl = null ;
/ * *
* @ property _powerOf2
* @ type Boolean
* @ private
* /
this . _powerOf2 = false ;
} ;
PIXI . BaseTexture . prototype . constructor = PIXI . BaseTexture ;
/ * *
* Forces this BaseTexture to be set as loaded , with the given width and height .
* Then calls BaseTexture . dirty .
* Important for when you don ' t want to modify the source object by forcing in ` complete ` or dimension properties it may not have .
*
* @ method forceLoaded
* @ param { number } width - The new width to force the BaseTexture to be .
* @ param { number } height - The new height to force the BaseTexture to be .
* /
PIXI . BaseTexture . prototype . forceLoaded = function ( width , height )
{
this . hasLoaded = true ;
this . width = width ;
this . height = height ;
this . dirty ( ) ;
} ;
/ * *
* Destroys this base texture
*
* @ method destroy
* /
PIXI . BaseTexture . prototype . destroy = function ( )
{
if ( this . imageUrl )
{
delete PIXI . BaseTextureCache [ this . imageUrl ] ;
delete PIXI . TextureCache [ this . imageUrl ] ;
this . imageUrl = null ;
if ( ! navigator . isCocoonJS ) this . source . src = '' ;
}
else if ( this . source )
{
PIXI . CanvasPool . removeByCanvas ( this . source ) ;
2016-02-18 14:41:53 +00:00
if ( this . source . _pixiId )
{
delete PIXI . BaseTextureCache [ this . source . _pixiId ] ;
}
2016-02-12 16:00:36 +00:00
}
this . source = null ;
this . unloadFromGPU ( ) ;
} ;
/ * *
* 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 ;
} ;
/ * *
* 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 ;
}
} ;
/ * *
* 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 ( ) ;
} ;
/ * *
* 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 .
*
* @ static
* @ method fromImage
* @ param imageUrl { String } The image url of the texture
* @ param crossorigin { Boolean }
* @ 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
* @ return { BaseTexture }
* /
PIXI . BaseTexture . fromImage = function ( imageUrl , crossorigin , scaleMode )
{
var baseTexture = PIXI . BaseTextureCache [ imageUrl ] ;
if ( crossorigin === undefined && imageUrl . indexOf ( 'data:' ) === - 1 ) crossorigin = true ;
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 ( ) ;
if ( crossorigin )
{
image . crossOrigin = '' ;
}
image . src = imageUrl ;
baseTexture = new PIXI . BaseTexture ( image , scaleMode ) ;
baseTexture . imageUrl = imageUrl ;
PIXI . BaseTextureCache [ imageUrl ] = baseTexture ;
// 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 ;
}
}
return baseTexture ;
} ;
/ * *
* Helper function that creates a base texture from the given canvas element .
*
* @ static
* @ method fromCanvas
* @ param canvas { Canvas } The canvas element source of the texture
* @ 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
* @ return { BaseTexture }
* /
PIXI . BaseTexture . fromCanvas = function ( canvas , scaleMode )
{
if ( ! canvas . _pixiId )
{
canvas . _pixiId = 'canvas_' + PIXI . TextureCacheIdGenerator ++ ;
}
if ( canvas . width === 0 )
{
canvas . width = 1 ;
}
if ( canvas . height === 0 )
{
canvas . height = 1 ;
}
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 = { } ;
/ * *
* TextureSilentFail is a boolean that defaults to ` false ` .
* If ` true ` then ` PIXI.Texture.setFrame ` will no longer throw an error if the texture dimensions are incorrect .
* Instead ` Texture.valid ` will be set to ` false ` ( # 1556 )
*
* @ type { boolean }
* /
PIXI . TextureSilentFail = false ;
PIXI . TextureCacheIdGenerator = 0 ;
/ * *
* A texture stores the information that represents an image or part of an image . It cannot be added
* 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 .
*
* @ 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
* @ param [ crop ] { Rectangle } The area of original texture
* @ param [ trim ] { Rectangle } Trimmed texture rectangle
* /
PIXI . Texture = function ( baseTexture , frame , crop , trim )
{
/ * *
* Does this Texture have any frame data assigned to it ?
*
* @ property noFrame
* @ type Boolean
* /
this . noFrame = false ;
if ( ! frame )
{
this . noFrame = true ;
frame = new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
}
if ( baseTexture instanceof PIXI . Texture )
{
baseTexture = baseTexture . baseTexture ;
}
/ * *
* The base texture that this texture uses .
*
* @ 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 ;
/ * *
* The texture trim data .
*
* @ property trim
* @ type Rectangle
* /
this . trim = trim ;
/ * *
* This will let the renderer know if the texture is valid . If it ' s not then it cannot be rendered .
*
* @ property valid
* @ type Boolean
* /
this . valid = false ;
/ * *
* Is this a tiling texture ? As used by the likes of a TilingSprite .
*
* @ property isTiling
* @ type Boolean
* /
this . isTiling = false ;
/ * *
* 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 ;
/ * *
* This will let a renderer know that a tinted parent has updated its texture .
*
* @ property requiresReTint
* @ type Boolean
* /
this . requiresReTint = false ;
/ * *
* The WebGL UV data cache .
*
* @ property _uvs
* @ type Object
* @ private
* /
this . _uvs = null ;
/ * *
* 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
* /
this . crop = crop || new PIXI . Rectangle ( 0 , 0 , 1 , 1 ) ;
if ( baseTexture . hasLoaded )
{
if ( this . noFrame ) frame = new PIXI . Rectangle ( 0 , 0 , baseTexture . width , baseTexture . height ) ;
this . setFrame ( frame ) ;
}
} ;
PIXI . Texture . prototype . constructor = PIXI . Texture ;
/ * *
* Called when the base texture is loaded
*
* @ method onBaseTextureLoaded
* @ private
* /
PIXI . Texture . prototype . onBaseTextureLoaded = function ( )
{
var baseTexture = this . baseTexture ;
if ( this . noFrame )
{
this . frame = new PIXI . Rectangle ( 0 , 0 , baseTexture . width , baseTexture . height ) ;
}
this . setFrame ( this . frame ) ;
} ;
/ * *
* Destroys this texture
*
* @ method destroy
* @ param destroyBase { Boolean } Whether to destroy the base texture as well
* /
PIXI . Texture . prototype . destroy = function ( destroyBase )
{
if ( destroyBase ) this . baseTexture . destroy ( ) ;
this . valid = false ;
} ;
/ * *
* Specifies the region of the baseTexture that this texture will use .
*
* @ method setFrame
* @ param frame { Rectangle } The frame of the texture to set it to
* /
PIXI . Texture . prototype . setFrame = function ( frame )
{
this . noFrame = false ;
this . frame = frame ;
this . width = frame . width ;
this . height = frame . height ;
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 ) )
{
if ( ! PIXI . TextureSilentFail )
{
throw new Error ( 'Texture Error: frame does not fit inside the base Texture dimensions ' + this ) ;
}
this . valid = false ;
return ;
}
this . valid = frame && frame . width && frame . height && this . baseTexture . source && this . baseTexture . hasLoaded ;
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 ;
}
if ( this . valid ) this . _updateUvs ( ) ;
} ;
/ * *
* Updates the internal WebGL UV cache .
*
* @ method _updateUvs
* @ private
* /
PIXI . Texture . prototype . _updateUvs = function ( )
{
if ( ! this . _uvs ) this . _uvs = new PIXI . TextureUvs ( ) ;
var frame = this . crop ;
var tw = this . baseTexture . width ;
var th = this . baseTexture . height ;
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 ;
} ;
/ * *
* 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 .
*
* @ static
* @ method fromImage
* @ param imageUrl { String } The image url of the texture
* @ param crossorigin { Boolean } Whether requests should be treated as crossorigin
* @ 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
* @ 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 ;
} ;
/ * *
* 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 .
*
* @ 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 ;
} ;
/ * *
* Helper function that creates a new a Texture based on the given canvas element .
*
* @ static
* @ method fromCanvas
* @ param canvas { Canvas } The canvas element source of the texture
* @ 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
* @ return { Texture }
* /
PIXI . Texture . fromCanvas = function ( canvas , scaleMode )
{
var baseTexture = PIXI . BaseTexture . fromCanvas ( canvas , scaleMode ) ;
return new PIXI . Texture ( baseTexture ) ;
} ;
/ * *
* Adds a texture to the global PIXI . TextureCache . This cache is shared across the whole PIXI object .
*
* @ static
* @ method addTextureToCache
* @ param texture { Texture } The Texture to add to the cache .
* @ param id { String } The id that the texture will be stored against .
* /
PIXI . Texture . addTextureToCache = function ( texture , id )
{
PIXI . TextureCache [ id ] = texture ;
} ;
/ * *
* Remove a texture from the global PIXI . TextureCache .
*
* @ static
* @ method removeTextureFromCache
* @ param id { String } The id of the texture to be removed
* @ return { Texture } The texture that was removed
* /
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 ;
this . y3 = 0 ;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* /
/ * *
* 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
*
* @ class RenderTexture
* @ extends Texture
* @ constructor
* @ param width { Number } The width of the render texture
* @ param height { Number } The height of the render texture
* @ param renderer { CanvasRenderer | WebGLRenderer } The renderer used for this RenderTexture
* @ 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
* @ param resolution { Number } The resolution of the texture being generated
* /
PIXI . RenderTexture = function ( width , height , renderer , scaleMode , resolution )
{
/ * *
* The with of the render texture
*
* @ property width
* @ type Number
* /
this . width = width || 100 ;
/ * *
* The height of the render texture
*
* @ property height
* @ type Number
* /
this . height = height || 100 ;
/ * *
* The Resolution of the texture .
*
* @ property resolution
* @ type Number
* /
this . resolution = resolution || 1 ;
/ * *
* The framing rectangle of the render texture
*
* @ property frame
* @ type Rectangle
* /
this . frame = new PIXI . Rectangle ( 0 , 0 , this . width * this . resolution , this . height * this . resolution ) ;
/ * *
* 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
* /
this . crop = new PIXI . Rectangle ( 0 , 0 , this . width * this . resolution , this . height * this . resolution ) ;
/ * *
* The base texture object that this texture uses
*
* @ property baseTexture
* @ type BaseTexture
* /
this . baseTexture = new PIXI . BaseTexture ( ) ;
this . baseTexture . width = this . width * this . resolution ;
this . baseTexture . height = this . height * this . resolution ;
this . baseTexture . _glTextures = [ ] ;
this . baseTexture . resolution = this . resolution ;
this . baseTexture . scaleMode = scaleMode || PIXI . scaleModes . DEFAULT ;
this . baseTexture . hasLoaded = true ;
PIXI . Texture . call ( this ,
this . baseTexture ,
new PIXI . Rectangle ( 0 , 0 , this . width * this . resolution , this . height * this . resolution )
) ;
/ * *
* The renderer this RenderTexture uses . A RenderTexture can only belong to one renderer at the moment if its webGL .
*
* @ property renderer
* @ type CanvasRenderer | WebGLRenderer
* /
this . renderer = renderer || PIXI . defaultRenderer ;
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
{
var gl = this . renderer . gl ;
this . baseTexture . _dirty [ gl . id ] = false ;
this . textureBuffer = new PIXI . FilterTexture ( gl , this . width , this . height , this . baseTexture . scaleMode ) ;
this . baseTexture . _glTextures [ gl . id ] = this . textureBuffer . texture ;
this . render = this . renderWebGL ;
this . projection = new PIXI . Point ( this . width * 0.5 , - this . height * 0.5 ) ;
}
else
{
this . render = this . renderCanvas ;
this . textureBuffer = new PIXI . CanvasBuffer ( this . width * this . resolution , this . height * this . resolution ) ;
this . baseTexture . source = this . textureBuffer . canvas ;
}
/ * *
* @ property valid
* @ type Boolean
* /
this . valid = true ;
this . tempMatrix = new Phaser . Matrix ( ) ;
this . _updateUvs ( ) ;
} ;
PIXI . RenderTexture . prototype = Object . create ( PIXI . Texture . prototype ) ;
PIXI . RenderTexture . prototype . constructor = PIXI . RenderTexture ;
/ * *
* Resizes the RenderTexture .
*
* @ 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 )
{
if ( width === this . width && height === this . height ) return ;
this . valid = ( width > 0 && height > 0 ) ;
this . width = width ;
this . height = height ;
this . frame . width = this . crop . width = width * this . resolution ;
this . frame . height = this . crop . height = height * this . resolution ;
if ( updateBase )
{
this . baseTexture . width = this . width * this . resolution ;
this . baseTexture . height = this . height * this . resolution ;
}
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
{
this . projection . x = this . width / 2 ;
this . projection . y = - this . height / 2 ;
}
if ( ! this . valid ) return ;
this . textureBuffer . resize ( this . width , this . height ) ;
} ;
/ * *
* Clears the RenderTexture .
*
* @ method clear
* /
PIXI . RenderTexture . prototype . clear = function ( )
{
if ( ! this . valid )
{
return ;
}
if ( this . renderer . type === PIXI . WEBGL _RENDERER )
{
this . renderer . gl . bindFramebuffer ( this . renderer . gl . FRAMEBUFFER , this . textureBuffer . frameBuffer ) ;
}
this . textureBuffer . clear ( ) ;
} ;
/ * *
* This function will draw the display object to the texture .
*
* @ method renderWebGL
* @ param displayObject { DisplayObject } The display object to render this texture on
* @ 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
* @ private
* /
PIXI . RenderTexture . prototype . renderWebGL = function ( displayObject , matrix , clear )
{
if ( ! this . valid || displayObject . alpha === 0 )
{
return ;
}
// Let's 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 ) ;
// Time to update all the children of the displayObject with the new matrix.
for ( var i = 0 ; i < displayObject . children . length ; i ++ )
{
displayObject . children [ i ] . updateTransform ( ) ;
}
// 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 ) ;
if ( clear )
{
this . textureBuffer . clear ( ) ;
}
this . renderer . spriteBatch . dirty = true ;
this . renderer . renderDisplayObject ( displayObject , this . projection , this . textureBuffer . frameBuffer , matrix ) ;
this . renderer . spriteBatch . dirty = true ;
} ;
/ * *
* This function will draw the display object to the texture .
*
* @ method renderCanvas
* @ param displayObject { DisplayObject } The display object to render this texture on
* @ 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
* @ private
* /
PIXI . RenderTexture . prototype . renderCanvas = function ( displayObject , matrix , clear )
{
if ( ! this . valid || displayObject . alpha === 0 )
{
return ;
}
// Let's 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 ( ) ;
if ( matrix )
{
wt . append ( matrix ) ;
}
// Time to update all the children of the displayObject with the new matrix (what new matrix? there isn't one!)
for ( var i = 0 ; i < displayObject . children . length ; i ++ )
{
displayObject . children [ i ] . updateTransform ( ) ;
}
if ( clear )
{
this . textureBuffer . clear ( ) ;
}
var realResolution = this . renderer . resolution ;
this . renderer . resolution = this . resolution ;
this . renderer . renderDisplayObject ( displayObject , this . textureBuffer . context , matrix ) ;
this . renderer . resolution = realResolution ;
} ;
/ * *
* Will return a HTML Image of the texture
*
* @ method getImage
* @ return { Image }
* /
PIXI . RenderTexture . prototype . getImage = function ( )
{
var image = new Image ( ) ;
image . src = this . getBase64 ( ) ;
return image ;
} ;
/ * *
* Will return a base64 encoded string of this texture . It works by calling RenderTexture . getCanvas and then running toDataURL on that .
*
* @ method getBase64
* @ return { String } A base64 encoded string of the texture .
* /
PIXI . RenderTexture . prototype . getBase64 = function ( )
{
return this . getCanvas ( ) . toDataURL ( ) ;
} ;
/ * *
* 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 .
* /
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 ) ;
canvasData . data . set ( webGLPixels ) ;
tempCanvas . context . putImageData ( canvasData , 0 , 0 ) ;
return tempCanvas . canvas ;
}
else
{
return this . textureBuffer . canvas ;
}
} ;
/ * *
* @ 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
* @ type Array ( Filter )
* @ private
* /
this . passes = [ this ] ;
/ * *
* @ property shaders
* @ type Array ( Shader )
* @ 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 ;
}
} ;
/ *
PIXI . AbstractFilter . prototype . apply = function ( frameBuffer )
{
// TODO :)
} ;
* /
/ * *
* @ 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 ) ;
/ * *
* The texture of the strip
*
* @ property texture
* @ type Texture
* /
this . texture = texture ;
// set up the main bits..
this . uvs = new PIXI . Float32Array ( [ 0 , 1 ,
1 , 1 ,
1 , 0 ,
0 , 1 ] ) ;
this . vertices = new PIXI . Float32Array ( [ 0 , 0 ,
100 , 0 ,
100 , 100 ,
0 , 100 ] ) ;
this . colors = new PIXI . Float32Array ( [ 1 , 1 , 1 , 1 ] ) ;
this . indices = new PIXI . Uint16Array ( [ 0 , 1 , 2 , 3 ] ) ;
/ * *
* Whether the strip is dirty or not
*
* @ property dirty
* @ type Boolean
* /
this . dirty = true ;
/ * *
* 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 ;
/ * *
* Triangles in canvas mode are automatically antialiased , use this value to force triangles to overlap a bit with each other .
*
* @ property canvasPadding
* @ type Number
* /
this . canvasPadding = 0 ;
this . drawMode = PIXI . Strip . DrawModes . TRIANGLE _STRIP ;
} ;
// 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 . vertices , 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 ;
var drawMode = this . drawMode === PIXI . Strip . DrawModes . TRIANGLE _STRIP ? gl . TRIANGLE _STRIP : gl . TRIANGLES ;
// gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mat4Real);
renderSession . blendModeManager . setBlendMode ( this . blendMode ) ;
// 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 ) ;
gl . uniform1f ( shader . alpha , this . worldAlpha ) ;
if ( ! this . dirty )
{
gl . bindBuffer ( gl . ARRAY _BUFFER , this . _vertexBuffer ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , this . vertices ) ;
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 ) ;
// 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 ] ) ;
}
// 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 . vertices , 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 ) ;
// 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 ] ) ;
}
// 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 ( drawMode , this . indices . length , gl . UNSIGNED _SHORT , 0 ) ;
} ;
PIXI . Strip . prototype . _renderCanvas = function ( renderSession )
{
var context = renderSession . context ;
var transform = this . worldTransform ;
2016-04-22 13:45:11 +00:00
var tx = ( transform . tx * renderSession . resolution ) + renderSession . shakeX ;
var ty = ( transform . ty * renderSession . resolution ) + renderSession . shakeY ;
2016-02-12 16:00:36 +00:00
if ( renderSession . roundPixels )
{
2016-04-22 13:45:11 +00:00
context . setTransform ( transform . a , transform . b , transform . c , transform . d , tx | 0 , ty | 0 ) ;
2016-02-12 16:00:36 +00:00
}
else
{
2016-04-22 13:45:11 +00:00
context . setTransform ( transform . a , transform . b , transform . c , transform . d , tx , ty ) ;
2016-02-12 16:00:36 +00:00
}
if ( this . drawMode === PIXI . Strip . DrawModes . TRIANGLE _STRIP )
{
this . _renderCanvasTriangleStrip ( context ) ;
}
else
{
this . _renderCanvasTriangles ( context ) ;
}
} ;
PIXI . Strip . prototype . _renderCanvasTriangleStrip = function ( context )
{
// draw triangles!!
var vertices = this . vertices ;
var uvs = this . uvs ;
var length = vertices . length / 2 ;
this . count ++ ;
for ( var i = 0 ; i < length - 2 ; i ++ ) {
// draw some triangles!
var index = i * 2 ;
this . _renderCanvasDrawTriangle ( context , vertices , uvs , index , ( index + 2 ) , ( index + 4 ) ) ;
}
} ;
PIXI . Strip . prototype . _renderCanvasTriangles = function ( context )
{
// draw triangles!!
var vertices = this . vertices ;
var uvs = this . uvs ;
var indices = this . indices ;
var length = indices . length ;
this . count ++ ;
for ( var i = 0 ; i < length ; i += 3 ) {
// draw some triangles!
var index0 = indices [ i ] * 2 , index1 = indices [ i + 1 ] * 2 , index2 = indices [ i + 2 ] * 2 ;
this . _renderCanvasDrawTriangle ( context , vertices , uvs , index0 , index1 , index2 ) ;
}
} ;
PIXI . Strip . prototype . _renderCanvasDrawTriangle = function ( context , vertices , uvs , index0 , index1 , index2 )
{
var textureSource = this . texture . baseTexture . source ;
var textureWidth = this . texture . width ;
var textureHeight = this . texture . height ;
var x0 = vertices [ index0 ] , x1 = vertices [ index1 ] , x2 = vertices [ index2 ] ;
var y0 = vertices [ index0 + 1 ] , y1 = vertices [ index1 + 1 ] , y2 = vertices [ index2 + 1 ] ;
var u0 = uvs [ index0 ] * textureWidth , u1 = uvs [ index1 ] * textureWidth , u2 = uvs [ index2 ] * textureWidth ;
var v0 = uvs [ index0 + 1 ] * textureHeight , v1 = uvs [ index1 + 1 ] * textureHeight , v2 = uvs [ index2 + 1 ] * textureHeight ;
if ( this . canvasPadding > 0 ) {
var paddingX = this . canvasPadding / this . worldTransform . a ;
var paddingY = this . canvasPadding / this . worldTransform . d ;
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 + paddingX ) ;
y0 = centerY + ( normY / dist ) * ( dist + paddingY ) ;
//
normX = x1 - centerX ;
normY = y1 - centerY ;
dist = Math . sqrt ( normX * normX + normY * normY ) ;
x1 = centerX + ( normX / dist ) * ( dist + paddingX ) ;
y1 = centerY + ( normY / dist ) * ( dist + paddingY ) ;
normX = x2 - centerX ;
normY = y2 - centerY ;
dist = Math . sqrt ( normX * normX + normY * normY ) ;
x2 = centerX + ( normX / dist ) * ( dist + paddingX ) ;
y2 = centerY + ( normY / dist ) * ( dist + paddingY ) ;
}
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 ) ;
context . drawImage ( textureSource , 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 vertices = strip . vertices ;
var length = vertices . length / 2 ;
this . count ++ ;
context . beginPath ( ) ;
for ( var i = 1 ; i < length - 2 ; i ++ )
{
// draw some triangles!
var index = i * 2 ;
var x0 = vertices [ index ] , x1 = vertices [ index + 2 ] , x2 = vertices [ index + 4 ] ;
var y0 = vertices [ index + 1 ] , y1 = vertices [ index + 3 ] , y2 = vertices [ index + 5 ] ;
context . moveTo ( x0 , y0 ) ;
context . lineTo ( x1 , y1 ) ;
context . lineTo ( x2 , y2 ) ;
}
context . fillStyle = '#FF0000' ;
context . fill ( ) ;
context . closePath ( ) ;
} ;
/ *
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 ;
} ;
* /
/ * *
* When the texture is updated , this event will fire to update the scale and frame
*
* @ method onTextureUpdate
* @ param event
* @ private
* /
PIXI . Strip . prototype . onTextureUpdate = function ( )
{
this . updateFrame = true ;
} ;
/ * *
* Returns the bounds of the mesh as a rectangle . The bounds calculation takes the worldTransform into account .
*
* @ method getBounds
* @ param matrix { Matrix } the transformation matrix of the sprite
* @ return { Rectangle } the framing rectangle
* /
PIXI . Strip . prototype . getBounds = function ( matrix )
{
var worldTransform = matrix || this . worldTransform ;
var a = worldTransform . a ;
var b = worldTransform . b ;
var c = worldTransform . c ;
var d = worldTransform . d ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
var maxX = - Infinity ;
var maxY = - Infinity ;
var minX = Infinity ;
var minY = Infinity ;
var vertices = this . vertices ;
for ( var i = 0 , n = vertices . length ; i < n ; i += 2 )
{
var rawX = vertices [ i ] , rawY = vertices [ i + 1 ] ;
var x = ( a * rawX ) + ( c * rawY ) + tx ;
var y = ( d * rawY ) + ( b * rawX ) + ty ;
minX = x < minX ? x : minX ;
minY = y < minY ? y : minY ;
maxX = x > maxX ? x : maxX ;
maxY = y > maxY ? y : maxY ;
}
if ( minX === - Infinity || maxY === Infinity )
{
return PIXI . EmptyRectangle ;
}
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 ;
} ;
/ * *
* Different drawing buffer modes supported
*
* @ property
* @ type { { TRIANGLE _STRIP : number , TRIANGLES : number } }
* @ static
* /
PIXI . Strip . DrawModes = {
TRIANGLE _STRIP : 0 ,
TRIANGLES : 1
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/ @Doormat23
* @ copyright Mat Groves , Rovanion Luckey
* /
/ * *
*
* @ class Rope
* @ constructor
* @ extends Strip
* @ param { Texture } texture - The texture to use on the rope .
* @ param { Array } points - An array of { PIXI . Point } .
*
* /
PIXI . Rope = function ( texture , points )
{
PIXI . Strip . call ( this , texture ) ;
this . points = points ;
this . vertices = 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 ) ;
this . refresh ( ) ;
} ;
// constructor
PIXI . Rope . prototype = Object . create ( PIXI . Strip . prototype ) ;
PIXI . Rope . prototype . constructor = PIXI . Rope ;
/ *
* Refreshes
*
* @ method refresh
* /
PIXI . Rope . prototype . refresh = function ( )
{
var points = this . points ;
if ( points . length < 1 ) return ;
var uvs = this . uvs ;
var lastPoint = points [ 0 ] ;
var indices = this . indices ;
var colors = this . colors ;
this . count -= 0.2 ;
uvs [ 0 ] = 0 ;
uvs [ 1 ] = 0 ;
uvs [ 2 ] = 0 ;
uvs [ 3 ] = 1 ;
colors [ 0 ] = 1 ;
colors [ 1 ] = 1 ;
indices [ 0 ] = 0 ;
indices [ 1 ] = 1 ;
var total = points . length ,
point , index , amount ;
for ( var i = 1 ; i < total ; i ++ )
{
point = points [ i ] ;
index = i * 4 ;
// time to do some smart drawing!
amount = i / ( total - 1 ) ;
if ( i % 2 )
{
uvs [ index ] = amount ;
uvs [ index + 1 ] = 0 ;
uvs [ index + 2 ] = amount ;
uvs [ index + 3 ] = 1 ;
}
else
{
uvs [ index ] = amount ;
uvs [ index + 1 ] = 0 ;
uvs [ index + 2 ] = amount ;
uvs [ index + 3 ] = 1 ;
}
index = i * 2 ;
colors [ index ] = 1 ;
colors [ index + 1 ] = 1 ;
index = i * 2 ;
indices [ index ] = index ;
indices [ index + 1 ] = index + 1 ;
lastPoint = point ;
}
} ;
/ *
* Updates the object transform for rendering
*
* @ method updateTransform
* @ private
* /
PIXI . Rope . prototype . updateTransform = function ( )
{
var points = this . points ;
if ( points . length < 1 ) return ;
var lastPoint = points [ 0 ] ;
var nextPoint ;
var perp = { x : 0 , y : 0 } ;
this . count -= 0.2 ;
var vertices = this . vertices ;
var total = points . length ,
point , index , ratio , perpLength , num ;
for ( var i = 0 ; i < total ; i ++ )
{
point = points [ i ] ;
index = i * 4 ;
if ( i < points . length - 1 )
{
nextPoint = points [ i + 1 ] ;
}
else
{
nextPoint = point ;
}
perp . y = - ( nextPoint . x - lastPoint . x ) ;
perp . x = nextPoint . y - lastPoint . y ;
ratio = ( 1 - ( i / ( total - 1 ) ) ) * 10 ;
if ( ratio > 1 ) ratio = 1 ;
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 ;
perp . x *= num ;
perp . y *= num ;
vertices [ index ] = point . x + perp . x ;
vertices [ index + 1 ] = point . y + perp . y ;
vertices [ index + 2 ] = point . x - perp . x ;
vertices [ index + 3 ] = point . y - perp . y ;
lastPoint = point ;
}
PIXI . DisplayObjectContainer . prototype . updateTransform . call ( this ) ;
} ;
/ *
* Sets the texture that the Rope will use
*
* @ method setTexture
* @ param texture { Texture } the texture that will be used
* /
PIXI . Rope . prototype . setTexture = function ( texture )
{
// stop current texture
this . texture = texture ;
//this.updateFrame = true;
} ;
/ * *
* @ author Mat Groves http : //matgroves.com/
* /
/ * *
* A tiling sprite is a fast way of rendering a tiling image
*
* @ class TilingSprite
* @ extends Sprite
* @ 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 width of the tiling sprite
*
* @ property width
* @ type Number
* /
this . _width = width || 128 ;
/ * *
* The height of the tiling sprite
*
* @ property height
* @ type Number
* /
this . _height = height || 128 ;
/ * *
* 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 ) ;
/ * *
* The offset position of the image that is being tiled
*
* @ property tilePosition
* @ type Point
* /
this . tilePosition = new PIXI . Point ( ) ;
/ * *
* 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 ;
/ * *
* If enabled a green rectangle will be drawn behind the generated tiling texture , allowing you to visually
* debug the texture being used .
*
* @ property textureDebug
* @ type Boolean
* /
this . textureDebug = false ;
/ * *
* The blend mode to be applied to the sprite
*
* @ property blendMode
* @ type Number
* @ default PIXI . blendModes . NORMAL ;
* /
this . blendMode = PIXI . blendModes . NORMAL ;
/ * *
* The CanvasBuffer object that the tiled texture is drawn to .
*
* @ property canvasBuffer
* @ type PIXI . CanvasBuffer
* /
this . canvasBuffer = null ;
/ * *
* An internal Texture object that holds the tiling texture that was generated from TilingSprite . texture .
*
* @ property tilingTexture
* @ type PIXI . Texture
* /
this . tilingTexture = null ;
/ * *
* The Context fill pattern that is used to draw the TilingSprite in Canvas mode only ( will be null in WebGL ) .
*
* @ property tilePattern
* @ type PIXI . Texture
* /
this . tilePattern = null ;
/ * *
* If true the TilingSprite will run generateTexture on its * * next * * render pass .
* This is set by the likes of Phaser . LoadTexture . setFrame .
*
* @ property refreshTexture
* @ type Boolean
* @ default true
* /
this . refreshTexture = true ;
this . frameWidth = 0 ;
this . frameHeight = 0 ;
} ;
PIXI . TilingSprite . prototype = Object . create ( PIXI . Sprite . prototype ) ;
PIXI . TilingSprite . prototype . constructor = PIXI . TilingSprite ;
PIXI . TilingSprite . prototype . setTexture = function ( texture )
{
if ( this . texture !== texture )
{
this . texture = texture ;
this . refreshTexture = true ;
this . cachedTint = 0xFFFFFF ;
}
} ;
/ * *
* Renders the object using the WebGL renderer
*
* @ method _renderWebGL
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . TilingSprite . prototype . _renderWebGL = function ( renderSession )
{
if ( ! this . visible || ! this . renderable || this . alpha === 0 )
{
return ;
}
if ( this . _mask )
{
renderSession . spriteBatch . stop ( ) ;
renderSession . maskManager . pushMask ( this . mask , renderSession ) ;
renderSession . spriteBatch . start ( ) ;
}
if ( this . _filters )
{
renderSession . spriteBatch . flush ( ) ;
renderSession . filterManager . pushFilter ( this . _filterBlock ) ;
}
if ( this . refreshTexture )
{
this . generateTilingTexture ( true , renderSession ) ;
if ( this . tilingTexture )
{
if ( this . tilingTexture . needsUpdate )
{
renderSession . renderer . updateTexture ( this . tilingTexture . baseTexture ) ;
this . tilingTexture . needsUpdate = false ;
}
}
else
{
return ;
}
}
renderSession . spriteBatch . renderTilingSprite ( this ) ;
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderWebGL ( renderSession ) ;
}
renderSession . spriteBatch . stop ( ) ;
if ( this . _filters )
{
renderSession . filterManager . popFilter ( ) ;
}
if ( this . _mask )
{
renderSession . maskManager . popMask ( this . _mask , renderSession ) ;
}
renderSession . spriteBatch . start ( ) ;
} ;
/ * *
* Renders the object using the Canvas renderer
*
* @ method _renderCanvas
* @ param renderSession { RenderSession }
* @ private
* /
PIXI . TilingSprite . prototype . _renderCanvas = function ( renderSession )
{
if ( ! this . visible || ! this . renderable || this . alpha === 0 )
{
return ;
}
var context = renderSession . context ;
if ( this . _mask )
{
renderSession . maskManager . pushMask ( this . _mask , renderSession ) ;
}
context . globalAlpha = this . worldAlpha ;
var wt = this . worldTransform ;
var resolution = renderSession . resolution ;
2016-04-22 13:45:11 +00:00
var tx = ( wt . tx * resolution ) + renderSession . shakeX ;
var ty = ( wt . ty * resolution ) + renderSession . shakeY ;
2016-02-12 16:00:36 +00:00
2016-04-22 13:45:11 +00:00
context . setTransform ( wt . a * resolution , wt . b * resolution , wt . c * resolution , wt . d * resolution , tx , ty ) ;
2016-02-12 16:00:36 +00:00
if ( this . refreshTexture )
{
this . generateTilingTexture ( false , renderSession ) ;
if ( this . tilingTexture )
{
this . tilePattern = context . createPattern ( this . tilingTexture . baseTexture . source , 'repeat' ) ;
}
else
{
return ;
}
}
var sessionBlendMode = renderSession . currentBlendMode ;
// Check blend mode
if ( this . blendMode !== renderSession . currentBlendMode )
{
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 ;
// Translate
context . scale ( tileScale . x , tileScale . y ) ;
context . translate ( tilePosition . x + ( this . anchor . x * - this . _width ) , tilePosition . y + ( this . anchor . y * - this . _height ) ) ;
context . fillStyle = this . tilePattern ;
var tx = - tilePosition . x ;
var ty = - tilePosition . y ;
var tw = this . _width / tileScale . x ;
var th = this . _height / tileScale . y ;
// Allow for pixel rounding
if ( renderSession . roundPixels )
{
tx |= 0 ;
ty |= 0 ;
tw |= 0 ;
th |= 0 ;
}
context . fillRect ( tx , ty , tw , th ) ;
// Translate back again
context . scale ( 1 / tileScale . x , 1 / tileScale . y ) ;
context . translate ( - tilePosition . x + ( this . anchor . x * this . _width ) , - tilePosition . y + ( this . anchor . y * this . _height ) ) ;
if ( this . _mask )
{
renderSession . maskManager . popMask ( renderSession ) ;
}
for ( var i = 0 ; i < this . children . length ; i ++ )
{
this . children [ i ] . _renderCanvas ( renderSession ) ;
}
// Reset blend mode
if ( sessionBlendMode !== this . blendMode )
{
renderSession . currentBlendMode = sessionBlendMode ;
context . globalCompositeOperation = PIXI . blendModesCanvas [ sessionBlendMode ] ;
}
} ;
/ * *
* 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!
} ;
/ * *
*
* @ method generateTilingTexture
*
* @ param forcePowerOfTwo { Boolean } Whether we want to force the texture to be a power of two
* @ param renderSession { RenderSession }
* /
PIXI . TilingSprite . prototype . generateTilingTexture = function ( forcePowerOfTwo , renderSession )
{
if ( ! this . texture . baseTexture . hasLoaded )
{
return ;
}
var texture = this . texture ;
var frame = texture . frame ;
2016-04-14 12:23:44 +00:00
var targetWidth = this . _frame . sourceSizeW || this . _frame . width ;
var targetHeight = this . _frame . sourceSizeH || this . _frame . height ;
2016-02-12 16:00:36 +00:00
var dx = 0 ;
var dy = 0 ;
if ( this . _frame . trimmed )
{
dx = this . _frame . spriteSourceSizeX ;
dy = this . _frame . spriteSourceSizeY ;
}
if ( forcePowerOfTwo )
{
targetWidth = PIXI . getNextPowerOfTwo ( targetWidth ) ;
targetHeight = PIXI . getNextPowerOfTwo ( targetHeight ) ;
}
if ( this . canvasBuffer )
{
this . canvasBuffer . resize ( targetWidth , targetHeight ) ;
this . tilingTexture . baseTexture . width = targetWidth ;
this . tilingTexture . baseTexture . height = targetHeight ;
this . tilingTexture . needsUpdate = true ;
}
else
{
this . canvasBuffer = new PIXI . CanvasBuffer ( targetWidth , targetHeight ) ;
this . tilingTexture = PIXI . Texture . fromCanvas ( this . canvasBuffer . canvas ) ;
this . tilingTexture . isTiling = true ;
this . tilingTexture . needsUpdate = true ;
}
if ( this . textureDebug )
{
this . canvasBuffer . context . strokeStyle = '#00ff00' ;
this . canvasBuffer . context . strokeRect ( 0 , 0 , targetWidth , targetHeight ) ;
}
// If a sprite sheet we need this:
var w = texture . crop . width ;
var h = texture . crop . height ;
if ( w !== targetWidth || h !== targetHeight )
{
w = targetWidth ;
h = targetHeight ;
}
this . canvasBuffer . context . drawImage ( texture . baseTexture . source ,
texture . crop . x ,
texture . crop . y ,
texture . crop . width ,
texture . crop . height ,
dx ,
dy ,
w ,
h ) ;
this . tileScaleOffset . x = frame . width / targetWidth ;
this . tileScaleOffset . y = frame . height / targetHeight ;
this . refreshTexture = false ;
this . tilingTexture . baseTexture . _powerOf2 = true ;
} ;
/ * *
* 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 ;
var b = worldTransform . b ;
var c = worldTransform . c ;
var d = worldTransform . d ;
var tx = worldTransform . tx ;
var ty = worldTransform . ty ;
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 ;
} ;
PIXI . TilingSprite . prototype . destroy = function ( ) {
PIXI . Sprite . prototype . destroy . call ( this ) ;
if ( this . canvasBuffer )
{
this . canvasBuffer . destroy ( ) ;
this . canvasBuffer = null ;
}
this . tileScale = null ;
this . tileScaleOffset = null ;
this . tilePosition = null ;
if ( this . tilingTexture )
{
this . tilingTexture . destroy ( true ) ;
this . tilingTexture = null ;
}
} ;
/ * *
* 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 ) {
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 ;
}
} ) ;
/ * *
* @ 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 ) {
define ( 'PIXI' , ( function ( ) { return root . PIXI = PIXI ; } ) ( ) ) ;
} else {
root . PIXI = PIXI ;
}
return PIXI ;
} ) . call ( this ) ;