Upgraded to Pixi.js 1.4.4

This commit is contained in:
photonstorm
2014-02-06 00:19:46 +00:00
parent 68d5c73fea
commit 9737710200
75 changed files with 5794 additions and 3786 deletions
+5 -8
View File
@@ -1,11 +1,11 @@
![Phaser Logo](http://www.photonstorm.com/wp-content/uploads/2013/09/phaser_10_release.jpg)
Phaser 1.1.5-dev
================
Phaser 1.2-dev
==============
Phaser is a fast, free and fun open source game framework for making desktop and mobile browser HTML5 games. It uses [Pixi.js](https://github.com/GoodBoyDigital/pixi.js/) internally for fast 2D Canvas and WebGL rendering.
Version: 1.1.5 "Saldaea" - Released: -in development-
Version: 1.2 "Shienar" - Released: -in development-
By Richard Davey, [Photon Storm](http://www.photonstorm.com)
@@ -57,10 +57,11 @@ There is also an [un-official Getting Started Guide](http://www.antonoffplus.com
Change Log
----------
Version 1.1.5 - "Saldaea" - -in development-
Version 1.2 - "Shienar" - -in development-
Significant API changes:
* Upgraded to Pixi.js 1.4.4
New features:
@@ -224,10 +225,6 @@ Road Map
Here is what's on our road map for the coming months:
Version 1.2 ("Shienar")
* Update to Pixi 1.4 - this newly released build has lots of internal changes and new features we want to take advantage of.
Version 1.3 ("Tarabon")
* Enhance the State Management, so you can perform non-destructive State swaps and persistence.
+63
View File
@@ -0,0 +1,63 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* Holds all information related to an Interaction event
*
* @class InteractionData
* @constructor
*/
PIXI.InteractionData = function()
{
/**
* This point stores the global coords of where the touch/mouse event happened
*
* @property global
* @type Point
*/
this.global = new PIXI.Point();
// this is here for legacy... but will remove
this.local = new PIXI.Point();
/**
* The target Sprite that was interacted with
*
* @property target
* @type Sprite
*/
this.target = null;
/**
* When passed to an event handler, this will be the original DOM Event that was captured
*
* @property originalEvent
* @type Event
*/
this.originalEvent = null;
};
/**
* This will return the local coordinates of the specified displayObject for this InteractionData
*
* @method getLocalPosition
* @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off
* @return {Point} A point containing the coordinates of the InteractionData position relative to the DisplayObject
*/
PIXI.InteractionData.prototype.getLocalPosition = function(displayObject)
{
var worldTransform = displayObject.worldTransform;
var global = this.global;
// do a cheeky transform to get the mouse coords;
var a00 = worldTransform.a, a01 = worldTransform.b, a02 = worldTransform.tx,
a10 = worldTransform.c, a11 = worldTransform.d, a12 = worldTransform.ty,
id = 1 / (a00 * a11 + a01 * -a10);
// set the mouse coords...
return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id,
a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id);
};
// constructor
PIXI.InteractionData.prototype.constructor = PIXI.InteractionData;
+139 -137
View File
@@ -4,6 +4,7 @@
/**
* The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive
* if its interactive parameter is set to true
* This manager also supports multitouch.
*
* @class InteractionManager
@@ -13,7 +14,7 @@
PIXI.InteractionManager = function(stage)
{
/**
* a refference to the stage
* a reference to the stage
*
* @property stage
* @type Stage
@@ -38,7 +39,6 @@ PIXI.InteractionManager = function(stage)
// helpers
this.tempPoint = new PIXI.Point();
//this.tempMatrix = mat3.create();
this.mouseoverEnabled = true;
@@ -58,6 +58,10 @@ PIXI.InteractionManager = function(stage)
this.onTouchEnd = this.onTouchEnd.bind(this);
this.onTouchMove = this.onTouchMove.bind(this);
this.last = 0;
this.currentCursorStyle = 'inherit';
this.mouseOut = false;
};
// constructor
@@ -124,36 +128,24 @@ PIXI.InteractionManager.prototype.setTarget = function(target)
this.setTargetDomElement( target.view );
}
document.body.addEventListener('mouseup', this.onMouseUp, true);
};
/**
* Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM
* elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element
* Sets the DOM element which will receive mouse/touch events. This is useful for when you have other DOM
* elements on top of the renderers Canvas element. With this you'll be able to delegate another DOM element
* to receive those events
*
* @method setTargetDomElement
* @param domElement {DOMElement} the dom element which will receive mouse and touch events
* @param domElement {DOMElement} the DOM element which will receive mouse and touch events
* @private
*/
PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement)
{
//remove previouse listeners
if( this.interactionDOMElement !== null )
{
this.interactionDOMElement.style['-ms-content-zooming'] = '';
this.interactionDOMElement.style['-ms-touch-action'] = '';
this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true);
this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true);
this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true);
// aint no multi touch just yet!
this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true);
this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true);
this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true);
}
this.removeEvents();
if (window.navigator.msPointerEnabled)
@@ -175,6 +167,30 @@ PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement)
domElement.addEventListener('touchstart', this.onTouchStart, true);
domElement.addEventListener('touchend', this.onTouchEnd, true);
domElement.addEventListener('touchmove', this.onTouchMove, true);
document.body.addEventListener('mouseup', this.onMouseUp, true);
};
PIXI.InteractionManager.prototype.removeEvents = function()
{
if(!this.interactionDOMElement)return;
this.interactionDOMElement.style['-ms-content-zooming'] = '';
this.interactionDOMElement.style['-ms-touch-action'] = '';
this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true);
this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true);
this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true);
// aint no multi touch just yet!
this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true);
this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true);
this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true);
this.interactionDOMElement = null;
document.body.removeEventListener('mouseup', this.onMouseUp, true);
};
/**
@@ -190,7 +206,7 @@ PIXI.InteractionManager.prototype.update = function()
// frequency of 30fps??
var now = Date.now();
var diff = now - this.last;
diff = (diff * 30) / 1000;
diff = (diff * PIXI.INTERACTION_FREQUENCY ) / 1000;
if(diff < 1)return;
this.last = now;
//
@@ -199,7 +215,7 @@ PIXI.InteractionManager.prototype.update = function()
// ok.. so mouse events??
// yes for now :)
// OPTIMSE - how often to check??
// OPTIMISE - how often to check??
if(this.dirty)
{
this.dirty = false;
@@ -220,7 +236,10 @@ PIXI.InteractionManager.prototype.update = function()
// loop through interactive objects!
var length = this.interactiveItems.length;
this.interactionDOMElement.style.cursor = 'inherit';
var cursor = 'inherit';
var over = false;
for (i = 0; i < length; i++)
{
@@ -232,42 +251,55 @@ PIXI.InteractionManager.prototype.update = function()
// OPTIMISATION - only calculate every time if the mousemove function exists..
// OK so.. does the object have any other interactive functions?
// hit-test the clip!
if(item.mouseover || item.mouseout || item.buttonMode)
// if(item.mouseover || item.mouseout || item.buttonMode)
// {
// ok so there are some functions so lets hit test it..
item.__hit = this.hitTest(item, this.mouse);
this.mouse.target = item;
// ok so deal with interactions..
// looks like there was a hit!
if(item.__hit && !over)
{
// ok so there are some functions so lets hit test it..
item.__hit = this.hitTest(item, this.mouse);
this.mouse.target = item;
// ok so deal with interactions..
// loks like there was a hit!
if(item.__hit)
if(item.buttonMode) cursor = item.defaultCursor;
if(!item.interactiveChildren)over = true;
if(!item.__isOver)
{
if(item.buttonMode) this.interactionDOMElement.style.cursor = item.defaultCursor;
if(!item.__isOver)
{
if(item.mouseover)item.mouseover(this.mouse);
item.__isOver = true;
// just the one!
//break;
if(item.mouseover)item.mouseover(this.mouse);
item.__isOver = true;
}
}
else
//break;
}
else
{
if(item.__isOver)
{
if(item.__isOver)
{
// roll out!
if(item.mouseout)item.mouseout(this.mouse);
item.__isOver = false;
}
// roll out!
if(item.mouseout)item.mouseout(this.mouse);
item.__isOver = false;
}
}
// }
// --->
}
if( this.currentCursorStyle !== cursor )
{
this.currentCursorStyle = cursor;
this.interactionDOMElement.style.cursor = cursor;
}
};
/**
* Is called when the mouse moves accross the renderer element
* Is called when the mouse moves across the renderer element
*
* @method onMouseMove
* @param event {Event} The DOM event of the mouse moving
@@ -307,7 +339,9 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event)
{
this.mouse.originalEvent = event || window.event; //IE uses window.event
// loop through inteaction tree...
if(PIXI.AUTO_PREVENT_DEFAULT)this.mouse.originalEvent.preventDefault();
// loop through interaction tree...
// hit test each item! ->
// get interactive items under point??
//stage.__i
@@ -337,7 +371,13 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event)
}
};
/**
* Is called when the mouse button is moved out of the renderer element
*
* @method onMouseDown
* @param event {Event} The DOM event of a mouse button being moved out
* @private
*/
PIXI.InteractionManager.prototype.onMouseOut = function()
{
var length = this.interactiveItems.length;
@@ -347,7 +387,6 @@ PIXI.InteractionManager.prototype.onMouseOut = function()
for (var i = 0; i < length; i++)
{
var item = this.interactiveItems[i];
if(item.__isOver)
{
this.mouse.target = item;
@@ -355,6 +394,12 @@ PIXI.InteractionManager.prototype.onMouseOut = function()
item.__isOver = false;
}
}
this.mouseOut = true;
// move the mouse to an impossible position
this.mouse.global.x = -10000;
this.mouse.global.y = -10000;
};
/**
@@ -366,6 +411,7 @@ PIXI.InteractionManager.prototype.onMouseOut = function()
*/
PIXI.InteractionManager.prototype.onMouseUp = function(event)
{
this.mouse.originalEvent = event || window.event; //IE uses window.event
var length = this.interactiveItems.length;
@@ -375,55 +421,57 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event)
{
var item = this.interactiveItems[i];
if(item.mouseup || item.mouseupoutside || item.click)
//if(item.mouseup || item.mouseupoutside || item.click)
//{
item.__hit = this.hitTest(item, this.mouse);
if(item.__hit && !up)
{
item.__hit = this.hitTest(item, this.mouse);
if(item.__hit && !up)
//call the function!
if(item.mouseup)
{
//call the function!
if(item.mouseup)
{
item.mouseup(this.mouse);
}
if(item.__isDown)
{
if(item.click)item.click(this.mouse);
}
if(!item.interactiveChildren)up = true;
item.mouseup(this.mouse);
}
else
if(item.__isDown)
{
if(item.__isDown)
{
if(item.mouseupoutside)item.mouseupoutside(this.mouse);
}
if(item.click)item.click(this.mouse);
}
item.__isDown = false;
if(!item.interactiveChildren)up = true;
}
else
{
if(item.__isDown)
{
if(item.mouseupoutside)item.mouseupoutside(this.mouse);
}
}
item.__isDown = false;
//}
}
};
/**
* Tests if the current mouse coords hit a sprite
* Tests if the current mouse coordinates hit a sprite
*
* @method hitTest
* @param item {DisplayObject} The displayObject to test for a hit
* @param interactionData {InteractionData} The interactiondata object to update in the case of a hit
* @param interactionData {InteractionData} The interactionData object to update in the case there is a hit
* @private
*/
PIXI.InteractionManager.prototype.hitTest = function(item, interactionData)
{
var global = interactionData.global;
if(item.vcount !== PIXI.visibleCount)return false;
if( !item.worldVisible )return false;
// temp fix for if the element is in a non visible
var isSprite = (item instanceof PIXI.Sprite),
worldTransform = item.worldTransform,
a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2],
a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5],
a00 = worldTransform.a, a01 = worldTransform.b, a02 = worldTransform.tx,
a10 = worldTransform.c, a11 = worldTransform.d, a12 = worldTransform.ty,
id = 1 / (a00 * a11 + a01 * -a10),
x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id,
y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id;
@@ -480,10 +528,10 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData)
};
/**
* Is called when a touch is moved accross the renderer element
* Is called when a touch is moved across the renderer element
*
* @method onTouchMove
* @param event {Event} The DOM event of a touch moving accross the renderer view
* @param event {Event} The DOM event of a touch moving across the renderer view
* @private
*/
PIXI.InteractionManager.prototype.onTouchMove = function(event)
@@ -502,6 +550,10 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event)
// update the touch position
touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height);
if(navigator.isCocoonJS) {
touchData.global.x = touchEvent.clientX;
touchData.global.y = touchEvent.clientY;
}
}
var length = this.interactiveItems.length;
@@ -524,6 +576,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event)
{
var rect = this.interactionDOMElement.getBoundingClientRect();
if(PIXI.AUTO_PREVENT_DEFAULT)event.preventDefault();
var changedTouches = event.changedTouches;
for (var i=0; i < changedTouches.length; i++)
{
@@ -537,6 +591,10 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event)
this.touchs[touchEvent.identifier] = touchData;
touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height);
if(navigator.isCocoonJS) {
touchData.global.x = touchEvent.clientX;
touchData.global.y = touchEvent.clientY;
}
var length = this.interactiveItems.length;
@@ -582,6 +640,10 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event)
var up = false;
touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height);
if(navigator.isCocoonJS) {
touchData.global.x = touchEvent.clientX;
touchData.global.y = touchEvent.clientY;
}
var length = this.interactiveItems.length;
for (var j = 0; j < length; j++)
@@ -633,64 +695,4 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event)
this.pool.push(touchData);
this.touchs[touchEvent.identifier] = null;
}
};
/**
* Holds all information related to an Interaction event
*
* @class InteractionData
* @constructor
*/
PIXI.InteractionData = function()
{
/**
* This point stores the global coords of where the touch/mouse event happened
*
* @property global
* @type Point
*/
this.global = new PIXI.Point();
// this is here for legacy... but will remove
this.local = new PIXI.Point();
/**
* The target Sprite that was interacted with
*
* @property target
* @type Sprite
*/
this.target = null;
/**
* When passed to an event handler, this will be the original DOM Event that was captured
*
* @property originalEvent
* @type Event
*/
this.originalEvent = null;
};
/**
* This will return the local coords of the specified displayObject for this InteractionData
*
* @method getLocalPosition
* @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off
* @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject
*/
PIXI.InteractionData.prototype.getLocalPosition = function(displayObject)
{
var worldTransform = displayObject.worldTransform;
var global = this.global;
// do a cheeky transform to get the mouse coords;
var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2],
a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5],
id = 1 / (a00 * a11 + a01 * -a10);
// set the mouse coords...
return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id,
a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id);
};
// constructor
PIXI.InteractionData.prototype.constructor = PIXI.InteractionData;
};
+38
View File
@@ -6,3 +6,41 @@
* @module PIXI
*/
var PIXI = PIXI || {};
PIXI.WEBGL_RENDERER = 0;
PIXI.CANVAS_RENDERER = 1;
// useful for testing against if your lib is using pixi.
PIXI.VERSION = "v1.4.4";
// the various blend modes supported by pixi
PIXI.blendModes = {
NORMAL:0,
ADD:1,
MULTIPLY:2,
SCREEN:3,
OVERLAY:4,
DARKEN:5,
LIGHTEN:6,
COLOR_DODGE:7,
COLOR_BURN:8,
HARD_LIGHT:9,
SOFT_LIGHT:10,
DIFFERENCE:11,
EXCLUSION:12,
HUE:13,
SATURATION:14,
COLOR:15,
LUMINOSITY:16
};
// the scale modes
PIXI.scaleModes = {
DEFAULT:0,
LINEAR:0,
NEAREST:1
};
// interaction frequency
PIXI.INTERACTION_FREQUENCY = 30;
PIXI.AUTO_PREVENT_DEFAULT = true;
+7 -7
View File
@@ -3,12 +3,12 @@
*/
/**
* The Circle object can be used to specify a hit area for displayobjects
* The Circle object can be used to specify a hit area for displayObjects
*
* @class Circle
* @constructor
* @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle
* @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle
* @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this circle
* @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this circle
* @param radius {Number} The radius of the circle
*/
PIXI.Circle = function(x, y, radius)
@@ -47,12 +47,12 @@ PIXI.Circle.prototype.clone = function()
};
/**
* Checks if the x, and y coords passed to this function are contained within this circle
* Checks whether the x, and y coordinates passed to this function are contained within this circle
*
* @method contains
* @param x {Number} The X coord of the point to test
* @param y {Number} The Y coord of the point to test
* @return {Boolean} if the x/y coords are within this polygon
* @param x {Number} The X coordinate of the point to test
* @param y {Number} The Y coordinate of the point to test
* @return {Boolean} Whether the x/y coordinates are within this polygon
*/
PIXI.Circle.prototype.contains = function(x, y)
{
+13 -7
View File
@@ -3,12 +3,12 @@
*/
/**
* The Ellipse object can be used to specify a hit area for displayobjects
* The Ellipse object can be used to specify a hit area for displayObjects
*
* @class Ellipse
* @constructor
* @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse
* @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse
* @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this ellipse
* @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this ellipse
* @param width {Number} The overall width of this ellipse
* @param height {Number} The overall height of this ellipse
*/
@@ -55,12 +55,12 @@ PIXI.Ellipse.prototype.clone = function()
};
/**
* Checks if the x, and y coords passed to this function are contained within this ellipse
* Checks whether the x and y coordinates passed to this function are contained within this ellipse
*
* @method contains
* @param x {Number} The X coord of the point to test
* @param y {Number} The Y coord of the point to test
* @return {Boolean} if the x/y coords are within this ellipse
* @param x {Number} The X coordinate of the point to test
* @param y {Number} The Y coordinate of the point to test
* @return {Boolean} Whether the x/y coords are within this ellipse
*/
PIXI.Ellipse.prototype.contains = function(x, y)
{
@@ -78,6 +78,12 @@ PIXI.Ellipse.prototype.contains = function(x, y)
return (normx + normy < 0.25);
};
/**
* Returns the framing rectangle of the ellipse as a PIXI.Rectangle object
*
* @method getBounds
* @return {Rectangle} the framing rectangle
*/
PIXI.Ellipse.prototype.getBounds = function()
{
return new PIXI.Rectangle(this.x, this.y, this.width, this.height);
+52 -275
View File
@@ -1,293 +1,70 @@
/*
* A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV
* you both rock!
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
function determineMatrixArrayType() {
PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
return PIXI.Matrix;
}
determineMatrixArrayType();
PIXI.mat3 = {};
PIXI.mat3.create = function()
{
var matrix = new PIXI.Matrix(9);
matrix[0] = 1;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 0;
matrix[4] = 1;
matrix[5] = 0;
matrix[6] = 0;
matrix[7] = 0;
matrix[8] = 1;
return matrix;
/*
* @class Matrix
* The Matrix class will choose the best type of array to use between
* a regular javascript Array and a Float32Array if the latter is available
*
*/
PIXI.determineMatrixArrayType = function() {
return (typeof Float32Array !== 'undefined') ? Float32Array : Array;
};
PIXI.Matrix2 = PIXI.determineMatrixArrayType();
PIXI.mat3.identity = function(matrix)
PIXI.Matrix = function()
{
matrix[0] = 1;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 0;
matrix[4] = 1;
matrix[5] = 0;
matrix[6] = 0;
matrix[7] = 0;
matrix[8] = 1;
return matrix;
this.a = 1;
this.b = 0;
this.c = 0;
this.d = 1;
this.tx = 0;
this.ty = 0;
};
PIXI.mat4 = {};
PIXI.mat4.create = function()
PIXI.Matrix.prototype.fromArray = function(array)
{
var matrix = new PIXI.Matrix(16);
matrix[0] = 1;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 0;
matrix[4] = 0;
matrix[5] = 1;
matrix[6] = 0;
matrix[7] = 0;
matrix[8] = 0;
matrix[9] = 0;
matrix[10] = 1;
matrix[11] = 0;
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1;
return matrix;
this.a = array[0];
this.b = array[1];
this.c = array[3];
this.d = array[4];
this.tx = array[2];
this.ty = array[5];
};
PIXI.mat3.multiply = function (mat, mat2, dest)
PIXI.Matrix.prototype.toArray = function(transpose)
{
if (!dest) { dest = mat; }
if(!this.array) this.array = new Float32Array(9);
var array = this.array;
// Cache the matrix values (makes for huge speed increases!)
var a00 = mat[0], a01 = mat[1], a02 = mat[2],
a10 = mat[3], a11 = mat[4], a12 = mat[5],
a20 = mat[6], a21 = mat[7], a22 = mat[8],
b00 = mat2[0], b01 = mat2[1], b02 = mat2[2],
b10 = mat2[3], b11 = mat2[4], b12 = mat2[5],
b20 = mat2[6], b21 = mat2[7], b22 = mat2[8];
dest[0] = b00 * a00 + b01 * a10 + b02 * a20;
dest[1] = b00 * a01 + b01 * a11 + b02 * a21;
dest[2] = b00 * a02 + b01 * a12 + b02 * a22;
dest[3] = b10 * a00 + b11 * a10 + b12 * a20;
dest[4] = b10 * a01 + b11 * a11 + b12 * a21;
dest[5] = b10 * a02 + b11 * a12 + b12 * a22;
dest[6] = b20 * a00 + b21 * a10 + b22 * a20;
dest[7] = b20 * a01 + b21 * a11 + b22 * a21;
dest[8] = b20 * a02 + b21 * a12 + b22 * a22;
return dest;
};
PIXI.mat3.clone = function(mat)
{
var matrix = new PIXI.Matrix(9);
matrix[0] = mat[0];
matrix[1] = mat[1];
matrix[2] = mat[2];
matrix[3] = mat[3];
matrix[4] = mat[4];
matrix[5] = mat[5];
matrix[6] = mat[6];
matrix[7] = mat[7];
matrix[8] = mat[8];
return matrix;
};
PIXI.mat3.transpose = function (mat, dest)
{
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (!dest || mat === dest) {
var a01 = mat[1], a02 = mat[2],
a12 = mat[5];
mat[1] = mat[3];
mat[2] = mat[6];
mat[3] = a01;
mat[5] = mat[7];
mat[6] = a02;
mat[7] = a12;
return mat;
}
dest[0] = mat[0];
dest[1] = mat[3];
dest[2] = mat[6];
dest[3] = mat[1];
dest[4] = mat[4];
dest[5] = mat[7];
dest[6] = mat[2];
dest[7] = mat[5];
dest[8] = mat[8];
return dest;
};
PIXI.mat3.toMat4 = function (mat, dest)
{
if (!dest) { dest = PIXI.mat4.create(); }
dest[15] = 1;
dest[14] = 0;
dest[13] = 0;
dest[12] = 0;
dest[11] = 0;
dest[10] = mat[8];
dest[9] = mat[7];
dest[8] = mat[6];
dest[7] = 0;
dest[6] = mat[5];
dest[5] = mat[4];
dest[4] = mat[3];
dest[3] = 0;
dest[2] = mat[2];
dest[1] = mat[1];
dest[0] = mat[0];
return dest;
};
/////
PIXI.mat4.create = function()
{
var matrix = new PIXI.Matrix(16);
matrix[0] = 1;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 0;
matrix[4] = 0;
matrix[5] = 1;
matrix[6] = 0;
matrix[7] = 0;
matrix[8] = 0;
matrix[9] = 0;
matrix[10] = 1;
matrix[11] = 0;
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1;
return matrix;
};
PIXI.mat4.transpose = function (mat, dest)
{
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (!dest || mat === dest)
if(transpose)
{
var a01 = mat[1], a02 = mat[2], a03 = mat[3],
a12 = mat[6], a13 = mat[7],
a23 = mat[11];
mat[1] = mat[4];
mat[2] = mat[8];
mat[3] = mat[12];
mat[4] = a01;
mat[6] = mat[9];
mat[7] = mat[13];
mat[8] = a02;
mat[9] = a12;
mat[11] = mat[14];
mat[12] = a03;
mat[13] = a13;
mat[14] = a23;
return mat;
this.array[0] = this.a;
this.array[1] = this.c;
this.array[2] = 0;
this.array[3] = this.b;
this.array[4] = this.d;
this.array[5] = 0;
this.array[6] = this.tx;
this.array[7] = this.ty;
this.array[8] = 1;
}
else
{
this.array[0] = this.a;
this.array[1] = this.b;
this.array[2] = this.tx;
this.array[3] = this.c;
this.array[4] = this.d;
this.array[5] = this.ty;
this.array[6] = 0;
this.array[7] = 0;
this.array[8] = 1;
}
dest[0] = mat[0];
dest[1] = mat[4];
dest[2] = mat[8];
dest[3] = mat[12];
dest[4] = mat[1];
dest[5] = mat[5];
dest[6] = mat[9];
dest[7] = mat[13];
dest[8] = mat[2];
dest[9] = mat[6];
dest[10] = mat[10];
dest[11] = mat[14];
dest[12] = mat[3];
dest[13] = mat[7];
dest[14] = mat[11];
dest[15] = mat[15];
return dest;
return array;//[this.a, this.b, this.tx, this.c, this.d, this.ty, 0, 0, 1];
};
PIXI.mat4.multiply = function (mat, mat2, dest)
{
if (!dest) { dest = mat; }
// Cache the matrix values (makes for huge speed increases!)
var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3];
var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7];
var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11];
var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
// Cache only the current line of the second matrix
var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3];
dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[4];
b1 = mat2[5];
b2 = mat2[6];
b3 = mat2[7];
dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[8];
b1 = mat2[9];
b2 = mat2[10];
b3 = mat2[11];
dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[12];
b1 = mat2[13];
b2 = mat2[14];
b3 = mat2[15];
dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
return dest;
};
PIXI.identityMatrix = new PIXI.Matrix();
+8 -2
View File
@@ -7,8 +7,8 @@
*
* @class Point
* @constructor
* @param x {Number} position of the point
* @param y {Number} position of the point
* @param x {Number} position of the point on the x axis
* @param y {Number} position of the point on the y axis
*/
PIXI.Point = function(x, y)
{
@@ -41,3 +41,9 @@ PIXI.Point.prototype.clone = function()
// constructor
PIXI.Point.prototype.constructor = PIXI.Point;
PIXI.Point.prototype.set = function(x, y)
{
this.x = x || 0;
this.y = y || ( (y !== 0) ? this.x : 0 ) ;
};
+4 -4
View File
@@ -49,12 +49,12 @@ PIXI.Polygon.prototype.clone = function()
};
/**
* Checks if the x, and y coords passed to this function are contained within this polygon
* Checks whether the x and y coordinates passed to this function are contained within this polygon
*
* @method contains
* @param x {Number} The X coord of the point to test
* @param y {Number} The Y coord of the point to test
* @return {Boolean} if the x/y coords are within this polygon
* @param x {Number} The X coordinate of the point to test
* @param y {Number} The Y coordinate of the point to test
* @return {Boolean} Whether the x/y coordinates are within this polygon
*/
PIXI.Polygon.prototype.contains = function(x, y)
{
+5 -4
View File
@@ -55,12 +55,12 @@ PIXI.Rectangle.prototype.clone = function()
};
/**
* Checks if the x, and y coords passed to this function are contained within this Rectangle
* Checks whether the x and y coordinates passed to this function are contained within this Rectangle
*
* @method contains
* @param x {Number} The X coord of the point to test
* @param y {Number} The Y coord of the point to test
* @return {Boolean} if the x/y coords are within this Rectangle
* @param x {Number} The X coordinate of the point to test
* @param y {Number} The Y coordinate of the point to test
* @return {Boolean} Whether the x/y coords are within this Rectangle
*/
PIXI.Rectangle.prototype.contains = function(x, y)
{
@@ -84,3 +84,4 @@ PIXI.Rectangle.prototype.contains = function(x, y)
// constructor
PIXI.Rectangle.prototype.constructor = PIXI.Rectangle;
PIXI.EmptyRectangle = new PIXI.Rectangle(0,0,0,0);
+190 -230
View File
@@ -104,7 +104,7 @@ PIXI.DisplayObject = function()
this.stage = null;
/**
* [read-only] The multiplied alpha of the displayobject
* [read-only] The multiplied alpha of the displayObject
*
* @property worldAlpha
* @type Number
@@ -122,6 +122,13 @@ PIXI.DisplayObject = function()
*/
this._interactive = false;
/**
* This is the cursor that will be used when the mouse is over this object. To enable this the element must have interaction = true and buttonMode = true
*
* @property defaultCursor
* @type String
*
*/
this.defaultCursor = 'pointer';
/**
@@ -132,20 +139,10 @@ PIXI.DisplayObject = function()
* @readOnly
* @private
*/
this.worldTransform = PIXI.mat3.create(); //mat3.identity();
this.worldTransform = new PIXI.Matrix();
/**
* [read-only] Current transform of the object locally
*
* @property localTransform
* @type Mat3
* @readOnly
* @private
*/
this.localTransform = PIXI.mat3.create(); //mat3.identity();
/**
* [NYI] Unkown
* [NYI] Unknown
*
* @property color
* @type Array<>
@@ -162,13 +159,43 @@ PIXI.DisplayObject = function()
*/
this.dynamic = true;
// chach that puppy!
// cached sin rotation and cos rotation
this._sr = 0;
this._cr = 1;
/**
* The area the filter is applied to
*
* @property filterArea
* @type Rectangle
*/
this.filterArea = new PIXI.Rectangle(0,0,1,1);
/**
* 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 _currentBounds
* @type Rectangle
* @private
*/
this._mask = null;
/*
* MOUSE Callbacks
*/
@@ -224,7 +251,7 @@ PIXI.DisplayObject = function()
*/
/**
* A callback that is used when the user touch's over the displayObject
* A callback that is used when the user touches over the displayObject
* @method touchstart
* @param interactionData {InteractionData}
*/
@@ -279,9 +306,30 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', {
}
});
/**
* [read-only] Indicates if the sprite is globaly 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.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping.
* 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
@@ -293,27 +341,9 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', {
},
set: function(value) {
if(value)
{
if(this._mask)
{
value.start = this._mask.start;
value.end = this._mask.end;
}
else
{
this.addFilter(value);
value.renderable = false;
}
}
else
{
this.removeFilter(this._mask);
this._mask.renderable = true;
}
if(this._mask)this._mask.isMask = false;
this._mask = value;
if(this._mask)this._mask.isMask = true;
}
});
@@ -332,9 +362,6 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', {
if(value)
{
if(this._filters)this.removeFilter(this._filters);
this.addFilter(value);
// now put all the passes in one place..
var passes = [];
for (var i = 0; i < value.length; i++)
@@ -346,172 +373,14 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', {
}
}
value.start.filterPasses = passes;
}
else
{
if(this._filters) {
this.removeFilter(this._filters);
}
// TODO change this as it is legacy
this._filterBlock = {target:this, filterPasses:passes};
}
this._filters = value;
}
});
/*
* Adds a filter to this displayObject
*
* @method addFilter
* @param mask {Graphics} the graphics object to use as a filter
* @private
*/
PIXI.DisplayObject.prototype.addFilter = function(data)
{
//if(this.filter)return;
//this.filter = true;
// data[0].target = this;
// insert a filter block..
// TODO Onject pool thease bad boys..
var start = new PIXI.FilterBlock();
var end = new PIXI.FilterBlock();
data.start = start;
data.end = end;
start.data = data;
end.data = data;
start.first = start.last = this;
end.first = end.last = this;
start.open = true;
start.target = this;
/*
* insert start
*/
var childFirst = start;
var childLast = start;
var nextObject;
var previousObject;
previousObject = this.first._iPrev;
if(previousObject)
{
nextObject = previousObject._iNext;
childFirst._iPrev = previousObject;
previousObject._iNext = childFirst;
}
else
{
nextObject = this;
}
if(nextObject)
{
nextObject._iPrev = childLast;
childLast._iNext = nextObject;
}
// now insert the end filter block..
/*
* insert end filter
*/
childFirst = end;
childLast = end;
nextObject = null;
previousObject = null;
previousObject = this.last;
nextObject = previousObject._iNext;
if(nextObject)
{
nextObject._iPrev = childLast;
childLast._iNext = nextObject;
}
childFirst._iPrev = previousObject;
previousObject._iNext = childFirst;
var updateLast = this;
var prevLast = this.last;
while(updateLast)
{
if(updateLast.last === prevLast)
{
updateLast.last = end;
}
updateLast = updateLast.parent;
}
this.first = start;
// if webGL...
if(this.__renderGroup)
{
this.__renderGroup.addFilterBlocks(start, end);
}
};
/*
* Removes the filter to this displayObject
*
* @method removeFilter
* @private
*/
PIXI.DisplayObject.prototype.removeFilter = function(data)
{
//if(!this.filter)return;
//this.filter = false;
// console.log('YUOIO')
// modify the list..
var startBlock = data.start;
var nextObject = startBlock._iNext;
var previousObject = startBlock._iPrev;
if(nextObject)nextObject._iPrev = previousObject;
if(previousObject)previousObject._iNext = nextObject;
this.first = startBlock._iNext;
// remove the end filter
var lastBlock = data.end;
nextObject = lastBlock._iNext;
previousObject = lastBlock._iPrev;
if(nextObject)nextObject._iPrev = previousObject;
previousObject._iNext = nextObject;
// this is always true too!
var tempLast = lastBlock._iPrev;
// need to make sure the parents last is updated too
var updateLast = this;
while(updateLast.last === lastBlock)
{
updateLast.last = tempLast;
updateLast = updateLast.parent;
if(!updateLast)break;
}
// if webGL...
if(this.__renderGroup)
{
this.__renderGroup.removeFilterBlocks(startBlock, lastBlock);
}
};
/*
* Updates the object transform for rendering
*
@@ -523,48 +392,139 @@ PIXI.DisplayObject.prototype.updateTransform = function()
// TODO OPTIMIZE THIS!! with dirty
if(this.rotation !== this.rotationCache)
{
if(isNaN(parseFloat(this.rotation)))
throw new Error('DisplayObject rotation values must be numeric.');
this.rotationCache = this.rotation;
this._sr = Math.sin(this.rotation);
this._cr = Math.cos(this.rotation);
}
var localTransform = this.localTransform;
var parentTransform = this.parent.worldTransform;
var worldTransform = this.worldTransform;
// var localTransform = this.localTransform//.toArray();
var parentTransform = this.parent.worldTransform;//.toArray();
var worldTransform = this.worldTransform;//.toArray();
//console.log(localTransform)
localTransform[0] = this._cr * this.scale.x;
localTransform[1] = -this._sr * this.scale.y;
localTransform[3] = this._sr * this.scale.x;
localTransform[4] = this._cr * this.scale.y;
// TODO --> do we even need a local matrix???
var px = this.pivot.x;
var py = this.pivot.y;
// Cache the matrix values (makes for huge speed increases!)
var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1],
a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3],
var a00 = this._cr * this.scale.x,
a01 = -this._sr * this.scale.y,
a10 = this._sr * this.scale.x,
a11 = this._cr * this.scale.y,
a02 = this.position.x + a00 * px - py * a01,
a12 = this.position.y + a11 * py - px * a10,
b00 = parentTransform.a, b01 = parentTransform.b, b02 = parentTransform.tx,
b10 = parentTransform.c, b11 = parentTransform.d, b12 = parentTransform.ty;
b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2],
b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5];
worldTransform.a = b00 * a00 + b01 * a10;
worldTransform.b = b00 * a01 + b01 * a11;
worldTransform.tx = b00 * a02 + b01 * a12 + b02;
localTransform[2] = a02;
localTransform[5] = a12;
worldTransform.c = b10 * a00 + b11 * a10;
worldTransform.d = b10 * a01 + b11 * a11;
worldTransform.ty = b10 * a02 + b11 * a12 + b12;
worldTransform[0] = b00 * a00 + b01 * a10;
worldTransform[1] = b00 * a01 + b01 * a11;
worldTransform[2] = b00 * a02 + b01 * a12 + b02;
worldTransform[3] = b10 * a00 + b11 * a10;
worldTransform[4] = b10 * a01 + b11 * a11;
worldTransform[5] = b10 * a02 + b11 * a12 + b12;
// because we are using affine transformation, we can optimise the matrix concatenation process.. wooo!
// mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform);
this.worldAlpha = this.alpha * this.parent.worldAlpha;
this.vcount = PIXI.visibleCount;
};
PIXI.visibleCount = 0;
/**
* Retrieves the bounds of the displayObject as a rectangle object
*
* @method getBounds
* @return {Rectangle} the rectangular bounding area
*/
PIXI.DisplayObject.prototype.getBounds = function()
{
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()
{
var matrixCache = this.worldTransform;
this.worldTransform = PIXI.identityMatrix;
this.updateTransform();
var bounds = this.getBounds();
this.worldTransform = matrixCache;
return bounds;
};
/**
* Sets the object's stage reference, the stage this object is connected to
*
* @method setStageReference
* @param stage {Stage} the stage that the object will have as its current stage reference
*/
PIXI.DisplayObject.prototype.setStageReference = function(stage)
{
this.stage = stage;
if(this._interactive)this.stage.dirty = true;
};
/**
* 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;
}
});
+228 -200
View File
@@ -29,6 +29,44 @@ PIXI.DisplayObjectContainer = function()
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) {
this.scale.x = value / (this.getLocalBounds().width/this.scale.x);
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) {
this.scale.y = value / (this.getLocalBounds().height/this.scale.y);
this._height = value;
}
});
*/
/**
* Adds a child to the container.
*
@@ -37,82 +75,7 @@ PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer;
*/
PIXI.DisplayObjectContainer.prototype.addChild = function(child)
{
if(child.parent && child.parent !== this)
{
//// COULD BE THIS???
child.parent.removeChild(child);
// return;
}
child.parent = this;
this.children.push(child);
// update the stage refference..
if(this.stage)
{
var tmpChild = child;
do
{
if(tmpChild.interactive)this.stage.dirty = true;
tmpChild.stage = this.stage;
tmpChild = tmpChild._iNext;
}
while(tmpChild);
}
// LINKED LIST //
// modify the list..
var childFirst = child.first;
var childLast = child.last;
var nextObject;
var previousObject;
// this could be wrong if there is a filter??
if(this._filters || this._mask)
{
previousObject = this.last._iPrev;
}
else
{
previousObject = this.last;
}
nextObject = previousObject._iNext;
// always true in this case
// need to make sure the parents last is updated too
var updateLast = this;
var prevLast = previousObject;
while(updateLast)
{
if(updateLast.last === prevLast)
{
updateLast.last = child.last;
}
updateLast = updateLast.parent;
}
if(nextObject)
{
nextObject._iPrev = childLast;
childLast._iNext = nextObject;
}
childFirst._iPrev = previousObject;
previousObject._iNext = childFirst;
// need to remove any render groups..
if(this.__renderGroup)
{
// being used by a renderTexture.. if it exists then it must be from a render texture;
if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child);
// add them to the new render group..
this.__renderGroup.addDisplayObjectAndChildren(child);
}
this.addChildAt(child, this.children.length);
};
/**
@@ -126,76 +89,16 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
{
if(index >= 0 && index <= this.children.length)
{
if(child.parent !== undefined)
if(child.parent)
{
child.parent.removeChild(child);
}
child.parent = this;
if(this.stage)
{
var tmpChild = child;
do
{
if(tmpChild.interactive)this.stage.dirty = true;
tmpChild.stage = this.stage;
tmpChild = tmpChild._iNext;
}
while(tmpChild);
}
// modify the list..
var childFirst = child.first;
var childLast = child.last;
var nextObject;
var previousObject;
if(index === this.children.length)
{
previousObject = this.last;
var updateLast = this;
var prevLast = this.last;
while(updateLast)
{
if(updateLast.last === prevLast)
{
updateLast.last = child.last;
}
updateLast = updateLast.parent;
}
}
else if(index === 0)
{
previousObject = this;
}
else
{
previousObject = this.children[index-1].last;
}
nextObject = previousObject._iNext;
// always true in this case
if(nextObject)
{
nextObject._iPrev = childLast;
childLast._iNext = nextObject;
}
childFirst._iPrev = previousObject;
previousObject._iNext = childFirst;
this.children.splice(index, 0, child);
// need to remove any render groups..
if(this.__renderGroup)
{
// being used by a renderTexture.. if it exists then it must be from a render texture;
if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child);
// add them to the new render group..
this.__renderGroup.addDisplayObjectAndChildren(child);
}
if(this.stage)child.setStageReference(this.stage);
}
else
{
@@ -224,23 +127,13 @@ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2)
throw new Error('swapChildren: Both the supplied DisplayObjects must be a child of the caller.');
}
this.removeChild(child);
this.removeChild(child2);
if(index1 < index2)
{
this.addChildAt(child2, index1);
this.addChildAt(child, index2);
}
else
{
this.addChildAt(child, index2);
this.addChildAt(child2, index1);
}
this.children[index1] = child2;
this.children[index2] = child;
};
/**
* Returns the Child at the specified index
* Returns the child at the specified index
*
* @method getChildAt
* @param index {Number} The index to get the child from
@@ -253,7 +146,7 @@ PIXI.DisplayObjectContainer.prototype.getChildAt = function(index)
}
else
{
throw new Error('Both the supplied DisplayObjects must be a child of the caller ' + this);
throw new Error('The supplied DisplayObjects must be a child of the caller ' + this);
}
};
@@ -268,53 +161,8 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
var index = this.children.indexOf( child );
if ( index !== -1 )
{
// unlink //
// modify the list..
var childFirst = child.first;
var childLast = child.last;
var nextObject = childLast._iNext;
var previousObject = childFirst._iPrev;
if(nextObject)nextObject._iPrev = previousObject;
previousObject._iNext = nextObject;
if(this.last === childLast)
{
var tempLast = childFirst._iPrev;
// need to make sure the parents last is updated too
var updateLast = this;
while(updateLast.last === childLast)
{
updateLast.last = tempLast;
updateLast = updateLast.parent;
if(!updateLast)break;
}
}
childLast._iNext = null;
childFirst._iPrev = null;
// update the stage reference..
if(this.stage)
{
var tmpChild = child;
do
{
if(tmpChild.interactive)this.stage.dirty = true;
tmpChild.stage = null;
tmpChild = tmpChild._iNext;
}
while(tmpChild);
}
// webGL trim
if(child.__renderGroup)
{
child.__renderGroup.removeDisplayObjectAndChildren(child);
}
if(this.stage)child.removeStageReference();
child.parent = undefined;
this.children.splice( index, 1 );
@@ -326,13 +174,15 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
};
/*
* Updates the container's children's transform for rendering
* Updates the container's childrens transform for rendering
*
* @method updateTransform
* @private
*/
PIXI.DisplayObjectContainer.prototype.updateTransform = function()
{
//this._currentBounds = null;
if(!this.visible)return;
PIXI.DisplayObject.prototype.updateTransform.call( this );
@@ -342,3 +192,181 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function()
this.children[i].updateTransform();
}
};
/**
* Retrieves the bounds of the displayObjectContainer as a rectangle object
*
* @method getBounds
* @return {Rectangle} the rectangular bounding area
*/
PIXI.DisplayObjectContainer.prototype.getBounds = function()
{
if(this.children.length === 0)return PIXI.EmptyRectangle;
// TODO the bounds have already been calculated this render session so return what we have
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
var childBounds;
var childMaxX;
var childMaxY;
var childVisible = false;
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
if(!child.visible)continue;
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;
}
if(!childVisible)
return PIXI.EmptyRectangle;
var bounds = this._bounds;
bounds.x = minX;
bounds.y = minY;
bounds.width = maxX - minX;
bounds.height = maxY - minY;
// TODO: store a reference so that if this function gets called again in the render cycle we do not have to recalculate
//this._currentBounds = bounds;
return bounds;
};
/**
* Sets the container's stage reference, the stage this object 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;
if(this._interactive)this.stage.dirty = true;
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child.setStageReference(stage);
}
};
/**
* removes the current stage reference of the container
*
* @method removeStageReference
*/
PIXI.DisplayObjectContainer.prototype.removeStageReference = function()
{
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child.removeStageReference();
}
if(this._interactive)this.stage.dirty = true;
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;
var i,j;
if(this._mask || this._filters)
{
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);
}
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if(this._filters)renderSession.filterManager.popFilter();
if(this._mask)renderSession.maskManager.popMask(renderSession);
renderSession.spriteBatch.start();
}
else
{
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
};
/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.DisplayObjectContainer.prototype._renderCanvas = function(renderSession)
{
if(this.visible === false || this.alpha === 0)return;
if(this._mask)
{
renderSession.maskManager.pushMask(this._mask, renderSession.context);
}
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderCanvas(renderSession);
}
if(this._mask)
{
renderSession.maskManager.popMask(renderSession.context);
}
};
+1 -1
View File
@@ -49,7 +49,7 @@ PIXI.MovieClip = function(textures)
this.onComplete = null;
/**
* [read-only] The index MovieClips current frame (this may not have to be a whole number)
* [read-only] The MovieClips current frame index (this may not have to be a whole number)
*
* @property currentFrame
* @type Number
+296 -29
View File
@@ -2,19 +2,18 @@
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI.blendModes = {};
PIXI.blendModes.NORMAL = 0;
PIXI.blendModes.SCREEN = 1;
/**
* The SPrite object is the base for all textured objects that are rendered to the screen
* 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
* @type String
*
* A sprite can be created directly from an image like this :
* var sprite = nex 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)
{
@@ -22,9 +21,9 @@ PIXI.Sprite = function(texture)
/**
* The anchor sets the origin point of the texture.
* The default is 0,0 this means the textures 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
* 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 centred
* Setting the anchor to 1,1 would mean the textures origin points will be the bottom right corner
*
* @property anchor
* @type Point
@@ -39,15 +38,6 @@ PIXI.Sprite = function(texture)
*/
this.texture = texture;
/**
* The blend mode of sprite.
* currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN
*
* @property blendMode
* @type Number
*/
this.blendMode = PIXI.blendModes.NORMAL;
/**
* The width of the sprite (this is initially set by the texture)
*
@@ -66,9 +56,28 @@ PIXI.Sprite = function(texture)
*/
this._height = 0;
/**
* The tint applied to the sprite. This is a hex value
*
* @property tint
* @type Number
* @default 0xFFFFFF
*/
this.tint = 0xFFFFFF;// * Math.random();
/**
* The blend mode to be applied to the sprite
*
* @property blendMode
* @type Number
* @default PIXI.blendModes.NORMAL;
*/
this.blendMode = PIXI.blendModes.NORMAL;
if(texture.baseTexture.hasLoaded)
{
this.updateFrame = true;
this.onTextureUpdate();
}
else
{
@@ -84,7 +93,7 @@ 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 acheive the value set
* The width of the sprite, setting this will actually modify the scale to achieve the value set
*
* @property width
* @type Number
@@ -100,7 +109,7 @@ Object.defineProperty(PIXI.Sprite.prototype, 'width', {
});
/**
* The height of the sprite, setting this will actually modify the scale to acheive the value set
* The height of the sprite, setting this will actually modify the scale to achieve the value set
*
* @property height
* @type Number
@@ -128,17 +137,13 @@ PIXI.Sprite.prototype.setTexture = function(texture)
{
this.textureChange = true;
this.texture = texture;
if(this.__renderGroup)
{
this.__renderGroup.updateTexture(this);
}
}
else
{
this.texture = texture;
}
this.cachedTint = 0xFFFFFF;
this.updateFrame = true;
};
@@ -151,15 +156,277 @@ PIXI.Sprite.prototype.setTexture = function(texture)
*/
PIXI.Sprite.prototype.onTextureUpdate = function()
{
//this.texture.removeEventListener( 'update', this.onTextureUpdateBind );
// 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;
this.updateFrame = true;
};
/**
* Retrieves the bounds of the sprite as a rectangle object
*
* @method getBounds
* @return {Rectangle} the rectangular bounding area
*/
PIXI.Sprite.prototype.getBounds = function()
{
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 = this.worldTransform;
var a = worldTransform.a;
var b = worldTransform.c;
var c = worldTransform.b;
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;
};
/**
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.Sprite.prototype._renderWebGL = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(!this.visible || this.alpha <= 0)return;
var i,j;
// do a quick check to see if this element has a mask or a filter.
if(this._mask || this._filters)
{
var spriteBatch = renderSession.spriteBatch;
if(this._mask)
{
spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
spriteBatch.start();
}
if(this._filters)
{
spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
// add this sprite to the batch
spriteBatch.render(this);
// now loop through the children and make sure they get rendered
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
// time to stop the sprite batch as either a mask element or a filter draw will happen next
spriteBatch.stop();
if(this._filters)renderSession.filterManager.popFilter();
if(this._mask)renderSession.maskManager.popMask(renderSession);
spriteBatch.start();
}
else
{
renderSession.spriteBatch.render(this);
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
//TODO check culling
};
/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.Sprite.prototype._renderCanvas = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(this.visible === false || this.alpha === 0)return;
var frame = this.texture.frame;
var context = renderSession.context;
var texture = this.texture;
if(this.blendMode !== renderSession.currentBlendMode)
{
renderSession.currentBlendMode = this.blendMode;
context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
}
if(this._mask)
{
renderSession.maskManager.pushMask(this._mask, renderSession.context);
}
//ignore null sources
if(frame && frame.width && frame.height && texture.baseTexture.source)
{
context.globalAlpha = this.worldAlpha;
var transform = this.worldTransform;
// allow for trimming
context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
//if smoothingEnabled is supported and we need to change the smoothing property for this texture
if(renderSession.smoothProperty && renderSession.scaleMode !== this.texture.baseTexture.scaleMode) {
renderSession.scaleMode = this.texture.baseTexture.scaleMode;
context[renderSession.smoothProperty] = (renderSession.scaleMode === PIXI.scaleModes.LINEAR);
}
if(this.tint !== 0xFFFFFF)
{
if(this.cachedTint !== this.tint)
{
// no point tinting an image that has not loaded yet!
if(!texture.baseTexture.hasLoaded)return;
this.cachedTint = this.tint;
//TODO clean up caching - how to clean up the caches?
this.tintedTexture = PIXI.CanvasTinter.getTintedTexture(this, this.tint);
}
context.drawImage(this.tintedTexture,
0,
0,
frame.width,
frame.height,
(this.anchor.x) * -frame.width,
(this.anchor.y) * -frame.height,
frame.width,
frame.height);
}
else
{
if(texture.trimmed)
{
var trim = texture.trim;
context.drawImage(this.texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
trim.x - this.anchor.x * trim.realWidth,
trim.y - this.anchor.y * trim.realHeight,
frame.width,
frame.height);
}
else
{
context.drawImage(this.texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
(this.anchor.x) * -frame.width,
(this.anchor.y) * -frame.height,
frame.width,
frame.height);
}
}
}
// OVERWRITE
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderCanvas(renderSession);
}
if(this._mask)
{
renderSession.maskManager.popMask(renderSession.context);
}
};
// some helper functions..
/**
+371
View File
@@ -0,0 +1,371 @@
PIXI.ParticleBatch = function(texture)
{
PIXI.DisplayObjectContainer.call( this);
this.textureThing = texture;
this.ready = false;
}
PIXI.ParticleBatch.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
PIXI.ParticleBatch.constructor = PIXI.ParticleBatch;
PIXI.ParticleBatch.prototype.initWebGL = function(gl)
{
var vecShaderSrc = [
"attribute vec2 aVertexPosition;",
"attribute vec2 aMovement;",
"attribute vec2 aTexture;",
"uniform mat3 translationMatrix;",
"uniform float time;",
// "uniform float pos;",
"uniform vec2 projectionVector;",
"varying vec2 vTextureCoord;",
"const float PI = 3.14159265358;",
"void main(void) {",
"vec2 v = aVertexPosition;",
"float x = aMovement.x * 0.01;",
"vec2 scaledVertex = aVertexPosition;",
"v.x = (scaledVertex.x) * cos(x) - (scaledVertex.y) * sin(x);",
"v.y = (scaledVertex.x) * sin(x) + (scaledVertex.y) * cos(x);",
//"float pos = p * p * ((this._p1 + 1) * p - this._p1);"
//"v.y = sin(-time*PI * 2.0) * -aMovement.y;",
"v += aMovement;",
// "v += aVertexPosition;",
// "v.y *= 1.0 + smoothstep(time, 0.5, 1.0) * 3.0;",
// "v.y += aMovement.y * time + aVertexPosition.y;",
// "v.y = time * aMovement.y;;",
// "v.y += aVertexPosition.y;",
//"v.x += aMovement.x ;",
// "v.y *= -1.0;",
"v.x += 1280.0/2.0;",
"v.y += 800.0/2.0;",
"gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);",
// "gl_Position = vec4(aVertexPosition, 0.0, 1.0);",
"vTextureCoord = aTexture;",
"}"
];
var fragShaderSrc = [
"precision lowp float;",
"varying vec2 vTextureCoord;",
"uniform sampler2D uSampler;",
"void main(void) {",
"gl_FragColor = texture2D(uSampler, vTextureCoord);",
"}"
];
this.program = PIXI.compileProgram(gl, vecShaderSrc, fragShaderSrc)
gl.useProgram(this.program);
this.translationMatrix = gl.getUniformLocation(this.program, "translationMatrix");
this.projectionVector = gl.getUniformLocation(this.program, "projectionVector");
this.time = gl.getUniformLocation(this.program, "time");
this.aVertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
this.aMovement = gl.getAttribLocation(this.program, "aMovement");
this.aTexture = gl.getAttribLocation(this.program, "aTexture");
// console.log(":::" + this.aMovement)
this.totalItems = 10000;
this.verticies = new Float32Array( this.totalItems * 8 );
this.movement = new Float32Array( this.totalItems * 8 );
this.posData = new Float32Array( this.totalItems * 3 );
this.texture = new Float32Array( this.totalItems * 8 );
this.indices = new Uint16Array( this.totalItems * 6);
for (var i = 0; i < this.totalItems * 8; i+=8) {
var scale = 1// + Math.random()
// position..
this.verticies[i] = -20 * scale;
this.verticies[i+1] = -20 * scale;
this.verticies[i+2] = 20 * scale;
this.verticies[i+3] = -20 * scale;
this.verticies[i+4] = 20 * scale;
this.verticies[i+5] = 20 * scale;
this.verticies[i+6] = -20 * scale;
this.verticies[i+7] = 20 * scale;
};
var fullWidth = 142;
var fullHeight= 157;
var simpleFrame = new PIXI.Rectangle(0, 0, 142, 157);
var gemCount = 0;
for (var i = 0; i < this.totalItems * 8; i+=8) {
gemCount++
var gemFrame = this.texture.frame || simpleFrame;//this.gems[gemCount % this.gems.length].frame;
// console.log(gemFrame);
// position..
var xoff = gemFrame.x / fullWidth;
var yoff = gemFrame.y / fullHeight;
this.texture[i] = xoff;
this.texture[i+1] = yoff;
this.texture[i+2] = xoff + gemFrame.width / fullWidth;
this.texture[i+3] = yoff;
this.texture[i+4] = xoff + gemFrame.width / fullWidth;
this.texture[i+5] = yoff + gemFrame.height / fullHeight;
this.texture[i+6] = xoff;
this.texture[i+7] = yoff + gemFrame.height / fullHeight;
//
};
for (var i = 0; i < this.totalItems* 8; i+=8) {
var pos = 0//Math.random() * 200;
var angle = Math.random() * Math.PI * 2;
var speed = (0.3 + Math.random() * 0.9) * 0.01;
var pos = Math.sin(angle) * speed;//Math.random() * 10 - 5;
var posY = Math.cos(angle) * speed;
var scale = 1;
// var posY = 0.5 + Math.random()// * 200
// console.log(pos);
this.movement[i] = pos;
this.movement[i+1] = posY;
this.movement[i+2] = scale;
this.movement[i+3] = scale;
this.movement[i+4] = rotation;
this.movement[i+5] = scale;
this.movement[i+2] = pos;
this.movement[i+3] = posY;
this.movement[i+4] = pos;
this.movement[i+5] = posY;
this.movement[i+6] = pos;
this.movement[i+7] = posY;
}
this.reset();
for (var i = 0; i < this.totalItems * 6; i+=6) {
var i3 = (i / 6) * 4;
this.indices[i] = i3;
this.indices[i+1] = i3+1;
this.indices[i+2] = i3+2;
this.indices[i+3] = i3;
this.indices[i+4] = i3+2;
this.indices[i+5] = i3+3;
}
// console.log(this);
this.vertexBuffer = gl.createBuffer();
this.textureBuffer = gl.createBuffer();
this.movementBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.verticies, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.texture, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this.movementBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.movement, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
this.count = 0;
this.speed = 18;
this.posy = 0;
this.ready = true;
// alert("!")
}
PIXI.ParticleBatch.prototype.addChild = function(child)
{
PIXI.DisplayObjectContainer.prototype.addChild.call(child);
}
PIXI.ParticleBatch.prototype.reset = function()
{
for (var i = 0; i < this.totalItems* 4; i+=4) {
this.posData[i] = 0; // pos x
this.posData[i + 1] = 0; // pos y
var angle = Math.random() * Math.PI * 2;
var speed = 10 + Math.random() * 15;
var pos = Math.sin(angle) * speed;//Math.random() * 10 - 5;
var posY = Math.cos(angle) *speed;
this.posData[i + 2] = pos; // speed x
this.posData[i + 3] = posY - 10; // speed y
}
}
PIXI.ParticleBatch.prototype._renderWebGL = function(renderSession)
{
if(!this.visible)return;
renderSession.shaderManager.deactivateDefaultShader()
if(!this.ready)this.initWebGL( renderSession.gl );
renderSession.spriteBatch.stop();
this.speed -= 0.4;
this.count += this.speed;
var gl = renderSession.gl;
var glTexture = this.textureThing.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.textureThing.baseTexture, gl)
gl.useProgram(this.program);
gl.enableVertexAttribArray(this.aVertexPosition);
gl.enableVertexAttribArray(this.aMovement);
gl.enableVertexAttribArray(this.aTexture);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, glTexture);
gl.uniform1f(this.time, this.count);
gl.uniform2f(this.projectionVector, renderSession.projection.x, renderSession.projection.y);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.vertexAttribPointer(this.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
gl.vertexAttribPointer(this.aTexture, 2, gl.FLOAT, false, 0, 0);
for (var i = 0; i < this.totalItems* 8; i+=8) {
var val = ( i / 8 ) * 4;
this.posData[val + 3] += 0.02;
this.posData[val] += this.posData[val + 2];
this.posData[val + 1] += this.posData[val + 3];
var pos = this.posData[val];
var posY = this.posData[val + 1];
//pos += this.posData[val + 2];
//posY += this.posData[val + 3];
this.movement[i] = pos;
this.movement[i+1] = posY;
this.movement[i+2] = pos;
this.movement[i+3] = posY;
this.movement[i+4] = pos;
this.movement[i+5] = posY;
this.movement[i+6] = pos;
this.movement[i+7] = posY;
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.movementBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.movement);
gl.vertexAttribPointer(this.aMovement, 2, gl.FLOAT, false, 0, 0);
//gl.bindBuffer(gl.ARRAY_BUFFER, this.movementBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.drawElements(gl.TRIANGLES, 6 * this.totalItems , gl.UNSIGNED_SHORT, 0);
// not sure if both needed? but ya have for now!
// override!
// disable the current stuff..
// gl.disableVertexAttribArray(PIXI.stripShader.aVertexPosition);
//gl.disableVertexAttribArray(PIXI.stripShader.colorAttribute);
//gl.disableVertexAttribArray(PIXI.stripShader.aTextureCoord);
gl.disableVertexAttribArray(this.aVertexPosition);
gl.disableVertexAttribArray(this.aMovement);
gl.disableVertexAttribArray(this.aTexture);
renderSession.shaderManager.activateDefaultShader()
renderSession.spriteBatch.start();
/*
gl.useProgram(PIXI.defaultShader.program);
gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition);
gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute);
gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
*/
}
+156
View File
@@ -0,0 +1,156 @@
/**
* @author Mat Groves http://matgroves.com/
*/
/**
* TODO-Alvin
*
* @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.constructor = PIXI.SpriteBatch;
/*
* Initialises the spriteBatch
*
* @method initWebGL
* @param gl {WebGLContext} the current WebGL drawing context
*/
PIXI.SpriteBatch.prototype.initWebGL = function(gl)
{
this.fastSpriteBatch = new PIXI.WebGLFastSpriteBatch(gl);
this.ready = true;
// alert("!")
};
/*
* Updates the object transform for rendering
*
* @method updateTransform
* @private
*/
PIXI.SpriteBatch.prototype.updateTransform = function()
{
// dont need to!
PIXI.DisplayObject.prototype.updateTransform.call( this );
// 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 );
renderSession.spriteBatch.stop();
renderSession.shaderManager.activateShader(renderSession.shaderManager.fastShader);
this.fastSpriteBatch.begin(this, renderSession);
this.fastSpriteBatch.render(this);
renderSession.shaderManager.activateShader(renderSession.shaderManager.defaultShader);
renderSession.spriteBatch.start();
};
/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.SpriteBatch.prototype._renderCanvas = function(renderSession)
{
var context = renderSession.context;
context.globalAlpha = this.worldAlpha;
var transform = this.worldTransform;
// alow for trimming
context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
context.save();
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
var texture = child.texture;
var frame = texture.frame;
context.globalAlpha = this.worldAlpha * child.alpha;
if(child.rotation % (Math.PI * 2) === 0)
{
// this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call
context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5) | 0,
((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5) | 0,
frame.width * child.scale.x,
frame.height * child.scale.y);
}
else
{
PIXI.DisplayObject.prototype.updateTransform.call(child);
transform = child.localTransform;
if(this.rotation !== this.rotationCache)
{
this.rotationCache = this.rotation;
this._sr = Math.sin(this.rotation);
this._cr = Math.cos(this.rotation);
}
var a = child._cr * child.scale.x,
b = -child._sr * child.scale.y,
c = child._sr * child.scale.x,
d = child._cr * child.scale.y;
context.setTransform(a, c, b, d, child.position.x, child.position.y);
//context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
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);
}
}
context.restore();
};
+11 -10
View File
@@ -8,8 +8,15 @@
* @class Stage
* @extends DisplayObjectContainer
* @constructor
* @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format
* @param backgroundColor {Number} the background color of the stage, you have to pass this in is in hex format
* like: 0xFFFFFF for white
*
* Creating a stage is a mandatory process when you use Pixi, which is as simple as this :
* var stage = new PIXI.Stage(0xFFFFFF);
* where the parameter given is the background colour of the stage, in hex
* you will use this stage instance to add your sprites to it and therefore to the renderer
* Here is how to add a sprite to the stage :
* stage.addChild(sprite);
*/
PIXI.Stage = function(backgroundColor)
{
@@ -23,7 +30,7 @@ PIXI.Stage = function(backgroundColor)
* @readOnly
* @private
*/
this.worldTransform = PIXI.mat3.create();
this.worldTransform = new PIXI.Matrix();
/**
* Whether or not the stage is interactive
@@ -50,17 +57,13 @@ PIXI.Stage = function(backgroundColor)
*/
this.dirty = true;
this.__childrenAdded = [];
this.__childrenRemoved = [];
//the stage is it's own stage
//the stage is its own stage
this.stage = this;
//optimize hit detection a bit
this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000);
this.setBackgroundColor(backgroundColor);
this.worldVisible = true;
};
// constructor
@@ -69,7 +72,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage;
/**
* Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element.
* This is useful for when you have other DOM elements ontop of the Canvas element.
* This is useful for when you have other DOM elements on top of the Canvas element.
*
* @method setInteractionDelegate
* @param domElement {DOMElement} This new domElement which will receive mouse/touch events
@@ -88,7 +91,6 @@ PIXI.Stage.prototype.setInteractionDelegate = function(domElement)
PIXI.Stage.prototype.updateTransform = function()
{
this.worldAlpha = 1;
this.vcount = PIXI.visibleCount;
for(var i=0,j=this.children.length; i<j; i++)
{
@@ -102,7 +104,6 @@ PIXI.Stage.prototype.updateTransform = function()
this.interactionManager.dirty = true;
}
if(this.interactive)this.interactionManager.update();
};
-58
View File
@@ -1,58 +0,0 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* This object is one that will allow you to specify custom rendering functions based on render type
*
* @class CustomRenderable
* @extends DisplayObject
* @constructor
*/
PIXI.CustomRenderable = function()
{
PIXI.DisplayObject.call( this );
this.renderable = true;
};
// constructor
PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype );
PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable;
/**
* If this object is being rendered by a CanvasRenderer it will call this callback
*
* @method renderCanvas
* @param renderer {CanvasRenderer} The renderer instance
*/
PIXI.CustomRenderable.prototype.renderCanvas = function()
{
// override!
};
/**
* If this object is being rendered by a WebGLRenderer it will call this callback to initialize
*
* @method initWebGL
* @param renderer {WebGLRenderer} The renderer instance
*/
PIXI.CustomRenderable.prototype.initWebGL = function()
{
// override!
};
/**
* If this object is being rendered by a WebGLRenderer it will call this callback
*
* @method renderWebGL
* @param rendererGroup {WebGLRenderGroup} The renderer group instance
* @param projectionMatrix {Matrix} The object's projection matrix
*/
PIXI.CustomRenderable.prototype.renderWebGL = function()
{
// not sure if both needed? but ya have for now!
// override!
};
+27 -3
View File
@@ -1,7 +1,14 @@
/**
* @author Mat Groves http://matgroves.com/
/* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
*
* @class Rope
* @constructor
* @param texture {Texture} TODO-Alvin
* @param y {Array} TODO-Alvin
*
*/
PIXI.Rope = function(texture, points)
{
PIXI.Strip.call( this, texture );
@@ -30,6 +37,11 @@ PIXI.Rope = function(texture, points)
PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype );
PIXI.Rope.prototype.constructor = PIXI.Rope;
/*
* Refreshes TODO-Alvin
*
* @method refresh
*/
PIXI.Rope.prototype.refresh = function()
{
var points = this.points;
@@ -96,6 +108,12 @@ PIXI.Rope.prototype.refresh = function()
}
};
/*
* Updates the object transform for rendering
*
* @method updateTransform
* @private
*/
PIXI.Rope.prototype.updateTransform = function()
{
@@ -157,7 +175,13 @@ PIXI.Rope.prototype.updateTransform = function()
PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
};
/*
* Sets the texture that the Rope will use
* TODO-Alvin
*
* @method setTexture
* @param texture {Texture} the texture that will be used
*/
PIXI.Rope.prototype.setTexture = function(texture)
{
// stop current texture
+25
View File
@@ -2,6 +2,16 @@
* @author Mat Groves http://matgroves.com/
*/
/**
*
* @class Strip
* @constructor
* @param texture {Texture} TODO-Alvin
* @param width {Number} the width of the TODO-Alvin
* @param height {Number} the height of the TODO-Alvin
*
*/
PIXI.Strip = function(texture, width, height)
{
PIXI.DisplayObjectContainer.call( this );
@@ -69,6 +79,14 @@ PIXI.Strip = function(texture, width, height)
PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
PIXI.Strip.prototype.constructor = PIXI.Strip;
/*
* Sets the texture that the Strip will use
* TODO-Alvin
*
* @method setTexture
* @param texture {Texture} the texture that will be used
* @private
*/
PIXI.Strip.prototype.setTexture = function(texture)
{
//TODO SET THE TEXTURES
@@ -81,6 +99,13 @@ PIXI.Strip.prototype.setTexture = function(texture)
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;
+315 -27
View File
@@ -14,31 +14,22 @@
*/
PIXI.TilingSprite = function(texture, width, height)
{
PIXI.DisplayObjectContainer.call( this );
PIXI.Sprite.call( this, texture);
/**
* The texture that the sprite is using
*
* @property texture
* @type Texture
*/
this.texture = texture;
/**
* The width of the tiling sprite
* The with of the tiling sprite
*
* @property width
* @type Number
*/
this.width = width;
this.width = width || 100;
/**
* The height of the tiling sprite
*
* @property height
* @type Number
*/
this.height = height;
this.height = height || 100;
/**
* The scaling of the image that is being tiled
@@ -48,6 +39,14 @@ PIXI.TilingSprite = function(texture, width, height)
*/
this.tileScale = new PIXI.Point(1,1);
/**
*
*
* @property tileScaleOffset
* @type Point
*/
this.tileScaleOffset = new PIXI.Point(1,1);
/**
* The offset position of the image that is being tiled
*
@@ -58,31 +57,63 @@ PIXI.TilingSprite = function(texture, width, height)
this.renderable = true;
/**
* The tint applied to the sprite. This is a hex value
*
* @property tint
* @type Number
* @default 0xFFFFFF
*/
this.tint = 0xFFFFFF;
/**
* The blend mode to be applied to the sprite
*
* @property blendMode
* @type Number
* @default PIXI.blendModes.NORMAL;
*/
this.blendMode = PIXI.blendModes.NORMAL;
};
// constructor
PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
PIXI.TilingSprite.prototype = Object.create( PIXI.Sprite.prototype );
PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;
/**
* Sets the texture of the tiling sprite
* The width of the sprite, setting this will actually modify the scale to achieve the value set
*
* @method setTexture
* @param texture {Texture} The PIXI texture that is displayed by the sprite
* @property width
* @type Number
*/
PIXI.TilingSprite.prototype.setTexture = function(texture)
{
//TODO SET THE TEXTURES
//TODO VISIBILITY
// stop current texture
this.texture = texture;
this.updateFrame = true;
};
Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {
get: function() {
return this._width;
},
set: function(value) {
this._width = value;
}
});
/**
* When the texture is updated, this event will fire to update the frame
* 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;
}
});
/**
* When the texture is updated, this event will fire to update the scale and frame
*
* @method onTextureUpdate
* @param event
@@ -90,5 +121,262 @@ PIXI.TilingSprite.prototype.setTexture = function(texture)
*/
PIXI.TilingSprite.prototype.onTextureUpdate = function()
{
// so if _width is 0 then width was not set..
//console.log("HI MUM")
this.updateFrame = true;
};
PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
{
if(this.visible === false || this.alpha === 0)return;
var i,j;
if(this.mask || this.filters)
{
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.tilingTexture)this.generateTilingTexture(true);
else renderSession.spriteBatch.renderTilingSprite(this);
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if(this.filters)renderSession.filterManager.popFilter();
if(this.mask)renderSession.maskManager.popMask(renderSession);
renderSession.spriteBatch.start();
}
else
{
if(!this.tilingTexture)this.generateTilingTexture(true);
else renderSession.spriteBatch.renderTilingSprite(this);
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
};
PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
{
if(this.visible === false || this.alpha === 0)return;
var context = renderSession.context;
if(this._mask)
{
renderSession.maskManager.pushMask(this._mask, context);
}
context.globalAlpha = this.worldAlpha;
var transform = this.worldTransform;
// allow for trimming
context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
if(!this.__tilePattern)
{
this.generateTilingTexture(false);
if(this.tilingTexture)
{
this.__tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
}
}
// check blend mode
if(this.blendMode !== renderSession.currentBlendMode)
{
renderSession.currentBlendMode = this.blendMode;
context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
}
context.beginPath();
var tilePosition = this.tilePosition;
var tileScale = this.tileScale;
tilePosition.x %= this.tilingTexture.baseTexture.width;
tilePosition.y %= this.tilingTexture.baseTexture.height;
// console.log(tileScale.x)
// offset
context.scale(tileScale.x,tileScale.y);
context.translate(tilePosition.x, tilePosition.y);
context.fillStyle = this.__tilePattern;
context.fillRect(-tilePosition.x,-tilePosition.y,this.width / tileScale.x, this.height / tileScale.y);
context.scale(1/tileScale.x, 1/tileScale.y);
context.translate(-tilePosition.x, -tilePosition.y);
context.closePath();
if(this._mask)
{
renderSession.maskManager.popMask(renderSession.context);
}
};
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.c;
var c = worldTransform.b;
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.generateTilingTexture = function(forcePowerOfTwo)
{
var texture = this.texture;
if(!texture.baseTexture.hasLoaded)return;
var baseTexture = texture.baseTexture;
var frame = texture.frame;
var targetWidth, targetHeight;
// check that the frame is the same size as the base texture.
var isFrame = frame.width !== baseTexture.width || frame.height !== baseTexture.height;
this.tilingTexture = texture;
var newTextureRequired = false;
if(!forcePowerOfTwo)
{
if(isFrame)
{
targetWidth = frame.width;
targetHeight = frame.height;
newTextureRequired = true;
}
}
else
{
targetWidth = PIXI.getNextPowerOfTwo(texture.frame.width);
targetHeight = PIXI.getNextPowerOfTwo(texture.frame.height);
if(frame.width !== targetWidth && frame.height !== targetHeight)newTextureRequired = true;
}
if(newTextureRequired)
{
var canvasBuffer = new PIXI.CanvasBuffer(targetWidth, targetHeight);
canvasBuffer.context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
0,
0,
targetWidth,
targetHeight);
this.tilingTexture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
this.tileScaleOffset.x = frame.width / targetWidth;
this.tileScaleOffset.y = frame.height / targetHeight;
}
this.tilingTexture.baseTexture._powerOf2 = true;
};
+16 -5
View File
@@ -3,7 +3,7 @@
*/
/**
* This is the base class for creating a pixi.js filter. Currently only webGL supports filters.
* This is the base class for creating a pixi.js filter. Currently only webGL supports filters.
* If you want to make a custom filter this should be your base class.
* @class AbstractFilter
* @constructor
@@ -21,15 +21,26 @@ PIXI.AbstractFilter = function(fragmentSrc, uniforms)
*/
this.passes = [this];
/**
* @property shaders
* @type Array an array of shaders
* @private
*/
this.shaders = [];
this.dirty = true;
this.padding = 0;
/**
@property uniforms
@private
* @property uniforms
* @type object
* @private
*/
this.uniforms = uniforms || {};
/**
* @property fragmentSrc
* @type Array
* @private
*/
this.fragmentSrc = fragmentSrc || [];
};
+93
View File
@@ -0,0 +1,93 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
*
* The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object.
* You can use this filter to apply all manor of crazy warping effects
* Currently the r property of the texture is used to offset the x and the g propery of the texture is used to offset the y.
* @class AlphaMaskFilter
* @contructor
* @param texture {Texture} The texture used for the displacemtent map * must be power of 2 texture at the moment
*/
PIXI.AlphaMaskFilter = function(texture)
{
PIXI.AbstractFilter.call( this );
this.passes = [this];
texture.baseTexture._powerOf2 = true;
// set the uniforms
//console.log()
this.uniforms = {
mask: {type: 'sampler2D', value:texture},
mapDimensions: {type: '2f', value:{x:1, y:5112}},
dimensions: {type: '4fv', value:[0,0,0,0]}
};
if(texture.baseTexture.hasLoaded)
{
this.uniforms.mask.value.x = texture.width;
this.uniforms.mask.value.y = texture.height;
}
else
{
this.boundLoadedFunction = this.onTextureLoaded.bind(this);
texture.baseTexture.on('loaded', this.boundLoadedFunction);
}
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying vec4 vColor;',
'uniform sampler2D mask;',
'uniform sampler2D uSampler;',
'uniform vec2 offset;',
'uniform vec4 dimensions;',
'uniform vec2 mapDimensions;',
'void main(void) {',
' vec2 mapCords = vTextureCoord.xy;',
' mapCords += (dimensions.zw + offset)/ dimensions.xy ;',
' mapCords.y *= -1.0;',
' mapCords.y += 1.0;',
' mapCords *= dimensions.xy / mapDimensions;',
' vec4 original = texture2D(uSampler, vTextureCoord);',
' float maskAlpha = texture2D(mask, mapCords).r;',
' original *= maskAlpha;',
//' original.rgb *= maskAlpha;',
' gl_FragColor = original;',
//' gl_FragColor = gl_FragColor;',
'}'
];
};
PIXI.AlphaMaskFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
PIXI.AlphaMaskFilter.prototype.constructor = PIXI.AlphaMaskFilter;
PIXI.AlphaMaskFilter.prototype.onTextureLoaded = function()
{
this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width;
this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height;
this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction);
};
/**
* The texture used for the displacemtent map * must be power of 2 texture at the moment
*
* @property map
* @type Texture
*/
Object.defineProperty(PIXI.AlphaMaskFilter.prototype, 'map', {
get: function() {
return this.uniforms.mask.value;
},
set: function(value) {
this.uniforms.mask.value = value;
}
});
+2 -2
View File
@@ -35,7 +35,7 @@ Object.defineProperty(PIXI.BlurFilter.prototype, 'blur', {
});
/**
* Sets the strength of the blurX property simultaneously
* Sets the strength of the blurX property
*
* @property blurX
* @type Number the strength of the blurX
@@ -51,7 +51,7 @@ Object.defineProperty(PIXI.BlurFilter.prototype, 'blurX', {
});
/**
* Sets the strength of the blurX property simultaneously
* Sets the strength of the blurX property
*
* @property blurY
* @type Number the strength of the blurY
+1 -1
View File
@@ -16,7 +16,7 @@ PIXI.BlurXFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float blur;',
'uniform sampler2D uSampler;',
+1 -1
View File
@@ -16,7 +16,7 @@ PIXI.BlurYFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float blur;',
'uniform sampler2D uSampler;',
+2 -2
View File
@@ -27,14 +27,14 @@ PIXI.ColorMatrixFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float invert;',
'uniform mat4 matrix;',
'uniform sampler2D uSampler;',
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;',
' gl_FragColor = gl_FragColor * vColor;',
// ' gl_FragColor = gl_FragColor;',
'}'
];
};
+3 -3
View File
@@ -4,7 +4,7 @@
/**
*
* This turns your displayObjects to black and white.
* This lowers the color depth of your image by the given amount, producing an image with a smaller palette.
* @class ColorStepFilter
* @contructor
*/
@@ -22,14 +22,14 @@ PIXI.ColorStepFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform sampler2D uSampler;',
'uniform float step;',
'void main(void) {',
' vec4 color = texture2D(uSampler, vTextureCoord);',
' color = floor(color * step) / step;',
' gl_FragColor = color * vColor;',
' gl_FragColor = color;',
'}'
];
};
+1 -1
View File
@@ -16,7 +16,7 @@ PIXI.CrossHatchFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float blur;',
'uniform sampler2D uSampler;',
+3 -2
View File
@@ -19,6 +19,7 @@ PIXI.DisplacementFilter = function(texture)
texture.baseTexture._powerOf2 = true;
// set the uniforms
//console.log()
this.uniforms = {
displacementMap: {type: 'sampler2D', value:texture},
scale: {type: '2f', value:{x:30, y:30}},
@@ -42,7 +43,7 @@ PIXI.DisplacementFilter = function(texture)
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform sampler2D displacementMap;',
'uniform sampler2D uSampler;',
'uniform vec2 scale;',
@@ -66,7 +67,7 @@ PIXI.DisplacementFilter = function(texture)
' vec2 cord = vTextureCoord;',
//' gl_FragColor = texture2D(displacementMap, cord);',
' gl_FragColor = gl_FragColor * vColor;',
// ' gl_FragColor = gl_FragColor;',
'}'
];
};
+3 -3
View File
@@ -5,8 +5,8 @@
/**
*
* This filter applies a pixlate effect making display objects appear 'blocky'
* @class PixelateFilter
* This filter applies a dotscreen effect making display objects appear to be made out of black and white halftone dots like an old printer
* @class DotScreenFilter
* @contructor
*/
PIXI.DotScreenFilter = function()
@@ -25,7 +25,7 @@ PIXI.DotScreenFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform vec4 dimensions;',
'uniform sampler2D uSampler;',
+2 -2
View File
@@ -22,14 +22,14 @@ PIXI.GrayFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform sampler2D uSampler;',
'uniform float gray;',
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord);',
' gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);',
' gl_FragColor = gl_FragColor * vColor;',
// ' gl_FragColor = gl_FragColor;',
'}'
];
};
+2 -2
View File
@@ -22,7 +22,7 @@ PIXI.InvertFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float invert;',
'uniform sampler2D uSampler;',
@@ -30,7 +30,7 @@ PIXI.InvertFilter = function()
' gl_FragColor = texture2D(uSampler, vTextureCoord);',
' gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, 1.0 - invert);',
//' gl_FragColor.rgb = gl_FragColor.rgb * gl_FragColor.a;',
' gl_FragColor = gl_FragColor * vColor;',
// ' gl_FragColor = gl_FragColor * vColor;',
'}'
];
};
+225
View File
@@ -0,0 +1,225 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
*
* The NormalMapFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object.
* You can use this filter to apply all manor of crazy warping effects
* Currently the r property of the texture is used offset the x and the g propery of the texture is used to offset the y.
* @class NormalMapFilter
* @contructor
* @param texture {Texture} The texture used for the displacemtent map * must be power of 2 texture at the moment
*/
PIXI.NormalMapFilter = function(texture)
{
PIXI.AbstractFilter.call( this );
this.passes = [this];
texture.baseTexture._powerOf2 = true;
// set the uniforms
//console.log()
this.uniforms = {
displacementMap: {type: 'sampler2D', value:texture},
scale: {type: '2f', value:{x:15, y:15}},
offset: {type: '2f', value:{x:0, y:0}},
mapDimensions: {type: '2f', value:{x:1, y:1}},
dimensions: {type: '4f', value:[0,0,0,0]},
// LightDir: {type: 'f3', value:[0, 1, 0]},
LightPos: {type: '3f', value:[0, 1, 0]}
};
if(texture.baseTexture.hasLoaded)
{
this.uniforms.mapDimensions.value.x = texture.width;
this.uniforms.mapDimensions.value.y = texture.height;
}
else
{
this.boundLoadedFunction = this.onTextureLoaded.bind(this);
texture.baseTexture.on("loaded", this.boundLoadedFunction);
}
this.fragmentSrc = [
"precision mediump float;",
"varying vec2 vTextureCoord;",
"varying float vColor;",
"uniform sampler2D displacementMap;",
"uniform sampler2D uSampler;",
"uniform vec4 dimensions;",
"const vec2 Resolution = vec2(1.0,1.0);", //resolution of screen
"uniform vec3 LightPos;", //light position, normalized
"const vec4 LightColor = vec4(1.0, 1.0, 1.0, 1.0);", //light RGBA -- alpha is intensity
"const vec4 AmbientColor = vec4(1.0, 1.0, 1.0, 0.5);", //ambient RGBA -- alpha is intensity
"const vec3 Falloff = vec3(0.0, 1.0, 0.2);", //attenuation coefficients
"uniform vec3 LightDir;",//" = vec3(1.0, 0.0, 1.0);",
"uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);",
"void main(void) {",
"vec2 mapCords = vTextureCoord.xy;",
"vec4 color = texture2D(uSampler, vTextureCoord.st);",
"vec3 nColor = texture2D(displacementMap, vTextureCoord.st).rgb;",
"mapCords *= vec2(dimensions.x/512.0, dimensions.y/512.0);",
"mapCords.y *= -1.0;",
"mapCords.y += 1.0;",
//RGBA of our diffuse color
"vec4 DiffuseColor = texture2D(uSampler, vTextureCoord);",
//RGB of our normal map
"vec3 NormalMap = texture2D(displacementMap, mapCords).rgb;",
//The delta position of light
//"vec3 LightDir = vec3(LightPos.xy - (gl_FragCoord.xy / Resolution.xy), LightPos.z);",
"vec3 LightDir = vec3(LightPos.xy - (mapCords.xy), LightPos.z);",
//Correct for aspect ratio
//"LightDir.x *= Resolution.x / Resolution.y;",
//Determine distance (used for attenuation) BEFORE we normalize our LightDir
"float D = length(LightDir);",
//normalize our vectors
"vec3 N = normalize(NormalMap * 2.0 - 1.0);",
"vec3 L = normalize(LightDir);",
//Pre-multiply light color with intensity
//Then perform "N dot L" to determine our diffuse term
"vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(N, L), 0.0);",
//pre-multiply ambient color with intensity
"vec3 Ambient = AmbientColor.rgb * AmbientColor.a;",
//calculate attenuation
"float Attenuation = 1.0 / ( Falloff.x + (Falloff.y*D) + (Falloff.z*D*D) );",
//the calculation which brings it all together
"vec3 Intensity = Ambient + Diffuse * Attenuation;",
"vec3 FinalColor = DiffuseColor.rgb * Intensity;",
"gl_FragColor = vColor * vec4(FinalColor, DiffuseColor.a);",
//"gl_FragColor = vec4(1.0, 0.0, 0.0, Attenuation);",//vColor * vec4(FinalColor, DiffuseColor.a);",
/*
// normalise color
"vec3 normal = normalize(nColor * 2.0 - 1.0);",
"vec3 deltaPos = vec3( (light.xy - gl_FragCoord.xy) / resolution.xy, light.z );",
"float lambert = clamp(dot(normal, lightDir), 0.0, 1.0);",
"float d = sqrt(dot(deltaPos, deltaPos));",
"float att = 1.0 / ( attenuation.x + (attenuation.y*d) + (attenuation.z*d*d) );",
"vec3 result = (ambientColor * ambientIntensity) + (lightColor.rgb * lambert) * att;",
"result *= color.rgb;",
"gl_FragColor = vec4(result, 1.0);",*/
"}"
];
}
/*
void main() {
//sample color & normals from our textures
vec4 color = texture2D(u_texture, v_texCoords.st);
vec3 nColor = texture2D(u_normals, v_texCoords.st).rgb;
//some bump map programs will need the Y value flipped..
nColor.g = yInvert ? 1.0 - nColor.g : nColor.g;
//this is for debugging purposes, allowing us to lower the intensity of our bump map
vec3 nBase = vec3(0.5, 0.5, 1.0);
nColor = mix(nBase, nColor, strength);
//normals need to be converted to [-1.0, 1.0] range and normalized
vec3 normal = normalize(nColor * 2.0 - 1.0);
//here we do a simple distance calculation
vec3 deltaPos = vec3( (light.xy - gl_FragCoord.xy) / resolution.xy, light.z );
vec3 lightDir = normalize(deltaPos);
float lambert = useNormals ? clamp(dot(normal, lightDir), 0.0, 1.0) : 1.0;
//now let's get a nice little falloff
float d = sqrt(dot(deltaPos, deltaPos));
float att = useShadow ? 1.0 / ( attenuation.x + (attenuation.y*d) + (attenuation.z*d*d) ) : 1.0;
vec3 result = (ambientColor * ambientIntensity) + (lightColor.rgb * lambert) * att;
result *= color.rgb;
gl_FragColor = v_color * vec4(result, color.a);
}
*/
PIXI.NormalMapFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
PIXI.NormalMapFilter.prototype.constructor = PIXI.NormalMapFilter;
PIXI.NormalMapFilter.prototype.onTextureLoaded = function()
{
this.uniforms.mapDimensions.value.x = this.uniforms.displacementMap.value.width;
this.uniforms.mapDimensions.value.y = this.uniforms.displacementMap.value.height;
this.uniforms.displacementMap.value.baseTexture.off("loaded", this.boundLoadedFunction)
}
/**
* The texture used for the displacemtent map * must be power of 2 texture at the moment
*
* @property map
* @type Texture
*/
Object.defineProperty(PIXI.NormalMapFilter.prototype, 'map', {
get: function() {
return this.uniforms.displacementMap.value;
},
set: function(value) {
this.uniforms.displacementMap.value = value;
}
});
/**
* The multiplier used to scale the displacement result from the map calculation.
*
* @property scale
* @type Point
*/
Object.defineProperty(PIXI.NormalMapFilter.prototype, 'scale', {
get: function() {
return this.uniforms.scale.value;
},
set: function(value) {
this.uniforms.scale.value = value;
}
});
/**
* The offset used to move the displacement map.
*
* @property offset
* @type Point
*/
Object.defineProperty(PIXI.NormalMapFilter.prototype, 'offset', {
get: function() {
return this.uniforms.offset.value;
},
set: function(value) {
this.uniforms.offset.value = value;
}
});
+2 -2
View File
@@ -4,7 +4,7 @@
/**
*
* This filter applies a pixlate effect making display objects appear 'blocky'
* This filter applies a pixelate effect making display objects appear 'blocky'
* @class PixelateFilter
* @contructor
*/
@@ -24,7 +24,7 @@ PIXI.PixelateFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform vec2 testDim;',
'uniform vec4 dimensions;',
'uniform vec2 pixelSize;',
+1 -1
View File
@@ -19,7 +19,7 @@ PIXI.RGBSplitFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform vec2 red;',
'uniform vec2 green;',
'uniform vec2 blue;',
+2 -2
View File
@@ -22,7 +22,7 @@ PIXI.SepiaFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform float sepia;',
'uniform sampler2D uSampler;',
@@ -31,7 +31,7 @@ PIXI.SepiaFilter = function()
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord);',
' gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb * sepiaMatrix, sepia);',
' gl_FragColor = gl_FragColor * vColor;',
// ' gl_FragColor = gl_FragColor * vColor;',
'}'
];
};
+3 -3
View File
@@ -4,8 +4,8 @@
/**
*
* This filter applies a pixlate effect making display objects appear 'blocky'
* @class PixelateFilter
* This filter applies a twist effect making display objects appear twisted in the given direction
* @class TwistFilter
* @contructor
*/
PIXI.TwistFilter = function()
@@ -24,7 +24,7 @@ PIXI.TwistFilter = function()
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform vec4 dimensions;',
'uniform sampler2D uSampler;',
+6 -1
View File
@@ -70,7 +70,12 @@ PIXI.AssetLoader = function(assetURLs, crossorigin)
// constructor
PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader;
/**
* Given a filename, returns its extension, wil
*
* @method _getDataType
* @param str {String} the name of the asset
*/
PIXI.AssetLoader.prototype._getDataType = function(str)
{
var test = 'data:';
+11 -5
View File
@@ -3,9 +3,9 @@
*/
/**
* The atlas file loader is used to load in Atlas data and parsing it
* The atlas file loader is used to load in Atlas data and parse it
* When loaded this class will dispatch a 'loaded' event
* If load failed this class will dispatch a 'error' event
* If loading fails this class will dispatch an 'error' event
* @class AtlasLoader
* @extends EventTarget
* @constructor
@@ -25,8 +25,11 @@ PIXI.AtlasLoader = function (url, crossorigin) {
// constructor
PIXI.AtlasLoader.constructor = PIXI.AtlasLoader;
/**
* This will begin loading the JSON file
/**
* Starts loading the JSON file
*
* @method load
*/
PIXI.AtlasLoader.prototype.load = function () {
this.ajaxRequest = new PIXI.AjaxRequest();
@@ -39,6 +42,7 @@ PIXI.AtlasLoader.prototype.load = function () {
/**
* Invoke when JSON file is loaded
* @method onAtlasLoaded
* @private
*/
PIXI.AtlasLoader.prototype.onAtlasLoaded = function () {
@@ -156,7 +160,8 @@ PIXI.AtlasLoader.prototype.onAtlasLoaded = function () {
};
/**
* Invoke when json file loaded
* Invoke when json file has loaded
* @method onLoaded
* @private
*/
PIXI.AtlasLoader.prototype.onLoaded = function () {
@@ -174,6 +179,7 @@ PIXI.AtlasLoader.prototype.onLoaded = function () {
/**
* Invoke when error occured
* @method onError
* @private
*/
PIXI.AtlasLoader.prototype.onError = function () {
+34 -22
View File
@@ -17,7 +17,7 @@
PIXI.BitmapFontLoader = function(url, crossorigin)
{
/*
* i use texture packer to load the assets..
* I use texture packer to load the assets..
* http://www.codeandweb.com/texturepacker
* make sure to set the format as 'JSON'
*/
@@ -67,7 +67,7 @@ PIXI.BitmapFontLoader.prototype.constructor = PIXI.BitmapFontLoader;
*/
PIXI.BitmapFontLoader.prototype.load = function()
{
this.ajaxRequest = new XMLHttpRequest();
this.ajaxRequest = new PIXI.AjaxRequest();
var scope = this;
this.ajaxRequest.onreadystatechange = function()
{
@@ -80,7 +80,7 @@ PIXI.BitmapFontLoader.prototype.load = function()
};
/**
* Invoked when XML file is loaded, parses the data
* Invoked when the XML file is loaded, parses the data
*
* @method onXMLLoaded
* @private
@@ -91,36 +91,48 @@ PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
{
if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1)
{
var textureUrl = this.baseUrl + this.ajaxRequest.responseXML.getElementsByTagName('page')[0].attributes.getNamedItem('file').nodeValue;
var responseXML = this.ajaxRequest.responseXML;
if(!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) {
if(typeof(window.DOMParser) === 'function') {
var domparser = new DOMParser();
responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml');
} else {
var div = document.createElement('div');
div.innerHTML = this.ajaxRequest.responseText;
responseXML = div;
}
}
var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file');
var image = new PIXI.ImageLoader(textureUrl, this.crossorigin);
this.texture = image.texture.baseTexture;
var data = {};
var info = this.ajaxRequest.responseXML.getElementsByTagName('info')[0];
var common = this.ajaxRequest.responseXML.getElementsByTagName('common')[0];
data.font = info.attributes.getNamedItem('face').nodeValue;
data.size = parseInt(info.attributes.getNamedItem('size').nodeValue, 10);
data.lineHeight = parseInt(common.attributes.getNamedItem('lineHeight').nodeValue, 10);
var info = responseXML.getElementsByTagName('info')[0];
var common = responseXML.getElementsByTagName('common')[0];
data.font = info.getAttribute('face');
data.size = parseInt(info.getAttribute('size'), 10);
data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10);
data.chars = {};
//parse letters
var letters = this.ajaxRequest.responseXML.getElementsByTagName('char');
var letters = responseXML.getElementsByTagName('char');
for (var i = 0; i < letters.length; i++)
{
var charCode = parseInt(letters[i].attributes.getNamedItem('id').nodeValue, 10);
var charCode = parseInt(letters[i].getAttribute('id'), 10);
var textureRect = new PIXI.Rectangle(
parseInt(letters[i].attributes.getNamedItem('x').nodeValue, 10),
parseInt(letters[i].attributes.getNamedItem('y').nodeValue, 10),
parseInt(letters[i].attributes.getNamedItem('width').nodeValue, 10),
parseInt(letters[i].attributes.getNamedItem('height').nodeValue, 10)
parseInt(letters[i].getAttribute('x'), 10),
parseInt(letters[i].getAttribute('y'), 10),
parseInt(letters[i].getAttribute('width'), 10),
parseInt(letters[i].getAttribute('height'), 10)
);
data.chars[charCode] = {
xOffset: parseInt(letters[i].attributes.getNamedItem('xoffset').nodeValue, 10),
yOffset: parseInt(letters[i].attributes.getNamedItem('yoffset').nodeValue, 10),
xAdvance: parseInt(letters[i].attributes.getNamedItem('xadvance').nodeValue, 10),
xOffset: parseInt(letters[i].getAttribute('xoffset'), 10),
yOffset: parseInt(letters[i].getAttribute('yoffset'), 10),
xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10),
kerning: {},
texture: PIXI.TextureCache[charCode] = new PIXI.Texture(this.texture, textureRect)
@@ -128,12 +140,12 @@ PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
}
//parse kernings
var kernings = this.ajaxRequest.responseXML.getElementsByTagName('kerning');
var kernings = responseXML.getElementsByTagName('kerning');
for (i = 0; i < kernings.length; i++)
{
var first = parseInt(kernings[i].attributes.getNamedItem('first').nodeValue, 10);
var second = parseInt(kernings[i].attributes.getNamedItem('second').nodeValue, 10);
var amount = parseInt(kernings[i].attributes.getNamedItem('amount').nodeValue, 10);
var first = parseInt(kernings[i].getAttribute('first'), 10);
var second = parseInt(kernings[i].getAttribute('second'), 10);
var amount = parseInt(kernings[i].getAttribute('amount'), 10);
data.chars[second].kerning[first] = amount;
+2 -2
View File
@@ -4,7 +4,7 @@
/**
* The image loader class is responsible for loading images file formats ('jpeg', 'jpg', 'png' and 'gif')
* Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()
* Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFrameId()
* When loaded this class will dispatch a 'loaded' event
*
* @class ImageLoader
@@ -73,7 +73,7 @@ PIXI.ImageLoader.prototype.onLoaded = function()
*
*
* @method loadFramedSpriteSheet
* @param frameWidth {Number} with of each frame
* @param frameWidth {Number} width of each frame
* @param frameHeight {Number} height of each frame
* @param textureName {String} if given, the frames will be cached in <textureName>-<ord> format
*/
+17 -7
View File
@@ -3,9 +3,9 @@
*/
/**
* The json file loader is used to load in JSON data and parsing it
* The json file loader is used to load in JSON data and parse it
* When loaded this class will dispatch a 'loaded' event
* If load failed this class will dispatch a 'error' event
* If loading fails this class will dispatch an 'error' event
*
* @class JsonLoader
* @uses EventTarget
@@ -61,7 +61,7 @@ PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader;
* @method load
*/
PIXI.JsonLoader.prototype.load = function () {
this.ajaxRequest = new PIXI.AjaxRequest();
this.ajaxRequest = new PIXI.AjaxRequest(this.crossorigin);
var scope = this;
this.ajaxRequest.onreadystatechange = function () {
scope.onJSONLoaded();
@@ -105,11 +105,21 @@ PIXI.JsonLoader.prototype.onJSONLoaded = function () {
width: rect.w,
height: rect.h
});
// check to see ifthe sprite ha been trimmed..
if (frameData[i].trimmed) {
//var realSize = frameData[i].spriteSourceSize;
PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize;
PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
// calculate the offset!
var texture = PIXI.TextureCache[i];
texture.trimmed = true;
var actualSize = frameData[i].sourceSize;
var realSize = frameData[i].spriteSourceSize;
texture.trim.x = realSize.x;
texture.trim.y = realSize.y;
texture.trim.realWidth = actualSize.w;
texture.trim.realHeight = actualSize.h;
}
}
}
+2 -17
View File
@@ -9,7 +9,7 @@
/**
* The Spine loader is used to load in JSON spine data
* To generate the data you need to use http://esotericsoftware.com/ and export the "JSON" format
* To generate the data you need to use http://esotericsoftware.com/ and export in the "JSON" format
* Due to a clash of names You will need to change the extension of the spine file from *.json to *.anim for it to load
* See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
* You will need to generate a sprite sheet to accompany the spine data
@@ -64,26 +64,11 @@ PIXI.SpineLoader.prototype.load = function () {
var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin);
jsonLoader.addEventListener("loaded", function (event) {
scope.json = event.content.json;
scope.onJSONLoaded();
scope.onLoaded();
});
jsonLoader.load();
};
/**
* Invoke when JSON file is loaded
*
* @method onJSONLoaded
* @private
*/
PIXI.SpineLoader.prototype.onJSONLoaded = function () {
var spineJsonParser = new spine.SkeletonJson();
var skeletonData = spineJsonParser.readSkeletonData(this.json);
PIXI.AnimCache[this.url] = skeletonData;
this.onLoaded();
};
/**
* Invoke when JSON file is loaded
*
+5 -43
View File
@@ -4,11 +4,11 @@
/**
* The sprite sheet loader is used to load in JSON sprite sheet data
* To generate the data you can use http://www.codeandweb.com/texturepacker and publish the 'JSON' format
* To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format
* There is a free version so thats nice, although the paid version is great value for money.
* It is highly recommended to use Sprite sheets (also know as texture atlas') as it means sprite's can be batched and drawn together for highly increased rendering speed.
* Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()
* This loader will also load the image file that the Spritesheet points to as well as the data.
* It is highly recommended to use Sprite sheets (also know as a 'texture atlas') as it means sprites can be batched and drawn together for highly increased rendering speed.
* Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFrameId()
* This loader will load the image file that the Spritesheet points to as well as the data.
* When loaded this class will dispatch a 'loaded' event
*
* @class SpriteSheetLoader
@@ -80,47 +80,9 @@ PIXI.SpriteSheetLoader.prototype.load = function () {
var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin);
jsonLoader.addEventListener('loaded', function (event) {
scope.json = event.content.json;
scope.onJSONLoaded();
});
jsonLoader.load();
};
/**
* Invoke when JSON file is loaded
*
* @method onJSONLoaded
* @private
*/
PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () {
var scope = this;
var textureUrl = this.baseUrl + this.json.meta.image;
var image = new PIXI.ImageLoader(textureUrl, this.crossorigin);
var frameData = this.json.frames;
this.texture = image.texture.baseTexture;
image.addEventListener('loaded', function () {
scope.onLoaded();
});
for (var i in frameData) {
var rect = frameData[i].frame;
if (rect) {
PIXI.TextureCache[i] = new PIXI.Texture(this.texture, {
x: rect.x,
y: rect.y,
width: rect.w,
height: rect.h
});
if (frameData[i].trimmed) {
//var realSize = frameData[i].spriteSourceSize;
PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize;
PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
// calculate the offset!
}
}
}
image.load();
jsonLoader.load();
};
/**
+406 -76
View File
@@ -5,8 +5,8 @@
/**
* The Graphics class contains a set of methods that you can use to create primitive shapes and lines.
* It is important to know that with the webGL renderer only simple polys can be filled at this stage
* Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png
* It is important to know that with the webGL renderer only simple polygons can be filled at this stage
* Complex polygons will not be filled. Heres an example of a complex polygon: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png
*
* @class Graphics
* @extends DisplayObjectContainer
@@ -51,6 +51,25 @@ PIXI.Graphics = function()
*/
this.graphicsData = [];
/**
* The tint applied to the graphic shape. This is a hex value
*
* @property tint
* @type Number
* @default 0xFFFFFF
*/
this.tint = 0xFFFFFF;// * Math.random();
/**
* The blend mode to be applied to the graphic shape
*
* @property blendMode
* @type Number
* @default PIXI.blendModes.NORMAL;
*/
this.blendMode = PIXI.blendModes.NORMAL;
/**
* Current path
*
@@ -59,6 +78,39 @@ PIXI.Graphics = function()
* @private
*/
this.currentPath = {points:[]};
/**
* WebGL lines ? TODO-Alvin
*
* @property _webGL
* @type Array
* @private
*/
this._webGL = [];
/**
* Whether this shape is used as a mask
*
* @property isMask
* @type isMask
*/
this.isMask = false;
/**
* The bounds of the graphic shape as rectangle object
*
* @property bounds
* @type Rectangle
*/
this.bounds = null;
/**
* the bound padding TODO-Alvin
*
* @property bounds
* @type Number
*/
this.boundsPadding = 10;
};
// constructor
@@ -66,7 +118,39 @@ PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype )
PIXI.Graphics.prototype.constructor = PIXI.Graphics;
/**
* Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.
* If cacheAsBitmap is true the graphics object will then be rendered as if it was a sprite.
* This is useful if your graphics element does not change often as it will speed up the rendering of the object
* It is also usful as the graphics object will always be antialiased because it will be rendered using canvas
* Not recommended if you are constanly redrawing the graphics element.
*
* @property cacheAsBitmap
* @default false
* @type Boolean
* @private
*/
Object.defineProperty(PIXI.Graphics.prototype, "cacheAsBitmap", {
get: function() {
return this._cacheAsBitmap;
},
set: function(value) {
this._cacheAsBitmap = value;
if(this._cacheAsBitmap)
{
this._generateCachedSprite();
}
else
{
this.destroyCachedSprite();
this.dirty = true;
}
}
});
/**
* Specifies the line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.
*
* @method lineStyle
* @param lineWidth {Number} width of the line to draw, will update the object's stored style
@@ -91,8 +175,8 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha)
* Moves the current drawing position to (x, y).
*
* @method moveTo
* @param x {Number} the X coord to move to
* @param y {Number} the Y coord to move to
* @param x {Number} the X coordinate to move to
* @param y {Number} the Y coordinate to move to
*/
PIXI.Graphics.prototype.moveTo = function(x, y)
{
@@ -111,8 +195,8 @@ PIXI.Graphics.prototype.moveTo = function(x, y)
* the current drawing position is then set to (x, y).
*
* @method lineTo
* @param x {Number} the X coord to draw to
* @param y {Number} the Y coord to draw to
* @param x {Number} the X coordinate to draw to
* @param y {Number} the Y coordinate to draw to
*/
PIXI.Graphics.prototype.lineTo = function(x, y)
{
@@ -125,11 +209,12 @@ PIXI.Graphics.prototype.lineTo = function(x, y)
* (such as lineTo() or drawCircle()) use when drawing.
*
* @method beginFill
* @param color {uint} the color of the fill
* @param alpha {Number} the alpha
* @param color {Number} the color of the fill
* @param alpha {Number} the alpha of the fill
*/
PIXI.Graphics.prototype.beginFill = function(color, alpha)
{
this.filling = true;
this.fillColor = color || 0;
this.fillAlpha = (arguments.length < 2) ? 1 : alpha;
@@ -171,12 +256,13 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height )
* Draws a circle.
*
* @method drawCircle
* @param x {Number} The X coord of the center of the circle
* @param y {Number} The Y coord of the center of the circle
* @param x {Number} The X coordinate of the center of the circle
* @param y {Number} The Y coordinate of the center of the circle
* @param radius {Number} The radius of the circle
*/
PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
{
if (!this.currentPath.points.length) this.graphicsData.pop();
this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
@@ -191,13 +277,14 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
* Draws an ellipse.
*
* @method drawEllipse
* @param x {Number}
* @param y {Number}
* @param width {Number}
* @param height {Number}
* @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this ellipse
* @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this ellipse
* @param width {Number} The width of the ellipse
* @param height {Number} The height of the ellipse
*/
PIXI.Graphics.prototype.drawEllipse = function( x, y, width, height)
{
if (!this.currentPath.points.length) this.graphicsData.pop();
this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
@@ -225,74 +312,317 @@ PIXI.Graphics.prototype.clear = function()
this.bounds = null; //new PIXI.Rectangle();
};
PIXI.Graphics.prototype.updateFilterBounds = function()
/**
* Useful function that returns a texture of the graphics object that can then be used to create sprites
* This can be quite useful if your geometry is complicated and needs to be reused multiple times.
*
* @method generateTexture
* @return {Texture} a texture of the graphics object
*/
PIXI.Graphics.prototype.generateTexture = function()
{
if(!this.bounds)
var bounds = this.getBounds();
var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height);
var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
canvasBuffer.context.translate(-bounds.x,-bounds.y);
PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context);
return texture;
};
/**
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.Graphics.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 === false || this.alpha === 0 || this.isMask === true)return;
if(this._cacheAsBitmap)
{
var minX = Infinity;
var maxX = -Infinity;
var minY = Infinity;
var maxY = -Infinity;
var points, x, y;
for (var i = 0; i < this.graphicsData.length; i++) {
var data = this.graphicsData[i];
var type = data.type;
var lineWidth = data.lineWidth;
points = data.points;
if(type === PIXI.Graphics.RECT)
{
x = points.x - lineWidth/2;
y = points.y - lineWidth/2;
var width = points.width + lineWidth;
var height = points.height + lineWidth;
minX = x < minX ? x : minX;
maxX = x + width > maxX ? x + width : maxX;
minY = y < minY ? x : minY;
maxY = y + height > maxY ? y + height : maxY;
}
else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP)
{
x = points.x;
y = points.y;
var radius = points.radius + lineWidth/2;
minX = x - radius < minX ? x - radius : minX;
maxX = x + radius > maxX ? x + radius : maxX;
minY = y - radius < minY ? y - radius : minY;
maxY = y + radius > maxY ? y + radius : maxY;
}
else
{
// POLY
for (var j = 0; j < points.length; j+=2)
{
x = points[j];
y = points[j+1];
minX = x-lineWidth < minX ? x-lineWidth : minX;
maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
minY = y-lineWidth < minY ? y-lineWidth : minY;
maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
}
}
if(this.dirty)
{
this._generateCachedSprite();
// we will also need to update the texture on the gpu too!
PIXI.updateWebGLTexture(this._cachedSprite.texture.baseTexture, renderSession.gl);
this.dirty = false;
}
this.bounds = new PIXI.Rectangle(minX, minY, maxX - minX, maxY - minY);
PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession);
return;
}
else
{
renderSession.spriteBatch.stop();
if(this._mask)renderSession.maskManager.pushMask(this.mask, renderSession);
if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock);
// check blend mode
if(this.blendMode !== renderSession.spriteBatch.currentBlendMode)
{
renderSession.spriteBatch.currentBlendMode = this.blendMode;
var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode];
renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
}
PIXI.WebGLGraphics.renderGraphics(this, renderSession);
// only render if it has children!
if(this.children.length)
{
renderSession.spriteBatch.start();
// simple render children!
for(var i=0, j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
}
if(this._filters)renderSession.filterManager.popFilter();
if(this._mask)renderSession.maskManager.popMask(renderSession);
renderSession.drawCount++;
renderSession.spriteBatch.start();
}
// console.log(this.bounds);
};
/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.Graphics.prototype._renderCanvas = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(this.visible === false || this.alpha === 0 || this.isMask === true)return;
var context = renderSession.context;
var transform = this.worldTransform;
if(this.blendMode !== renderSession.currentBlendMode)
{
renderSession.currentBlendMode = this.blendMode;
context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
}
context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
PIXI.CanvasGraphics.renderGraphics(this, context);
// simple render children!
for(var i=0, j=this.children.length; i<j; i++)
{
this.children[i]._renderCanvas(renderSession);
}
};
/**
* Retrieves the bounds of the graphic shape as a rectangle object
*
* @method getBounds
* @return {Rectangle} the rectangular bounding area
*/
PIXI.Graphics.prototype.getBounds = function()
{
if(!this.bounds)this.updateBounds();
var w0 = this.bounds.x;
var w1 = this.bounds.width + this.bounds.x;
var h0 = this.bounds.y;
var h1 = this.bounds.height + this.bounds.y;
var worldTransform = this.worldTransform;
var a = worldTransform.a;
var b = worldTransform.c;
var c = worldTransform.b;
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;
return bounds;
};
/**
* Update the bounds of the object
*
* @method updateBounds
*/
PIXI.Graphics.prototype.updateBounds = function()
{
var minX = Infinity;
var maxX = -Infinity;
var minY = Infinity;
var maxY = -Infinity;
var points, x, y, w, h;
for (var i = 0; i < this.graphicsData.length; i++) {
var data = this.graphicsData[i];
var type = data.type;
var lineWidth = data.lineWidth;
points = data.points;
if(type === PIXI.Graphics.RECT)
{
x = points[0] - lineWidth/2;
y = points[1] - lineWidth/2;
w = points[2] + lineWidth;
h = points[3] + lineWidth;
minX = x < minX ? x : minX;
maxX = x + w > maxX ? x + w : maxX;
minY = y < minY ? x : minY;
maxY = y + h > maxY ? y + h : maxY;
}
else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP)
{
x = points[0];
y = points[1];
w = points[2] + lineWidth/2;
h = points[3] + lineWidth/2;
minX = x - w < minX ? x - w : minX;
maxX = x + w > maxX ? x + w : maxX;
minY = y - h < minY ? y - h : minY;
maxY = y + h > maxY ? y + h : maxY;
}
else
{
// POLY
for (var j = 0; j < points.length; j+=2)
{
x = points[j];
y = points[j+1];
minX = x-lineWidth < minX ? x-lineWidth : minX;
maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
minY = y-lineWidth < minY ? y-lineWidth : minY;
maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
}
}
}
var padding = this.boundsPadding;
this.bounds = new PIXI.Rectangle(minX - padding, minY - padding, (maxX - minX) + padding * 2, (maxY - minY) + padding * 2);
};
/**
* Generates the cached sprite that was made using the generate TODO-Alvin
*
* @method _generateCachedSprite
* @private
*/
PIXI.Graphics.prototype._generateCachedSprite = function()
{
var bounds = this.getBounds();
if(!this._cachedSprite)
{
var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height);
var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
this._cachedSprite = new PIXI.Sprite(texture);
this._cachedSprite.buffer = canvasBuffer;
this._cachedSprite.worldTransform = this.worldTransform;
}
else
{
this._cachedSprite.buffer.resize(bounds.width, bounds.height);
}
// leverage the anchor to account for the offset of the element
this._cachedSprite.anchor.x = -( bounds.x / bounds.width );
this._cachedSprite.anchor.y = -( bounds.y / bounds.height );
// this._cachedSprite.buffer.context.save();
this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y);
PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context);
// this._cachedSprite.buffer.context.restore();
};
PIXI.Graphics.prototype.destroyCachedSprite = function()
{
this._cachedSprite.texture.destroy(true);
// let the gc collect the unused sprite
// TODO could be object pooled!
this._cachedSprite = null;
};
// SOME TYPES:
PIXI.Graphics.POLY = 0;
PIXI.Graphics.RECT = 1;
+4 -4
View File
@@ -20,8 +20,8 @@ PIXI.CanvasGraphics = function()
* @static
* @private
* @method renderGraphics
* @param graphics {Graphics}
* @param context {Context2D}
* @param graphics {Graphics} the actual graphics object to render
* @param context {Context2D} the 2d drawing method of the canvas
*/
PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
{
@@ -154,8 +154,8 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
* @static
* @private
* @method renderGraphicsMask
* @param graphics {Graphics}
* @param context {Context2D}
* @param graphics {Graphics} the graphics which will be used as a mask
* @param context {Context2D} the context 2d method of the canvas
*/
PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
{
+176 -178
View File
@@ -8,14 +8,72 @@
*
* @class CanvasRenderer
* @constructor
* @param width=0 {Number} the width of the canvas view
* @param height=0 {Number} the height of the canvas view
* @param view {Canvas} the canvas to use as a view, optional
* @param transparent=false {Boolean} the transparency of the render view, default false
* @param width=800 {Number} the width of the canvas view
* @param height=600 {Number} the height of the canvas view
* @param [view] {HTMLCanvasElement} the canvas to use as a view, optional
* @param [transparent=false] {Boolean} the transparency of the render view, default false
*/
PIXI.CanvasRenderer = function(width, height, view, transparent)
{
this.transparent = transparent;
PIXI.defaultRenderer = PIXI.defaultRenderer || this;
this.type = PIXI.CANVAS_RENDERER;
/**
* Whether the render view is transparent
*
* @property transparent
* @type Boolean
*/
this.transparent = !!transparent;
if(!PIXI.blendModesCanvas)
{
PIXI.blendModesCanvas = [];
if(PIXI.canUseNewCanvasBlendModes())
{
PIXI.blendModesCanvas[PIXI.blendModes.NORMAL] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.ADD] = "lighter"; //IS THIS OK???
PIXI.blendModesCanvas[PIXI.blendModes.MULTIPLY] = "multiply";
PIXI.blendModesCanvas[PIXI.blendModes.SCREEN] = "screen";
PIXI.blendModesCanvas[PIXI.blendModes.OVERLAY] = "overlay";
PIXI.blendModesCanvas[PIXI.blendModes.DARKEN] = "darken";
PIXI.blendModesCanvas[PIXI.blendModes.LIGHTEN] = "lighten";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR_DODGE] = "color-dodge";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR_BURN] = "color-burn";
PIXI.blendModesCanvas[PIXI.blendModes.HARD_LIGHT] = "hard-light";
PIXI.blendModesCanvas[PIXI.blendModes.SOFT_LIGHT] = "soft-light";
PIXI.blendModesCanvas[PIXI.blendModes.DIFFERENCE] = "difference";
PIXI.blendModesCanvas[PIXI.blendModes.EXCLUSION] = "exclusion";
PIXI.blendModesCanvas[PIXI.blendModes.HUE] = "hue";
PIXI.blendModesCanvas[PIXI.blendModes.SATURATION] = "saturation";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR] = "color";
PIXI.blendModesCanvas[PIXI.blendModes.LUMINOSITY] = "luminosity";
}
else
{
// this means that the browser does not support the cool new blend modes in canvas "cough" ie "cough"
PIXI.blendModesCanvas[PIXI.blendModes.NORMAL] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.ADD] = "lighter"; //IS THIS OK???
PIXI.blendModesCanvas[PIXI.blendModes.MULTIPLY] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.SCREEN] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.OVERLAY] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.DARKEN] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.LIGHTEN] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR_DODGE] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR_BURN] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.HARD_LIGHT] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.SOFT_LIGHT] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.DIFFERENCE] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.EXCLUSION] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.HUE] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.SATURATION] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.COLOR] = "source-over";
PIXI.blendModesCanvas[PIXI.blendModes.LUMINOSITY] = "source-over";
}
}
/**
* The width of the canvas view
@@ -36,33 +94,19 @@ PIXI.CanvasRenderer = function(width, height, view, transparent)
this.height = height || 600;
/**
* The canvas element that the everything is drawn to
* The canvas element that everything is drawn to
*
* @property view
* @type Canvas
* @type HTMLCanvasElement
*/
this.view = view || document.createElement( 'canvas' );
this.view = view || document.createElement( "canvas" );
/**
* The canvas context that the everything is drawn to
* The canvas 2d context that everything is drawn with
* @property context
* @type Canvas 2d Context
* @type HTMLCanvasElement 2d Context
*/
this.context = this.view.getContext( '2d' );
//some filter variables
this.smoothProperty = null;
if('imageSmoothingEnabled' in this.context)
this.smoothProperty = 'imageSmoothingEnabled';
else if('webkitImageSmoothingEnabled' in this.context)
this.smoothProperty = 'webkitImageSmoothingEnabled';
else if('mozImageSmoothingEnabled' in this.context)
this.smoothProperty = 'mozImageSmoothingEnabled';
else if('oImageSmoothingEnabled' in this.context)
this.smoothProperty = 'oImageSmoothingEnabled';
this.scaleMode = null;
this.context = this.view.getContext( "2d", { alpha: this.transparent } );
this.refresh = true;
// hack to enable some hardware acceleration!
@@ -71,6 +115,34 @@ PIXI.CanvasRenderer = function(width, height, view, transparent)
this.view.width = this.width;
this.view.height = this.height;
this.count = 0;
/**
* Instance of a PIXI.CanvasMaskManager, handles masking when using the canvas renderer
* @property CanvasMaskManager
* @type CanvasMaskManager
*/
this.maskManager = new PIXI.CanvasMaskManager();
/**
* RenderSession TODO-Alvin
* @property renderSession
* @type Object
*/
this.renderSession = {
context: this.context,
maskManager: this.maskManager,
scaleMode: null,
smoothProperty: null
};
if("imageSmoothingEnabled" in this.context)
this.renderSession.smoothProperty = "imageSmoothingEnabled";
else if("webkitImageSmoothingEnabled" in this.context)
this.renderSession.smoothProperty = "webkitImageSmoothingEnabled";
else if("mozImageSmoothingEnabled" in this.context)
this.renderSession.smoothProperty = "mozImageSmoothingEnabled";
else if("oImageSmoothingEnabled" in this.context)
this.renderSession.smoothProperty = "oImageSmoothingEnabled";
};
// constructor
@@ -88,20 +160,34 @@ PIXI.CanvasRenderer.prototype.render = function(stage)
//stage.__childrenRemoved = [];
// update textures if need be
PIXI.texturesToUpdate = [];
PIXI.texturesToDestroy = [];
PIXI.texturesToUpdate.length = 0;
PIXI.texturesToDestroy.length = 0;
PIXI.visibleCount++;
stage.updateTransform();
// update the background color
if(this.view.style.backgroundColor !== stage.backgroundColorString && !this.transparent)
this.view.style.backgroundColor = stage.backgroundColorString;
/* if(this.view.style.backgroundColor !== stage.backgroundColorString && !this.transparent)
this.view.style.backgroundColor = stage.backgroundColorString; */
this.context.setTransform(1,0,0,1,0,0);
this.context.clearRect(0, 0, this.width, this.height);
if(this.view.style.backgroundColor !== stage.backgroundColorString )
{
if(!this.transparent)
{
this.context.globalAlpha = 1;
this.context.fillStyle = stage.backgroundColorString;
this.context.fillRect(0, 0, this.width, this.height);
}
else
{
this.context.clearRect(0, 0, this.width, this.height);
}
}
//console.log(this.view.style.backgroundColor)
this.renderDisplayObject(stage);
//as
// run interaction!
if(stage.interactive)
@@ -117,12 +203,12 @@ PIXI.CanvasRenderer.prototype.render = function(stage)
// remove frame updates..
if(PIXI.Texture.frameUpdates.length > 0)
{
PIXI.Texture.frameUpdates = [];
PIXI.Texture.frameUpdates.length = 0;
}
};
/**
* resizes the canvas view to the specified width and height
* Resizes the canvas view to the specified width and height
*
* @method resize
* @param width {Number} the new width of the canvas view
@@ -142,119 +228,17 @@ PIXI.CanvasRenderer.prototype.resize = function(width, height)
*
* @method renderDisplayObject
* @param displayObject {DisplayObject} The displayObject to render
* @param context {Context2D} the context 2d method of the canvas
* @private
*/
PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject)
PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject, context)
{
// no loger recurrsive!
var transform;
var context = this.context;
// no longer recursive!
//var transform;
//var context = this.context;
context.globalCompositeOperation = 'source-over';
// one the display object hits this. we can break the loop
var testObject = displayObject.last._iNext;
displayObject = displayObject.first;
do
{
transform = displayObject.worldTransform;
if(!displayObject.visible)
{
displayObject = displayObject.last._iNext;
continue;
}
if(!displayObject.renderable)
{
displayObject = displayObject._iNext;
continue;
}
if(displayObject instanceof PIXI.Sprite)
{
var frame = displayObject.texture.frame;
//ignore null sources
if(frame && frame.width && frame.height && displayObject.texture.baseTexture.source)
{
context.globalAlpha = displayObject.worldAlpha;
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
//if smoothingEnabled is supported and we need to change the smoothing property for this texture
if(this.smoothProperty && this.scaleMode !== displayObject.texture.baseTexture.scaleMode) {
this.scaleMode = displayObject.texture.baseTexture.scaleMode;
context[this.smoothProperty] = (this.scaleMode === PIXI.BaseTexture.SCALE_MODE.LINEAR);
}
context.drawImage(displayObject.texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
(displayObject.anchor.x) * -frame.width,
(displayObject.anchor.y) * -frame.height,
frame.width,
frame.height);
}
}
else if(displayObject instanceof PIXI.Strip)
{
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
this.renderStrip(displayObject);
}
else if(displayObject instanceof PIXI.TilingSprite)
{
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
this.renderTilingSprite(displayObject);
}
else if(displayObject instanceof PIXI.CustomRenderable)
{
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
displayObject.renderCanvas(this);
}
else if(displayObject instanceof PIXI.Graphics)
{
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
PIXI.CanvasGraphics.renderGraphics(displayObject, context);
}
else if(displayObject instanceof PIXI.FilterBlock)
{
if(displayObject.data instanceof PIXI.Graphics)
{
var mask = displayObject.data;
if(displayObject.open)
{
context.save();
var cacheAlpha = mask.alpha;
var maskTransform = mask.worldTransform;
context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]);
mask.worldAlpha = 0.5;
context.worldAlpha = 0;
PIXI.CanvasGraphics.renderGraphicsMask(mask, context);
context.clip();
mask.worldAlpha = cacheAlpha;
}
else
{
context.restore();
}
}
}
//count++
displayObject = displayObject._iNext;
}
while(displayObject !== testObject);
this.renderSession.context = context || this.context;
displayObject._renderCanvas(this.renderSession);
};
/**
@@ -286,45 +270,11 @@ PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip)
context.lineTo(x2, y2);
}
context.fillStyle = '#FF0000';
context.fillStyle = "#FF0000";
context.fill();
context.closePath();
};
/**
* Renders a tiling sprite
*
* @method renderTilingSprite
* @param sprite {TilingSprite} The tilingsprite to render
* @private
*/
PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite)
{
var context = this.context;
context.globalAlpha = sprite.worldAlpha;
if(!sprite.__tilePattern)
sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, 'repeat');
context.beginPath();
var tilePosition = sprite.tilePosition;
var tileScale = sprite.tileScale;
// offset
context.scale(tileScale.x,tileScale.y);
context.translate(tilePosition.x, tilePosition.y);
context.fillStyle = sprite.__tilePattern;
context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y);
context.scale(1/tileScale.x, 1/tileScale.y);
context.translate(-tilePosition.x, -tilePosition.y);
context.closePath();
};
/**
* Renders a strip
*
@@ -380,3 +330,51 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
context.restore();
}
};
/**
* Creates a Canvas element of the given size
*
* @method CanvasBuffer
* @param width {Number} the width for the newly created canvas
* @param height {Number} the height for the newly created canvas
* @static
* @private
*/
PIXI.CanvasBuffer = function(width, height)
{
this.width = width;
this.height = height;
this.canvas = document.createElement( "canvas" );
this.context = this.canvas.getContext( "2d" );
this.canvas.width = width;
this.canvas.height = height;
};
/**
* Clears the canvas that was created by the CanvasBuffer class
*
* @method clear
* @private
*/
PIXI.CanvasBuffer.prototype.clear = function()
{
this.context.clearRect(0,0, this.width, this.height);
};
/**
* Resizes the canvas that was created by the CanvasBuffer class 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
* @private
*/
PIXI.CanvasBuffer.prototype.resize = function(width, height)
{
this.width = this.canvas.width = width;
this.height = this.canvas.height = height;
};
@@ -0,0 +1,51 @@
/**
* @author Mat Groves
*
*
*/
/**
* A set of functions used to handle masking
*
* @class CanvasMaskManager
*/
PIXI.CanvasMaskManager = function()
{
};
/**
* TODO-Alvin
*
* @method pushMask
* @param maskData TODO-Alvin
* @param context {Context2D} the 2d drawing method of the canvas
*/
PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context)
{
context.save();
//maskData.visible = false;
// maskData.alpha = 0;
var cacheAlpha = maskData.alpha;
var transform = maskData.worldTransform;
context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
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 context {Context2D} the 2d drawing method of the canvas
*/
PIXI.CanvasMaskManager.prototype.popMask = function(context)
{
context.restore();
};
@@ -0,0 +1,243 @@
/**
* @author Mat Groves
*
*
*/
/**
* @class CanvasTinter
* @constructor
* @static
*/
PIXI.CanvasTinter = function()
{
/// this.textureCach
};
//PIXI.CanvasTinter.cachTint = true;
/**
* TODO-Alvin
* @method getTintedTexture
* @param sprite {Sprite} the sprite to tint
* @param color {Number} the color to use to tint the sprite with
*/
PIXI.CanvasTinter.getTintedTexture = function(sprite, color)
{
//
// cache on sprite
// cache on texture
// no cache
var texture = sprite.texture;
color = PIXI.CanvasTinter.roundColor(color);
var stringColor = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
texture.tintCache = texture.tintCache || {};
if(texture.tintCache[stringColor]) return texture.tintCache[stringColor];
// clone texture..
var canvas = PIXI.CanvasTinter.canvas || document.createElement("canvas");
//PIXI.CanvasTinter.tintWithPerPixel(texture, stringColor, canvas);
PIXI.CanvasTinter.tintMethod(texture, color, canvas);
if(PIXI.CanvasTinter.convertTintToImage)
{
// is this better?
var tintImage = new Image();
tintImage.src = canvas.toDataURL();
texture.tintCache[stringColor] = tintImage;
}
else
{
texture.tintCache[stringColor] = canvas;
// if we are not converting the texture to an image then we need to lose the reference to the canvas
PIXI.CanvasTinter.canvas = null;
}
return canvas;
};
/**
* Tint a texture using the "multiply" operation
* @method tintWithMultiply
* @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 frame = texture.frame;
canvas.width = frame.width;
canvas.height = frame.height;
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, frame.width, frame.height);
context.globalCompositeOperation = "multiply";
context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
0,
0,
frame.width,
frame.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
0,
0,
frame.width,
frame.height);
};
/**
* Tint a texture using the "overlay" operation
* @method tintWithOverlay
* @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.tintWithOverlay = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var frame = texture.frame;
canvas.width = frame.width;
canvas.height = frame.height;
context.globalCompositeOperation = "copy";
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, frame.width, frame.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
0,
0,
frame.width,
frame.height);
//context.globalCompositeOperation = "copy";
};
/**
* Tint a texture pixel per pixel
* @method tintPerPixel
* @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 frame = texture.frame;
canvas.width = frame.width;
canvas.height = frame.height;
context.globalCompositeOperation = "copy";
context.drawImage(texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
0,
0,
frame.width,
frame.height);
var rgbValues = PIXI.hex2rgb(color);
var r = rgbValues[0], g = rgbValues[1], b = rgbValues[2];
var pixelData = context.getImageData(0, 0, frame.width, frame.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;
}
context.putImageData(pixelData, 0, 0);
};
/**
* Rounds the specified color according to the PIXI.CanvasTinter.cacheStepsPerColorChannel
* @method roundColor
* @param color {number} the color to round, should be a hex color
*/
PIXI.CanvasTinter.roundColor = function(color)
{
var step = PIXI.CanvasTinter.cacheStepsPerColorChannel;
var rgbValues = PIXI.hex2rgb(color);
rgbValues[0] = Math.min(255, (rgbValues[0] / step) * step);
rgbValues[1] = Math.min(255, (rgbValues[1] / step) * step);
rgbValues[2] = Math.min(255, (rgbValues[2] / step) * step);
return PIXI.rgb2hex(rgbValues);
};
/**
*
* Number of steps which will be used as a cap when rounding colors
*
* @property cacheStepsPerColorChannel
* @type Number
*/
PIXI.CanvasTinter.cacheStepsPerColorChannel = 8;
/**
*
* Number of steps which will be used as a cap when rounding colors
*
* @property convertTintToImage
* @type Boolean
*/
PIXI.CanvasTinter.convertTintToImage = false;
/**
* Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method
*
* @property canUseMultiply
* @type Boolean
*/
PIXI.CanvasTinter.canUseMultiply = PIXI.canUseNewCanvasBlendModes();
PIXI.CanvasTinter.tintMethod = PIXI.CanvasTinter.canUseMultiply ? PIXI.CanvasTinter.tintWithMultiply : PIXI.CanvasTinter.tintWithPerPixel;
-572
View File
@@ -1,572 +0,0 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI._batchs = [];
/**
* @private
*/
PIXI._getBatch = function(gl)
{
if(PIXI._batchs.length === 0)
{
return new PIXI.WebGLBatch(gl);
}
else
{
return PIXI._batchs.pop();
}
};
/**
* @private
*/
PIXI._returnBatch = function(batch)
{
batch.clean();
PIXI._batchs.push(batch);
};
/**
* @private
*/
PIXI._restoreBatchs = function(gl)
{
for (var i=0; i < PIXI._batchs.length; i++)
{
PIXI._batchs[i].restoreLostContext(gl);
}
};
/**
* A WebGLBatch Enables a group of sprites to be drawn using the same settings.
* if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch.
* All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites
* in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled
* automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster
* the webGL renderer will run.
*
* @class WebGLBatch
* @constructor
* @param gl {WebGLContext} an instance of the webGL context
*/
PIXI.WebGLBatch = function(gl)
{
this.gl = gl;
this.size = 0;
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.uvBuffer = gl.createBuffer();
this.colorBuffer = gl.createBuffer();
this.blendMode = PIXI.blendModes.NORMAL;
this.dynamicSize = 1;
};
// constructor
PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch;
/**
* Cleans the batch so that is can be returned to an object pool and reused
*
* @method clean
*/
PIXI.WebGLBatch.prototype.clean = function()
{
this.verticies = [];
this.uvs = [];
this.indices = [];
this.colors = [];
this.dynamicSize = 1;
this.texture = null;
this.last = null;
this.size = 0;
this.head = null;
this.tail = null;
};
/**
* Recreates the buffers in the event of a context loss
*
* @method restoreLostContext
* @param gl {WebGLContext}
*/
PIXI.WebGLBatch.prototype.restoreLostContext = function(gl)
{
this.gl = gl;
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.uvBuffer = gl.createBuffer();
this.colorBuffer = gl.createBuffer();
};
/**
* inits the batch's texture and blend mode based if the supplied sprite
*
* @method init
* @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with
* the same base texture and blend mode will be allowed to be added to this batch
*/
PIXI.WebGLBatch.prototype.init = function(sprite)
{
sprite.batch = this;
this.dirty = true;
this.blendMode = sprite.blendMode;
this.texture = sprite.texture.baseTexture;
this.head = sprite;
this.tail = sprite;
this.size = 1;
this.growBatch();
};
/**
* inserts a sprite before the specified sprite
*
* @method insertBefore
* @param sprite {Sprite} the sprite to be added
* @param nextSprite {nextSprite} the first sprite will be inserted before this sprite
*/
PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite)
{
this.size++;
sprite.batch = this;
this.dirty = true;
var tempPrev = nextSprite.__prev;
nextSprite.__prev = sprite;
sprite.__next = nextSprite;
if(tempPrev)
{
sprite.__prev = tempPrev;
tempPrev.__next = sprite;
}
else
{
this.head = sprite;
}
};
/**
* inserts a sprite after the specified sprite
*
* @method insertAfter
* @param sprite {Sprite} the sprite to be added
* @param previousSprite {Sprite} the first sprite will be inserted after this sprite
*/
PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite)
{
this.size++;
sprite.batch = this;
this.dirty = true;
var tempNext = previousSprite.__next;
previousSprite.__next = sprite;
sprite.__prev = previousSprite;
if(tempNext)
{
sprite.__next = tempNext;
tempNext.__prev = sprite;
}
else
{
this.tail = sprite;
}
};
/**
* removes a sprite from the batch
*
* @method remove
* @param sprite {Sprite} the sprite to be removed
*/
PIXI.WebGLBatch.prototype.remove = function(sprite)
{
this.size--;
if(this.size === 0)
{
sprite.batch = null;
sprite.__prev = null;
sprite.__next = null;
return;
}
if(sprite.__prev)
{
sprite.__prev.__next = sprite.__next;
}
else
{
this.head = sprite.__next;
this.head.__prev = null;
}
if(sprite.__next)
{
sprite.__next.__prev = sprite.__prev;
}
else
{
this.tail = sprite.__prev;
this.tail.__next = null;
}
sprite.batch = null;
sprite.__next = null;
sprite.__prev = null;
this.dirty = true;
};
/**
* Splits the batch into two with the specified sprite being the start of the new batch.
*
* @method split
* @param sprite {Sprite} the sprite that indicates where the batch should be split
* @return {WebGLBatch} the new batch
*/
PIXI.WebGLBatch.prototype.split = function(sprite)
{
this.dirty = true;
var batch = new PIXI.WebGLBatch(this.gl);
batch.init(sprite);
batch.texture = this.texture;
batch.tail = this.tail;
this.tail = sprite.__prev;
this.tail.__next = null;
sprite.__prev = null;
// return a splite batch!
// TODO this size is wrong!
// need to recalculate :/ problem with a linked list!
// unless it gets calculated in the "clean"?
// need to loop through items as there is no way to know the length on a linked list :/
var tempSize = 0;
while(sprite)
{
tempSize++;
sprite.batch = batch;
sprite = sprite.__next;
}
batch.size = tempSize;
this.size -= tempSize;
return batch;
};
/**
* Merges two batchs together
*
* @method merge
* @param batch {WebGLBatch} the batch that will be merged
*/
PIXI.WebGLBatch.prototype.merge = function(batch)
{
this.dirty = true;
this.tail.__next = batch.head;
batch.head.__prev = this.tail;
this.size += batch.size;
this.tail = batch.tail;
var sprite = batch.head;
while(sprite)
{
sprite.batch = this;
sprite = sprite.__next;
}
};
/**
* Grows the size of the batch. As the elements in the batch cannot have a dynamic size this
* function is used to increase the size of the batch. It also creates a little extra room so
* that the batch does not need to be resized every time a sprite is added
*
* @method growBatch
*/
PIXI.WebGLBatch.prototype.growBatch = function()
{
var gl = this.gl;
if( this.size === 1)
{
this.dynamicSize = 1;
}
else
{
this.dynamicSize = this.size * 1.5;
}
// grow verts
this.verticies = new Float32Array(this.dynamicSize * 8);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW);
this.uvs = new Float32Array( this.dynamicSize * 8 );
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW);
this.dirtyUVS = true;
this.colors = new Float32Array( this.dynamicSize * 4 );
gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW);
this.dirtyColors = true;
this.indices = new Uint16Array(this.dynamicSize * 6);
var length = this.indices.length/6;
for (var i = 0; i < length; i++)
{
var index2 = i * 6;
var index3 = i * 4;
this.indices[index2 + 0] = index3 + 0;
this.indices[index2 + 1] = index3 + 1;
this.indices[index2 + 2] = index3 + 2;
this.indices[index2 + 3] = index3 + 0;
this.indices[index2 + 4] = index3 + 2;
this.indices[index2 + 5] = index3 + 3;
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
};
/**
* Refresh's all the data in the batch and sync's it with the webGL buffers
*
* @method refresh
*/
PIXI.WebGLBatch.prototype.refresh = function()
{
if (this.dynamicSize < this.size)
{
this.growBatch();
}
var indexRun = 0;
var index, colorIndex;
var displayObject = this.head;
while(displayObject)
{
index = indexRun * 8;
var texture = displayObject.texture;
var frame = texture.frame;
var tw = texture.baseTexture.width;
var th = texture.baseTexture.height;
this.uvs[index + 0] = frame.x / tw;
this.uvs[index +1] = frame.y / th;
this.uvs[index +2] = (frame.x + frame.width) / tw;
this.uvs[index +3] = frame.y / th;
this.uvs[index +4] = (frame.x + frame.width) / tw;
this.uvs[index +5] = (frame.y + frame.height) / th;
this.uvs[index +6] = frame.x / tw;
this.uvs[index +7] = (frame.y + frame.height) / th;
displayObject.updateFrame = false;
colorIndex = indexRun * 4;
this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha;
displayObject = displayObject.__next;
indexRun++;
}
this.dirtyUVS = true;
this.dirtyColors = true;
};
/**
* Updates all the relevant geometry and uploads the data to the GPU
*
* @method update
*/
PIXI.WebGLBatch.prototype.update = function()
{
var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index;
var a, b, c, d, tx, ty;
var indexRun = 0;
var displayObject = this.head;
var verticies = this.verticies;
var uvs = this.uvs;
var colors = this.colors;
while(displayObject)
{
if(displayObject.vcount === PIXI.visibleCount)
{
width = displayObject.texture.frame.width;
height = displayObject.texture.frame.height;
// TODO trim??
aX = displayObject.anchor.x;// - displayObject.texture.trim.x
aY = displayObject.anchor.y; //- displayObject.texture.trim.y
w0 = width * (1-aX);
w1 = width * -aX;
h0 = height * (1-aY);
h1 = height * -aY;
index = indexRun * 8;
worldTransform = displayObject.worldTransform;
a = worldTransform[0];
b = worldTransform[3];
c = worldTransform[1];
d = worldTransform[4];
tx = worldTransform[2];
ty = worldTransform[5];
verticies[index + 0 ] = a * w1 + c * h1 + tx;
verticies[index + 1 ] = d * h1 + b * w1 + ty;
verticies[index + 2 ] = a * w0 + c * h1 + tx;
verticies[index + 3 ] = d * h1 + b * w0 + ty;
verticies[index + 4 ] = a * w0 + c * h0 + tx;
verticies[index + 5 ] = d * h0 + b * w0 + ty;
verticies[index + 6] = a * w1 + c * h0 + tx;
verticies[index + 7] = d * h0 + b * w1 + ty;
if(displayObject.updateFrame || displayObject.texture.updateFrame)
{
this.dirtyUVS = true;
var texture = displayObject.texture;
var frame = texture.frame;
var tw = texture.baseTexture.width;
var th = texture.baseTexture.height;
uvs[index + 0] = frame.x / tw;
uvs[index +1] = frame.y / th;
uvs[index +2] = (frame.x + frame.width) / tw;
uvs[index +3] = frame.y / th;
uvs[index +4] = (frame.x + frame.width) / tw;
uvs[index +5] = (frame.y + frame.height) / th;
uvs[index +6] = frame.x / tw;
uvs[index +7] = (frame.y + frame.height) / th;
displayObject.updateFrame = false;
}
// TODO this probably could do with some optimisation....
if(displayObject.cacheAlpha !== displayObject.worldAlpha)
{
displayObject.cacheAlpha = displayObject.worldAlpha;
var colorIndex = indexRun * 4;
colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha;
this.dirtyColors = true;
}
}
else
{
index = indexRun * 8;
verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = verticies[index + 7] = 0;
}
indexRun++;
displayObject = displayObject.__next;
}
};
/**
* Draws the batch to the frame buffer
*
* @method render
*/
PIXI.WebGLBatch.prototype.render = function(start, end)
{
start = start || 0;
if(end === undefined)
end = this.size;
if(this.dirty)
{
this.refresh();
this.dirty = false;
}
if (this.size === 0)return;
this.update();
var gl = this.gl;
//TODO optimize this!
var shaderProgram = PIXI.defaultShader;
//gl.useProgram(shaderProgram);
// update the verts..
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
// ok..
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies);
gl.vertexAttribPointer(shaderProgram.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
// update the uvs
//var isDefault = (shaderProgram == PIXI.shaderProgram)
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
if(this.dirtyUVS)
{
this.dirtyUVS = false;
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs);
}
gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture);
// update color!
gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
if(this.dirtyColors)
{
this.dirtyColors = false;
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors);
}
gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0);
// dont need to upload!
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
var len = end - start;
// DRAW THAT this!
gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 );
};
File diff suppressed because it is too large Load Diff
+365 -172
View File
@@ -2,15 +2,11 @@
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1);
// an instance of the gl context..
// only one at the moment :/
PIXI.gl = null;
PIXI.glContexts = []; // this is where we store the webGL contexts for easy access.
/**
* the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer
* should be used for browsers support webGL. This Render works by automatically managing webGLBatchs.
* 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 webGLBatch's.
* So no need for Sprite Batch's or Sprite Cloud's
* Dont forget to add the view to your DOM or you will not see anything :)
*
@@ -18,123 +14,150 @@ PIXI.gl = null;
* @constructor
* @param width=0 {Number} the width of the canvas view
* @param height=0 {Number} the height of the canvas view
* @param view {Canvas} the canvas to use as a view, optional
* @param transparent=false {Boolean} the transparency of the render view, default false
* @param view {HTMLCanvasElement} the canvas to use as a view, optional
* @param transparent=false {Boolean} If the render view is transparent, default false
* @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment)
*
*/
PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
{
// do a catch.. only 1 webGL renderer..
if(!PIXI.defaultRenderer)PIXI.defaultRenderer = this;
this.type = PIXI.WEBGL_RENDERER;
// do a catch.. only 1 webGL renderer..
/**
* Whether the render view is transparent
*
* @property transparent
* @type Boolean
*/
this.transparent = !!transparent;
/**
* The width of the canvas view
*
* @property width
* @type Number
* @default 800
*/
this.width = width || 800;
/**
* The height of the canvas view
*
* @property height
* @type Number
* @default 600
*/
this.height = height || 600;
/**
* The canvas element that everything is drawn to
*
* @property view
* @type HTMLCanvasElement
*/
this.view = view || document.createElement( 'canvas' );
this.view.width = this.width;
this.view.height = this.height;
// deal with losing context..
var scope = this;
this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false);
this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false);
// TODO-Alvin
this.contextLost = this.handleContextLost.bind(this);
this.contextRestoredLost = this.handleContextRestored.bind(this);
// console.log(this.handleContextRestored)
this.view.addEventListener('webglcontextlost', this.contextLost, false);
this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false);
this.batchs = [];
var options = {
this.options = {
alpha: this.transparent,
antialias:!!antialias, // SPEED UP??
premultipliedAlpha:false,
premultipliedAlpha:!!transparent,
stencil:true
};
//try 'experimental-webgl'
try {
PIXI.gl = this.gl = this.view.getContext('experimental-webgl', options);
this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) {
//try 'webgl'
try {
PIXI.gl = this.gl = this.view.getContext('webgl', options);
this.gl = this.view.getContext('webgl', this.options);
} catch (e2) {
// fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
}
}
PIXI.initDefaultShaders();
// PIXI.activateDefaultShader();
var gl = this.gl;
this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++;
gl.useProgram(PIXI.defaultShader.program);
PIXI.glContexts[this.glContextId] = gl;
if(!PIXI.blendModesWebGL)
{
PIXI.blendModesWebGL = [];
PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE];
PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
}
PIXI.WebGLRenderer.gl = gl;
this.batch = new PIXI.WebGLBatch(gl);
this.projection = new PIXI.Point();
this.projection.x = this.width/2;
this.projection.y = -this.height/2;
this.offset = new PIXI.Point(0, 0);
this.resize(this.width, this.height);
this.contextLost = false;
// time to create the render managers! each one focuses on managine a state in webGL
this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs
this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites
this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer
this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters
//
this.renderSession = {};
this.renderSession.gl = this.gl;
this.renderSession.drawCount = 0;
this.renderSession.shaderManager = this.shaderManager;
this.renderSession.maskManager = this.maskManager;
this.renderSession.filterManager = this.filterManager;
this.renderSession.spriteBatch = this.spriteBatch;
gl.useProgram(this.shaderManager.defaultShader.program);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.CULL_FACE);
gl.enable(gl.BLEND);
gl.colorMask(true, true, true, this.transparent);
PIXI.projection = new PIXI.Point(400, 300);
PIXI.offset = new PIXI.Point(0, 0);
// TODO remove thease globals..
this.resize(this.width, this.height);
this.contextLost = false;
//PIXI.pushShader(PIXI.defaultShader);
this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent);
// this.stageRenderGroup. = this.transparent
};
// constructor
PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer;
/**
* Gets a new WebGLBatch from the pool
*
* @static
* @method getBatch
* @return {WebGLBatch}
* @private
*/
PIXI.WebGLRenderer.getBatch = function()
{
if(PIXI._batchs.length === 0)
{
return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl);
}
else
{
return PIXI._batchs.pop();
}
};
/**
* Puts a batch back into the pool
*
* @static
* @method returnBatch
* @param batch {WebGLBatch} The batch to return
* @private
*/
PIXI.WebGLRenderer.returnBatch = function(batch)
{
batch.clean();
PIXI._batchs.push(batch);
};
/**
* Renders the stage to its webGL view
*
@@ -146,44 +169,49 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
if(this.contextLost)return;
// if rendering a new stage clear the batchs..
// if rendering a new stage clear the batches..
if(this.__stage !== stage)
{
if(stage.interactive)stage.interactionManager.removeEvents();
// TODO make this work
// dont think this is needed any more?
this.__stage = stage;
this.stageRenderGroup.setRenderable(stage);
}
// update any textures
// update any textures this includes uvs and uploading them to the gpu
PIXI.WebGLRenderer.updateTextures();
// update the scene graph
PIXI.visibleCount++;
stage.updateTransform();
var gl = this.gl;
// -- Does this need to be set every frame? -- //
gl.colorMask(true, true, true, this.transparent);
//gl.colorMask(true, true, true, this.transparent);
gl.viewport(0, 0, this.width, this.height);
// make sure we are bound to the main frame buffer
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent);
if(this.transparent)
{
gl.clearColor(0, 0, 0, 0);
}
else
{
gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1);
}
gl.clear(gl.COLOR_BUFFER_BIT);
// HACK TO TEST
// this.projection.x = this.width/2;
//this.projection.y = -this.height/2;
this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit;
PIXI.projection.x = this.width/2;
PIXI.projection.y = -this.height/2;
this.stageRenderGroup.render(PIXI.projection);
this.renderDisplayObject( stage, this.projection );
// interaction
// run interaction!
if(stage.interactive)
{
//need to add some events!
@@ -193,17 +221,65 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
stage.interactionManager.setTarget(this);
}
}
// after rendering lets confirm all frames that have been uodated..
if(PIXI.Texture.frameUpdates.length > 0)
else
{
for (var i=0; i < PIXI.Texture.frameUpdates.length; i++)
if(stage._interactiveEventsAdded)
{
PIXI.Texture.frameUpdates[i].updateFrame = false;
stage._interactiveEventsAdded = false;
stage.interactionManager.setTarget(this);
}
PIXI.Texture.frameUpdates = [];
}
/*
//can simulate context loss in Chrome like so:
this.view.onmousedown = function(ev) {
console.dir(this.gl.getSupportedExtensions());
var ext = (
gl.getExtension("WEBGL_scompressed_texture_s3tc")
// gl.getExtension("WEBGL_compressed_texture_s3tc") ||
// gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
// gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
);
console.dir(ext);
var loseCtx = this.gl.getExtension("WEBGL_lose_context");
console.log("killing context");
loseCtx.loseContext();
setTimeout(function() {
console.log("restoring context...");
loseCtx.restoreContext();
}.bind(this), 1000);
}.bind(this);
*/
};
/**
* Renders a display Object
*
* @method renderDIsplayObject
* @param displayObject {DisplayObject} The DisplayObject to render
* @param projection {Point}
* @param buffer {Array} buffer TODO-Alvin
*/
PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer)
{
// reset the render session data..
this.renderSession.drawCount = 0;
this.renderSession.currentBlendMode = 9999;
this.renderSession.projection = projection;
this.renderSession.offset = this.offset;
// start the sprite batch
this.spriteBatch.begin(this.renderSession);
// start the filter manager
this.filterManager.begin(this.renderSession, buffer);
// render the scene!
displayObject._renderWebGL(this.renderSession);
// finish the sprite batch
this.spriteBatch.end();
};
/**
@@ -218,58 +294,19 @@ PIXI.WebGLRenderer.updateTextures = function()
var i = 0;
//TODO break this out into a texture manager...
for (i = 0; i < PIXI.texturesToUpdate.length; i++)
PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]);
//for (i = 0; i < PIXI.texturesToUpdate.length; i++)
// PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]);
for (i=0; i < PIXI.Texture.frameUpdates.length; i++)
PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]);
for (i = 0; i < PIXI.texturesToDestroy.length; i++)
PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]);
PIXI.texturesToUpdate = [];
PIXI.texturesToDestroy = [];
};
/**
* Updates a loaded webgl texture
*
* @static
* @method updateTexture
* @param texture {Texture} The texture to update
* @private
*/
PIXI.WebGLRenderer.updateTexture = function(texture)
{
//TODO break this out into a texture manager...
var gl = PIXI.gl;
if(!texture._glTexture)
{
texture._glTexture = gl.createTexture();
}
if(texture.hasLoaded)
{
gl.bindTexture(gl.TEXTURE_2D, texture._glTexture);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
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.BaseTexture.SCALE_MODE.LINEAR ? gl.LINEAR : gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.BaseTexture.SCALE_MODE.LINEAR ? gl.LINEAR : gl.NEAREST);
// reguler...
if(!texture._powerOf2)
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
else
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
gl.bindTexture(gl.TEXTURE_2D, null);
}
PIXI.texturesToUpdate.length = 0;
PIXI.texturesToDestroy.length = 0;
PIXI.Texture.frameUpdates.length = 0;
};
/**
@@ -282,13 +319,35 @@ PIXI.WebGLRenderer.updateTexture = function(texture)
PIXI.WebGLRenderer.destroyTexture = function(texture)
{
//TODO break this out into a texture manager...
var gl = PIXI.gl;
if(texture._glTexture)
for (var i = texture._glTextures.length - 1; i >= 0; i--)
{
texture._glTexture = gl.createTexture();
gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture);
var glTexture = texture._glTextures[i];
var gl = PIXI.glContexts[i];
if(gl && glTexture)
{
gl.deleteTexture(glTexture);
}
}
texture._glTextures.length = 0;
};
/**
* TODO-Alvin
*
* @method updateTextureFrame
* @param texture {Texture} The texture to update the frame from
* @private
*/
PIXI.WebGLRenderer.updateTextureFrame = function(texture)
{
texture.updateFrame = false;
// now set the uvs. Figured that the uv data sits with a texture rather than a sprite.
// so uv data is stored on the texture itself
texture._updateWebGLuvs();
};
/**
@@ -308,18 +367,87 @@ PIXI.WebGLRenderer.prototype.resize = function(width, height)
this.gl.viewport(0, 0, this.width, this.height);
//var projectionMatrix = this.projectionMatrix;
this.projection.x = this.width/2;
this.projection.y = -this.height/2;
};
PIXI.projection.x = this.width/2;
PIXI.projection.y = -this.height/2;
/**
* Creates a WebGL texture
*
* @method createWebGLTexture
* @param texture {Texture} the texture to render
* @param gl {webglContext} the WebGL context
* @static
*/
PIXI.createWebGLTexture = function(texture, gl)
{
//PIXI.size.x = this.width/2;
//PIXI.size.y = -this.height/2;
// projectionMatrix[0] = 2/this.width;
// projectionMatrix[5] = -2/this.height;
// projectionMatrix[12] = -1;
// projectionMatrix[13] = 1;
if(texture.hasLoaded)
{
texture._glTextures[gl.id] = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
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);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
// reguler...
if(!texture._powerOf2)
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
else
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
gl.bindTexture(gl.TEXTURE_2D, null);
}
return texture._glTextures[gl.id];
};
/**
* Updates a WebGL texture
*
* @method updateWebGLTexture
* @param texture {Texture} the texture to update
* @param gl {webglContext} the WebGL context
* @private
*/
PIXI.updateWebGLTexture = function(texture, gl)
{
if( texture._glTextures[gl.id] )
{
gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
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);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
// reguler...
if(!texture._powerOf2)
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
else
{
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
gl.bindTexture(gl.TEXTURE_2D, null);
}
};
/**
@@ -344,26 +472,91 @@ PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
*/
PIXI.WebGLRenderer.prototype.handleContextRestored = function()
{
this.gl = this.view.getContext('experimental-webgl', {
alpha: true
});
this.initShaders();
//try 'experimental-webgl'
try {
this.gl = this.view.getContext('experimental-webgl', this.options);
} catch (e) {
//try 'webgl'
try {
this.gl = this.view.getContext('webgl', this.options);
} catch (e2) {
// fail, not able to get a context
throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
}
}
var gl = this.gl;
gl.id = PIXI.WebGLRenderer.glContextId ++;
// need to set the context...
this.shaderManager.setContext(gl);
this.spriteBatch.setContext(gl);
this.maskManager.setContext(gl);
this.filterManager.setContext(gl);
this.renderSession.gl = this.gl;
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.CULL_FACE);
gl.enable(gl.BLEND);
gl.colorMask(true, true, true, this.transparent);
this.gl.viewport(0, 0, this.width, this.height);
for(var key in PIXI.TextureCache)
{
var texture = PIXI.TextureCache[key].baseTexture;
texture._glTexture = null;
PIXI.WebGLRenderer.updateTexture(texture);
texture._glTextures = [];
}
for (var i=0; i < this.batchs.length; i++)
{
this.batchs[i].restoreLostContext(this.gl);
this.batchs[i].dirty = true;
}
PIXI._restoreBatchs(this.gl);
/**
* Whether the context was lost
* @property contextLost
* @type Boolean
*/
this.contextLost = false;
};
/**
* Destroy TODO-Alvin
*
* @method destroy
*/
PIXI.WebGLRenderer.prototype.destroy = function()
{
// deal with losing context..
// remove listeners
this.view.removeEventListener('webglcontextlost', this.contextLost);
this.view.removeEventListener('webglcontextrestored', this.contextRestoredLost);
PIXI.glContexts[this.glContextId] = null;
this.projection = null;
this.offset = null;
// time to create the render managers! each one focuses on managine a state in webGL
this.shaderManager.destroy();
this.spriteBatch.destroy();
this.maskManager.destroy();
this.filterManager.destroy();
this.shaderManager = null;
this.spriteBatch = null;
this.maskManager = null;
this.filterManager = null;
this.gl = null;
//
this.renderSession = null;
};
PIXI.WebGLRenderer.glContextId = 0;
-117
View File
@@ -1,117 +0,0 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI.initDefaultShaders = function()
{
PIXI.primitiveShader = new PIXI.PrimitiveShader();
PIXI.primitiveShader.init();
PIXI.stripShader = new PIXI.StripShader();
PIXI.stripShader.init();
PIXI.defaultShader = new PIXI.PixiShader();
PIXI.defaultShader.init();
var gl = PIXI.gl;
var shaderProgram = PIXI.defaultShader.program;
gl.useProgram(shaderProgram);
gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition);
gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute);
gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
};
PIXI.activatePrimitiveShader = function()
{
var gl = PIXI.gl;
gl.useProgram(PIXI.primitiveShader.program);
gl.disableVertexAttribArray(PIXI.defaultShader.aVertexPosition);
gl.disableVertexAttribArray(PIXI.defaultShader.colorAttribute);
gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
gl.enableVertexAttribArray(PIXI.primitiveShader.aVertexPosition);
gl.enableVertexAttribArray(PIXI.primitiveShader.colorAttribute);
};
PIXI.deactivatePrimitiveShader = function()
{
var gl = PIXI.gl;
gl.useProgram(PIXI.defaultShader.program);
gl.disableVertexAttribArray(PIXI.primitiveShader.aVertexPosition);
gl.disableVertexAttribArray(PIXI.primitiveShader.colorAttribute);
gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition);
gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute);
gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
};
PIXI.activateStripShader = function()
{
var gl = PIXI.gl;
gl.useProgram(PIXI.stripShader.program);
// gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
};
PIXI.deactivateStripShader = function()
{
var gl = PIXI.gl;
gl.useProgram(PIXI.defaultShader.program);
//gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
};
/*
SHADER COMPILER HELPERS
*/
PIXI.CompileVertexShader = function(gl, shaderSrc)
{
return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER);
};
PIXI.CompileFragmentShader = function(gl, shaderSrc)
{
return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER);
};
PIXI._CompileShader = function(gl, shaderSrc, shaderType)
{
var 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;
};
PIXI.compileProgram = function(vertexSrc, fragmentSrc)
{
var gl = PIXI.gl;
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)) {
window.console.log("Could not initialise shaders");
}
return shaderProgram;
};
@@ -0,0 +1,146 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
* @author Richard Davey http://www.photonstorm.com @photonstorm
*/
/**
* @class PIXI.PixiFastShader
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
*/
PIXI.PixiFastShader = function(gl)
{
/**
* @property gl
* @type WebGLContext
*/
this.gl = gl;
/**
* @property {any} program - The WebGL program.
*/
this.program = null;
/**
* @property {array} fragmentSrc - The fragment shader.
*/
this.fragmentSrc = [
'precision lowp float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'uniform sampler2D uSampler;',
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
'}'
];
/**
* @property {array} vertexSrc - The vertex shader
*/
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;',
'}'
];
/**
* @property {number} textureCount - A local texture counter for multi-texture shaders.
*/
this.textureCount = 0;
this.init();
};
/**
* 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;
};
@@ -7,8 +7,14 @@
* @class PIXI.PixiShader
* @constructor
*/
PIXI.PixiShader = function()
PIXI.PixiShader = function(gl)
{
/**
* @property gl
* @type WebGLContext
*/
this.gl = gl;
/**
* @property {any} program - The WebGL program.
*/
@@ -20,28 +26,36 @@ PIXI.PixiShader = function()
this.fragmentSrc = [
'precision lowp float;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'varying vec4 vColor;',
'uniform sampler2D uSampler;',
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;',
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
'}'
];
/**
* @property {number} textureCount - A local texture counter for multi-texture shaders.
*/
this.textureCount = 0;
this.attributes = [];
this.init();
};
/**
* @method PIXI.PixiShader#init
* Initialises the shader
* @method init
*
*/
PIXI.PixiShader.prototype.init = function()
{
var program = PIXI.compileProgram(this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc);
var gl = PIXI.gl;
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
@@ -52,8 +66,24 @@ PIXI.PixiShader.prototype.init = function()
// get and store the attributes
this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
this.colorAttribute = gl.getAttribLocation(program, 'aColor');
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.
// 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.aTextureCoord, this.colorAttribute];
// End worst hack eva //
// add those custom shaders!
for (var key in this.uniforms)
@@ -72,12 +102,12 @@ PIXI.PixiShader.prototype.init = function()
* 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 PIXI.PixiShader#initUniforms
* @method initUniforms
*/
PIXI.PixiShader.prototype.initUniforms = function()
{
this.textureCount = 1;
var gl = this.gl;
var uniform;
for (var key in this.uniforms)
@@ -103,21 +133,21 @@ PIXI.PixiShader.prototype.initUniforms = function()
if (type === 'mat2')
{
uniform.glFunc = PIXI.gl.uniformMatrix2fv;
uniform.glFunc = gl.uniformMatrix2fv;
}
else if (type === 'mat3')
{
uniform.glFunc = PIXI.gl.uniformMatrix3fv;
uniform.glFunc = gl.uniformMatrix3fv;
}
else if (type === 'mat4')
{
uniform.glFunc = PIXI.gl.uniformMatrix4fv;
uniform.glFunc = gl.uniformMatrix4fv;
}
}
else
{
// GL function reference
uniform.glFunc = PIXI.gl['uniform' + type];
uniform.glFunc = gl['uniform' + type];
if (type === '2f' || type === '2i')
{
@@ -141,9 +171,9 @@ PIXI.PixiShader.prototype.initUniforms = function()
};
/**
* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture is has loaded)
* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded)
*
* @method PIXI.PixiShader#initSampler2D
* @method initSampler2D
*/
PIXI.PixiShader.prototype.initSampler2D = function(uniform)
{
@@ -152,8 +182,10 @@ PIXI.PixiShader.prototype.initSampler2D = function(uniform)
return;
}
PIXI.gl.activeTexture(PIXI.gl['TEXTURE' + this.textureCount]);
PIXI.gl.bindTexture(PIXI.gl.TEXTURE_2D, uniform.value.baseTexture._glTexture);
var gl = this.gl;
gl.activeTexture(gl['TEXTURE' + this.textureCount]);
gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTexture);
// Extended texture data
if (uniform.textureData)
@@ -170,19 +202,19 @@ PIXI.PixiShader.prototype.initSampler2D = function(uniform)
// 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 : PIXI.gl.LINEAR;
var minFilter = (data.minFilter) ? data.minFilter : PIXI.gl.LINEAR;
var wrapS = (data.wrapS) ? data.wrapS : PIXI.gl.CLAMP_TO_EDGE;
var wrapT = (data.wrapT) ? data.wrapT : PIXI.gl.CLAMP_TO_EDGE;
var format = (data.luminance) ? PIXI.gl.LUMINANCE : PIXI.gl.RGBA;
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 = PIXI.gl.REPEAT;
wrapT = PIXI.gl.REPEAT;
wrapS = gl.REPEAT;
wrapT = gl.REPEAT;
}
PIXI.gl.pixelStorei(PIXI.gl.UNPACK_FLIP_Y_WEBGL, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY);
if (data.width)
{
@@ -191,21 +223,21 @@ PIXI.PixiShader.prototype.initSampler2D = function(uniform)
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);
PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, format, width, height, border, format, PIXI.gl.UNSIGNED_BYTE, null);
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);
PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, format, PIXI.gl.RGBA, PIXI.gl.UNSIGNED_BYTE, uniform.value.baseTexture.source);
gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source);
}
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MAG_FILTER, magFilter);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MIN_FILTER, minFilter);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_S, wrapS);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_T, wrapT);
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);
}
PIXI.gl.uniform1i(uniform.uniformLocation, this.textureCount);
gl.uniform1i(uniform.uniformLocation, this.textureCount);
uniform._init = true;
@@ -216,12 +248,13 @@ PIXI.PixiShader.prototype.initSampler2D = function(uniform)
/**
* Updates the shader uniform values.
*
* @method PIXI.PixiShader#syncUniforms
* @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)
@@ -233,32 +266,32 @@ PIXI.PixiShader.prototype.syncUniforms = function()
{
if (uniform.glMatrix === true)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.transpose, uniform.value);
uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value);
}
else
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value);
uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value);
}
}
else if (uniform.glValueLength === 2)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y);
uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y);
}
else if (uniform.glValueLength === 3)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z);
uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z);
}
else if (uniform.glValueLength === 4)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w);
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)
{
PIXI.gl.activeTexture(PIXI.gl['TEXTURE' + this.textureCount]);
PIXI.gl.bindTexture(PIXI.gl.TEXTURE_2D, uniform.value.baseTexture._glTexture);
PIXI.gl.uniform1i(uniform.uniformLocation, this.textureCount);
gl.activeTexture(gl['TEXTURE' + this.textureCount]);
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
@@ -270,22 +303,46 @@ PIXI.PixiShader.prototype.syncUniforms = function()
};
/**
* Destroys the shader
* @method destroy
*
*/
PIXI.PixiShader.prototype.destroy = function()
{
this.gl.deleteProgram( this.program );
this.uniforms = null;
this.gl = null;
this.attributes = null;
};
/**
*
* @property defaultVertexSrc
* @type String
*/
PIXI.PixiShader.defaultVertexSrc = [
'attribute vec2 aVertexPosition;',
'attribute vec2 aTextureCoord;',
'attribute float aColor;',
'attribute vec2 aColor;',
'uniform vec2 projectionVector;',
'uniform vec2 offsetVector;',
'varying vec2 vTextureCoord;',
'varying float vColor;',
'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 = aColor;',
' vec3 color = mod(vec3(aColor.y/65536.0, aColor.y/256.0, aColor.y), 256.0) / 256.0;',
' vColor = vec4(color * aColor.x, aColor.x);',
'}'
];
@@ -2,12 +2,28 @@
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI.PrimitiveShader = function()
/**
* @class PrimitiveShader
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
*/
PIXI.PrimitiveShader = function(gl)
{
// the webGL program..
/**
* @property gl
* @type WebGLContext
*/
this.gl = gl;
/**
* @property {any} program - The WebGL program.
*/
this.program = null;
/**
* @property fragmentSrc
* @type Array
*/
this.fragmentSrc = [
'precision mediump float;',
'varying vec4 vColor;',
@@ -17,6 +33,10 @@ PIXI.PrimitiveShader = function()
'}'
];
/**
* @property vertexSrc
* @type Array
*/
this.vertexSrc = [
'attribute vec2 aVertexPosition;',
'attribute vec4 aColor;',
@@ -24,35 +44,61 @@ PIXI.PrimitiveShader = function()
'uniform vec2 projectionVector;',
'uniform vec2 offsetVector;',
'uniform float alpha;',
'uniform vec3 tint;',
'varying vec4 vColor;',
'void main(void) {',
' vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);',
' v -= offsetVector.xyx;',
' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);',
' vColor = aColor * alpha;',
' vColor = aColor * vec4(tint * alpha, alpha);',
'}'
];
this.init();
};
/**
* Initialises the shader
* @method init
*
*/
PIXI.PrimitiveShader.prototype.init = function()
{
var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc);
var gl = PIXI.gl;
var gl = this.gl;
var program = PIXI.compileProgram(gl, this.vertexSrc, this.fragmentSrc);
gl.useProgram(program);
// get and store the uniforms for the shader
this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
this.tintColor = gl.getUniformLocation(program, 'tint');
// get and store the attributes
this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
this.colorAttribute = gl.getAttribLocation(program, 'aColor');
this.attributes = [this.aVertexPosition, this.colorAttribute];
this.translationMatrix = gl.getUniformLocation(program, 'translationMatrix');
this.alpha = gl.getUniformLocation(program, 'alpha');
this.program = program;
};
/**
* Destroys the shader
* @method destroy
*
*/
PIXI.PrimitiveShader.prototype.destroy = function()
{
this.gl.deleteProgram( this.program );
this.uniforms = null;
this.gl = null;
this.attribute = null;
};
@@ -5,9 +5,14 @@
PIXI.StripShader = function()
{
// the webGL program..
/**
* @property {any} program - The WebGL program.
*/
this.program = null;
/**
* @property {array} fragmentSrc - The fragment shader.
*/
this.fragmentSrc = [
'precision mediump float;',
'varying vec2 vTextureCoord;',
@@ -21,14 +26,17 @@ PIXI.StripShader = function()
'}'
];
/**
* @property {array} fragmentSrc - The fragment shader.
*/
this.vertexSrc = [
'attribute vec2 aVertexPosition;',
'attribute vec2 aTextureCoord;',
'attribute float aColor;',
'uniform mat3 translationMatrix;',
'uniform vec2 projectionVector;',
'uniform vec2 offsetVector;',
'varying vec2 vTextureCoord;',
'uniform vec2 offsetVector;',
'varying float vColor;',
'void main(void) {',
@@ -41,12 +49,17 @@ PIXI.StripShader = function()
];
};
/**
* Initialises the shader
* @method init
*
*/
PIXI.StripShader.prototype.init = function()
{
var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc);
var gl = PIXI.gl;
var program = PIXI.compileProgram(gl, this.vertexSrc, this.fragmentSrc);
gl.useProgram(program);
// get and store the uniforms for the shader
@@ -0,0 +1,84 @@
/**
* @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
* @private
*/
PIXI.FilterTexture = function(gl, width, height)
{
/**
* @property gl
* @type WebGLContext
*/
this.gl = gl;
// next time to create a frame buffer and texture
this.frameBuffer = gl.createFramebuffer();
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);
this.resize(width, height);
};
/**
* 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);
};
/**
* 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;
};
@@ -0,0 +1,351 @@
/**
* @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
*/
PIXI.WebGLFastSpriteBatch = function(gl)
{
this.vertSize = 10;
this.maxSize = 6000;//Math.pow(2, 16) / this.vertSize;
this.size = this.maxSize;
// console.log(this.size);
//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
this.vertices = new Float32Array(numVerts);
//index data
this.indices = new Uint16Array(numIndices);
this.vertexBuffer = null;
this.indexBuffer = null;
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;
}
this.drawing = false;
this.currentBatchSize = 0;
this.currentBaseTexture = null;
this.currentBlendMode = 0;
this.renderSession = null;
this.shader = null;
this.matrix = null;
this.setContext(gl);
};
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);
this.currentBlendMode = 99999;
};
PIXI.WebGLFastSpriteBatch.prototype.begin = function(spriteBatch, renderSession)
{
this.renderSession = renderSession;
this.shader = this.renderSession.shaderManager.fastShader;
this.matrix = spriteBatch.worldTransform.toArray(true);
// console.log(this.tempMatrix)
this.start();
};
PIXI.WebGLFastSpriteBatch.prototype.end = function()
{
this.flush();
};
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.currentBlendMode)
{
this.setBlendMode(sprite.blendMode);
}
for(var i=0,j= children.length; i<j; i++)
{
this.renderSprite(children[i]);
}
this.flush();
};
PIXI.WebGLFastSpriteBatch.prototype.renderSprite = function(sprite)
{
//sprite = children[i];
// TODO trim??
if(sprite.texture.baseTexture !== this.currentBaseTexture)
{
this.currentBaseTexture = sprite.texture.baseTexture;
this.flush();
if(!sprite.texture._uvs)return;
}
var uvs, verticies = this.vertices, width, height, w0, w1, h0, h1, index;
uvs = sprite.texture._uvs;
width = sprite.texture.frame.width;
height = sprite.texture.frame.height;
if (sprite.texture.trimmed)
{
// 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.realWidth;
w0 = w1 + sprite.texture.frame.width;
h1 = trim.y - sprite.anchor.y * trim.realHeight;
h0 = h1 + sprite.texture.frame.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
verticies[index++] = w1;
verticies[index++] = h1;
verticies[index++] = sprite.position.x;
verticies[index++] = sprite.position.y;
//scale
verticies[index++] = sprite.scale.x;
verticies[index++] = sprite.scale.y;
//rotation
verticies[index++] = sprite.rotation;
// uv
verticies[index++] = uvs.x0;
verticies[index++] = uvs.y1;
// color
verticies[index++] = sprite.alpha;
// xy
verticies[index++] = w0;
verticies[index++] = h1;
verticies[index++] = sprite.position.x;
verticies[index++] = sprite.position.y;
//scale
verticies[index++] = sprite.scale.x;
verticies[index++] = sprite.scale.y;
//rotation
verticies[index++] = sprite.rotation;
// uv
verticies[index++] = uvs.x1;
verticies[index++] = uvs.y1;
// color
verticies[index++] = sprite.alpha;
// xy
verticies[index++] = w0;
verticies[index++] = h0;
verticies[index++] = sprite.position.x;
verticies[index++] = sprite.position.y;
//scale
verticies[index++] = sprite.scale.x;
verticies[index++] = sprite.scale.y;
//rotation
verticies[index++] = sprite.rotation;
// uv
verticies[index++] = uvs.x2;
verticies[index++] = uvs.y2;
// color
verticies[index++] = sprite.alpha;
// xy
verticies[index++] = w1;
verticies[index++] = h0;
verticies[index++] = sprite.position.x;
verticies[index++] = sprite.position.y;
//scale
verticies[index++] = sprite.scale.x;
verticies[index++] = sprite.scale.y;
//rotation
verticies[index++] = sprite.rotation;
// uv
verticies[index++] = uvs.x3;
verticies[index++] = uvs.y3;
// color
verticies[index++] = sprite.alpha;
// increment the batchs
this.currentBatchSize++;
if(this.currentBatchSize >= this.size)
{
this.flush();
}
};
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])PIXI.createWebGLTexture(this.currentBaseTexture, gl);
gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id]);// || PIXI.createWebGLTexture(this.currentBaseTexture, gl));
// 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++;
};
PIXI.WebGLFastSpriteBatch.prototype.stop = function()
{
this.flush();
};
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);
// set the blend mode..
if(this.currentBlendMode !== PIXI.blendModes.NORMAL)
{
this.setBlendMode(PIXI.blendModes.NORMAL);
}
};
PIXI.WebGLFastSpriteBatch.prototype.setBlendMode = function(blendMode)
{
this.flush();
this.currentBlendMode = blendMode;
var blendModeWebGL = PIXI.blendModesWebGL[this.currentBlendMode];
this.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
};
@@ -2,32 +2,69 @@
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI.WebGLFilterManager = function(transparent)
/**
* @class WebGLFilterManager
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
* @param transparent {Boolean} Whether or not the drawing context should be transparent
* @private
*/
PIXI.WebGLFilterManager = function(gl, transparent)
{
this.transparent = transparent;
this.filterStack = [];
this.texturePool = [];
this.offsetX = 0;
this.offsetY = 0;
this.setContext(gl);
};
// API
/**
* 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();
};
// API
PIXI.WebGLFilterManager.prototype.begin = function(projection, buffer)
/**
*
* @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} TODO-Alvin
*/
PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
{
var gl = PIXI.gl;
var gl = this.gl;
var projection = this.renderSession.projection;
var offset = this.renderSession.offset;
// filter program
// OPTIMISATION - the first filter is free if its a simple color change?
@@ -41,7 +78,7 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
var texture = this.texturePool.pop();
if(!texture)
{
texture = new PIXI.FilterTexture(this.width, this.height);
texture = new PIXI.FilterTexture(this.gl, this.width, this.height);
}
else
{
@@ -50,7 +87,13 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
gl.bindTexture(gl.TEXTURE_2D, texture.texture);
this.getBounds(filterBlock.target);
// this.getBounds(filterBlock.target);
filterBlock.target.filterArea = filterBlock.target.getBounds();
// console.log(filterBlock.target.filterArea)
// console.log(filterBlock.target.filterArea);
// addpadding?
//displayObject.filterArea.x
var filterArea = filterBlock.target.filterArea;
@@ -69,34 +112,45 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
//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);
//console.log(filterArea)
// set view port
gl.viewport(0, 0, filterArea.width, filterArea.height);
PIXI.projection.x = filterArea.width/2;
PIXI.projection.y = -filterArea.height/2;
projection.x = filterArea.width/2;
projection.y = -filterArea.height/2;
PIXI.offset.x = -filterArea.x;
PIXI.offset.y = -filterArea.y;
offset.x = -filterArea.x;
offset.y = -filterArea.y;
//console.log(PIXI.defaultShader.projectionVector)
// update projection
gl.uniform2f(PIXI.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2);
gl.uniform2f(PIXI.defaultShader.offsetVector, -filterArea.x, -filterArea.y);
gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2);
gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y);
//PIXI.primitiveProgram
gl.colorMask(true, true, true, true);
gl.clearColor(0,0,0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
//filter.texture = texture;
filterBlock._glFilterTexture = texture;
//console.log("PUSH")
};
/**
* Removes the last filter from the filter stack and doesn't return it
* @method popFilter
*/
PIXI.WebGLFilterManager.prototype.popFilter = function()
{
var gl = PIXI.gl;
var gl = this.gl;
var filterBlock = this.filterStack.pop();
var filterArea = filterBlock.target.filterArea;
var texture = filterBlock._glFilterTexture;
var projection = this.renderSession.projection;
var offset = this.renderSession.offset;
if(filterBlock.filterPasses.length > 1)
{
@@ -119,7 +173,7 @@ PIXI.WebGLFilterManager.prototype.popFilter = function()
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
// nnow set the uvs..
// 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;
@@ -129,9 +183,9 @@ PIXI.WebGLFilterManager.prototype.popFilter = function()
var inputTexture = texture;
var outputTexture = this.texturePool.pop();
if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.width, this.height);
if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height);
// need to clear this FBO as it may have some left over elements from a prvious filter.
// 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);
@@ -199,11 +253,11 @@ PIXI.WebGLFilterManager.prototype.popFilter = function()
// TODO need toremove thease global elements..
PIXI.projection.x = sizeX/2;
PIXI.projection.y = -sizeY/2;
projection.x = sizeX/2;
projection.y = -sizeY/2;
PIXI.offset.x = offsetX;
PIXI.offset.y = offsetY;
offset.x = offsetX;
offset.y = offsetY;
filterArea = filterBlock.target.filterArea;
@@ -241,6 +295,9 @@ PIXI.WebGLFilterManager.prototype.popFilter = function()
// 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);
@@ -250,30 +307,39 @@ PIXI.WebGLFilterManager.prototype.popFilter = function()
this.applyFilterPass(filter, filterArea, sizeX, sizeY);
// now restore the regular shader..
gl.useProgram(PIXI.defaultShader.program);
gl.uniform2f(PIXI.defaultShader.projectionVector, sizeX/2, -sizeY/2);
gl.uniform2f(PIXI.defaultShader.offsetVector, -offsetX, -offsetY);
gl.useProgram(this.defaultShader.program);
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 = PIXI.gl;
var shader = filter.shader;
var gl = this.gl;
var shader = filter.shaders[gl.id];
if(!shader)
{
shader = new PIXI.PixiShader();
shader = new PIXI.PixiShader(gl);
shader.fragmentSrc = filter.fragmentSrc;
shader.uniforms = filter.uniforms;
shader.init();
filter.shader = shader;
filter.shaders[gl.id] = shader;
}
// set the shader
@@ -284,10 +350,12 @@ PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea,
if(filter.uniforms.dimensions)
{
//console.log(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;
// console.log(this.vertexArray[5])
}
shader.syncUniforms();
@@ -298,23 +366,34 @@ PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea,
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 = PIXI.gl;
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 refferance to the vertexFloatData..
// keep a reference to the vertexFloatData..
this.vertexArray = new Float32Array([0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
@@ -339,6 +418,17 @@ PIXI.WebGLFilterManager.prototype.initShaderBuffers = function()
this.uvArray,
gl.STATIC_DRAW);
this.colorArray = new 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(
@@ -347,150 +437,29 @@ PIXI.WebGLFilterManager.prototype.initShaderBuffers = function()
gl.STATIC_DRAW);
};
PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject)
/**
* TODO-Alvin
* @method destroy
*/
PIXI.WebGLFilterManager.prototype.destroy = function()
{
// time to get the width and height of the object!
var worldTransform, width, height, aX, aY, w0, w1, h0, h1, doTest;
var a, b, c, d, tx, ty, x1, x2, x3, x4, y1, y2, y3, y4;
var gl = this.gl;
var tempObject = displayObject.first;
var testObject = displayObject.last._iNext;
var maxX = -Infinity;
var maxY = -Infinity;
var minX = Infinity;
var minY = Infinity;
do
{
// TODO can be optimized! - what if there is no scale / rotation?
if(tempObject.visible)
{
if(tempObject instanceof PIXI.Sprite)
{
width = tempObject.texture.frame.width;
height = tempObject.texture.frame.height;
// TODO trim??
aX = tempObject.anchor.x;
aY = tempObject.anchor.y;
w0 = width * (1-aX);
w1 = width * -aX;
h0 = height * (1-aY);
h1 = height * -aY;
doTest = true;
}
else if(tempObject instanceof PIXI.Graphics)
{
tempObject.updateFilterBounds();
var bounds = tempObject.bounds;
width = bounds.width;
height = bounds.height;
w0 = bounds.x;
w1 = bounds.x + bounds.width;
h0 = bounds.y;
h1 = bounds.y + bounds.height;
doTest = true;
}
}
if(doTest)
{
worldTransform = tempObject.worldTransform;
a = worldTransform[0];
b = worldTransform[3];
c = worldTransform[1];
d = worldTransform[4];
tx = worldTransform[2];
ty = worldTransform[5];
x1 = a * w1 + c * h1 + tx;
y1 = d * h1 + b * w1 + ty;
x2 = a * w0 + c * h1 + tx;
y2 = d * h1 + b * w0 + ty;
x3 = a * w0 + c * h0 + tx;
y3 = d * h0 + b * w0 + ty;
x4 = a * w1 + c * h0 + tx;
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;
}
doTest = false;
tempObject = tempObject._iNext;
this.filterStack = null;
this.offsetX = 0;
this.offsetY = 0;
// destroy textures
for (var i = 0; i < this.texturePool.length; i++) {
this.texturePool.destroy();
}
while(tempObject !== testObject);
this.texturePool = null;
displayObject.filterArea.x = minX;
displayObject.filterArea.y = minY;
displayObject.filterArea.width = maxX - minX;
displayObject.filterArea.height = maxY - minY;
};
PIXI.FilterTexture = function(width, height)
{
var gl = PIXI.gl;
// next time to create a frame buffer and texture
this.frameBuffer = gl.createFramebuffer();
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);
this.resize(width, height);
};
PIXI.FilterTexture.prototype.resize = function(width, height)
{
if(this.width === width && this.height === height) return;
this.width = width;
this.height = height;
var gl = PIXI.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);
};
//destroy buffers..
gl.deleteBuffer(this.vertexBuffer);
gl.deleteBuffer(this.uvBuffer);
gl.deleteBuffer(this.colorBuffer);
gl.deleteBuffer(this.indexBuffer);
};
@@ -5,7 +5,9 @@
/**
* A set of functions used by the webGL renderer to draw the primitive graphics data
*
* @class CanvasGraphics
* @class WebGLGraphics
* @private
* @static
*/
PIXI.WebGLGraphics = function()
{
@@ -19,16 +21,21 @@ PIXI.WebGLGraphics = function()
* @private
* @method renderGraphics
* @param graphics {Graphics}
* @param projection {Object}
* @param renderSession {Object}
*/
PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
PIXI.WebGLGraphics.renderGraphics = function(graphics, renderSession)//projection, offset)
{
var gl = PIXI.gl;
var gl = renderSession.gl;
var projection = renderSession.projection,
offset = renderSession.offset,
shader = renderSession.shaderManager.primitiveShader;
if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0,
if(!graphics._webGL[gl.id])graphics._webGL[gl.id] = {points:[], indices:[], lastIndex:0,
buffer:gl.createBuffer(),
indexBuffer:gl.createBuffer()};
var webGL = graphics._webGL[gl.id];
if(graphics.dirty)
{
graphics.dirty = false;
@@ -37,43 +44,41 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
{
graphics.clearDirty = false;
graphics._webGL.lastIndex = 0;
graphics._webGL.points = [];
graphics._webGL.indices = [];
webGL.lastIndex = 0;
webGL.points = [];
webGL.indices = [];
}
PIXI.WebGLGraphics.updateGraphics(graphics);
PIXI.WebGLGraphics.updateGraphics(graphics, gl);
}
PIXI.activatePrimitiveShader();
renderSession.shaderManager.activatePrimitiveShader();
// This could be speeded up fo sure!
var m = PIXI.mat3.clone(graphics.worldTransform);
// This could be speeded up for sure!
PIXI.mat3.transpose(m);
// set the matrix transform for the
// set the matrix transform
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.uniformMatrix3fv(PIXI.primitiveShader.translationMatrix, false, m);
gl.uniformMatrix3fv(shader.translationMatrix, false, graphics.worldTransform.toArray(true));
gl.uniform2f(PIXI.primitiveShader.projectionVector, projection.x, -projection.y);
gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y);
gl.uniform2f(shader.projectionVector, projection.x, -projection.y);
gl.uniform2f(shader.offsetVector, -offset.x, -offset.y);
gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha);
gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer);
gl.uniform3fv(shader.tintColor, PIXI.hex2rgb(graphics.tint));
gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4);
gl.uniform1f(shader.alpha, graphics.worldAlpha);
gl.bindBuffer(gl.ARRAY_BUFFER, webGL.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, graphics._webGL.indexBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGL.indexBuffer);
gl.drawElements(gl.TRIANGLE_STRIP, webGL.indices.length, gl.UNSIGNED_SHORT, 0 );
gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 );
PIXI.deactivatePrimitiveShader();
renderSession.shaderManager.deactivatePrimitiveShader();
// return to default shader...
// PIXI.activateShader(PIXI.defaultShader);
@@ -85,11 +90,14 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
* @static
* @private
* @method updateGraphics
* @param graphics {Graphics}
* @param graphicsData {Graphics} The graphics object to update
* @param gl {WebGLContext} the current WebGL drawing context
*/
PIXI.WebGLGraphics.updateGraphics = function(graphics)
PIXI.WebGLGraphics.updateGraphics = function(graphics, gl)
{
for (var i = graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++)
var webGL = graphics._webGL[gl.id];
for (var i = webGL.lastIndex; i < graphics.graphicsData.length; i++)
{
var data = graphics.graphicsData[i];
@@ -98,37 +106,37 @@ PIXI.WebGLGraphics.updateGraphics = function(graphics)
if(data.fill)
{
if(data.points.length>3)
PIXI.WebGLGraphics.buildPoly(data, graphics._webGL);
PIXI.WebGLGraphics.buildPoly(data, webGL);
}
if(data.lineWidth > 0)
{
PIXI.WebGLGraphics.buildLine(data, graphics._webGL);
PIXI.WebGLGraphics.buildLine(data, webGL);
}
}
else if(data.type === PIXI.Graphics.RECT)
{
PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL);
PIXI.WebGLGraphics.buildRectangle(data, webGL);
}
else if(data.type === PIXI.Graphics.CIRC || data.type === PIXI.Graphics.ELIP)
{
PIXI.WebGLGraphics.buildCircle(data, graphics._webGL);
PIXI.WebGLGraphics.buildCircle(data, webGL);
}
}
graphics._webGL.lastIndex = graphics.graphicsData.length;
webGL.lastIndex = graphics.graphicsData.length;
var gl = PIXI.gl;
graphics._webGL.glPoints = new Float32Array(graphics._webGL.points);
webGL.glPoints = new Float32Array(webGL.points);
gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer);
gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, webGL.buffer);
gl.bufferData(gl.ARRAY_BUFFER, webGL.glPoints, gl.STATIC_DRAW);
graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices);
webGL.glIndicies = new Uint16Array(webGL.indices);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGL.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, webGL.glIndicies, gl.STATIC_DRAW);
};
/**
@@ -137,7 +145,7 @@ PIXI.WebGLGraphics.updateGraphics = function(graphics)
* @static
* @private
* @method buildRectangle
* @param graphics {Graphics}
* @param graphicsData {Graphics} The graphics object to draw TODO-Alvin
* @param webGLData {Object}
*/
PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
@@ -185,13 +193,18 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
if(graphicsData.lineWidth)
{
var tempPoints = graphicsData.points;
graphicsData.points = [x, y,
x + width, y,
x + width, y + height,
x, y + height,
x, y];
PIXI.WebGLGraphics.buildLine(graphicsData, webGLData);
graphicsData.points = tempPoints;
}
};
@@ -201,7 +214,7 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
* @static
* @private
* @method buildCircle
* @param graphics {Graphics}
* @param graphicsData {Graphics} The graphics object to draw
* @param webGLData {Object}
*/
PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
@@ -252,6 +265,8 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
if(graphicsData.lineWidth)
{
var tempPoints = graphicsData.points;
graphicsData.points = [];
for (i = 0; i < totalSegs + 1; i++)
@@ -261,6 +276,8 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
}
PIXI.WebGLGraphics.buildLine(graphicsData, webGLData);
graphicsData.points = tempPoints;
}
};
@@ -270,7 +287,7 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
* @static
* @private
* @method buildLine
* @param graphics {Graphics}
* @param graphicsData {Graphics} The graphics object to draw TODO-Alvin
* @param webGLData {Object}
*/
PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
@@ -293,7 +310,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
var firstPoint = new PIXI.Point( points[0], points[1] );
var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] );
// if the first point is the last point - goona have issues :)
// if the first point is the last point - gonna have issues :)
if(firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y)
{
points.pop();
@@ -480,7 +497,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
* @static
* @private
* @method buildPoly
* @param graphics {Graphics}
* @param graphicsData {Graphics} The graphics object to draw TODO-Alvin
* @param webGLData {Object}
*/
PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData)
@@ -0,0 +1,97 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* @class WebGLMaskManager
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
* @private
*/
PIXI.WebGLMaskManager = function(gl)
{
this.maskStack = [];
this.maskPosition = 0;
this.setContext(gl);
};
/**
* 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 {RenderSession}
*/
PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession)
{
var gl = this.gl;
if(this.maskStack.length === 0)
{
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.ALWAYS,1,1);
}
// maskData.visible = false;
this.maskStack.push(maskData);
gl.colorMask(false, false, false, true);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
PIXI.WebGLGraphics.renderGraphics(maskData, renderSession);
gl.colorMask(true, true, true, true);
gl.stencilFunc(gl.NOTEQUAL,0, this.maskStack.length);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
};
/**
* Removes the last filter from the filter stack and doesn't return it
* @method popMask
*
* @param renderSession {RenderSession} TODO-Alvin
*/
PIXI.WebGLMaskManager.prototype.popMask = function(renderSession)
{
var gl = this.gl;
var maskData = this.maskStack.pop();
if(maskData)
{
gl.colorMask(false, false, false, false);
//gl.stencilFunc(gl.ALWAYS,1,1);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
PIXI.WebGLGraphics.renderGraphics(maskData, renderSession);
gl.colorMask(true, true, true, true);
gl.stencilFunc(gl.NOTEQUAL,0,this.maskStack.length);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
}
if(this.maskStack.length === 0)gl.disable(gl.STENCIL_TEST);
};
/**
* TODO-Alvin
* @method destroy
*/
PIXI.WebGLMaskManager.prototype.destroy = function()
{
this.maskStack = null;
this.gl = null;
};
@@ -0,0 +1,161 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* @class WebGLShaderManager
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
* @private
*/
PIXI.WebGLShaderManager = function(gl)
{
this.maxAttibs = 10;
this.attribState = [];
this.tempAttribState = [];
for (var i = 0; i < this.maxAttibs; i++) {
this.attribState[i] = false;
}
this.setContext(gl);
// the final one is used for the rendering strips
//this.stripShader = new PIXI.StripShader(gl);
};
/**
* Initialises the context and the properties
* @method setContext
* @param gl {WebGLContext} the current WebGL drawing context
* @param transparent {Boolean} Whether or not the drawing context should be transparent
*/
PIXI.WebGLShaderManager.prototype.setContext = function(gl)
{
this.gl = gl;
// the next one is used for rendering primatives
this.primitiveShader = new PIXI.PrimitiveShader(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);
this.activateShader(this.defaultShader);
};
/**
* Initialises the context and the properties
* @method setAttribs
* @param attribs {Array} TODO-Alvin
*/
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);
}
}
}
// console.log(this.tempAttribState)
};
/**
* TODO-Alvin
* @method activateShader
* @param shader {Object} the shader that is going to be activated
*/
PIXI.WebGLShaderManager.prototype.activateShader = function(shader)
{
//if(this.currentShader == shader)return;
this.currentShader = shader;
// console.log(shader.program)
this.gl.useProgram(shader.program);
this.setAttribs(shader.attributes);
// console.log(shader.attributes)
};
/**
* Triggers the primitive shader
* @method activatePrimitiveShader
*/
PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function()
{
var gl = this.gl;
gl.useProgram(this.primitiveShader.program);
this.setAttribs(this.primitiveShader.attributes);
};
/**
* Disable the primitive shader
* @method deactivatePrimitiveShader
*/
PIXI.WebGLShaderManager.prototype.deactivatePrimitiveShader = function()
{
var gl = this.gl;
gl.useProgram(this.defaultShader.program);
this.setAttribs(this.defaultShader.attributes);
};
/**
* Destroys
* @method destroy
*/
PIXI.WebGLShaderManager.prototype.destroy = function()
{
this.attribState = null;
this.tempAttribState = null;
this.primitiveShader.destroy();
this.defaultShader.destroy();
this.fastShader.destroy();
this.gl = null;
};
@@ -0,0 +1,55 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
PIXI.initDefaultShaders = function()
{
// PIXI.stripShader = new PIXI.StripShader();
// PIXI.stripShader.init();
};
PIXI.CompileVertexShader = function(gl, shaderSrc)
{
return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER);
};
PIXI.CompileFragmentShader = function(gl, shaderSrc)
{
return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER);
};
PIXI._CompileShader = function(gl, shaderSrc, shaderType)
{
var 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;
};
PIXI.compileProgram = function(gl, vertexSrc, fragmentSrc)
{
//var gl = PIXI.gl;
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)) {
window.console.log("Could not initialise shaders");
}
return shaderProgram;
};
@@ -0,0 +1,496 @@
/**
* @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 WebGLSpriteBatch
* @private
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
*
*/
PIXI.WebGLSpriteBatch = function(gl)
{
/**
* TODO-Alvin
*
* @property vertSize
* @type Number
*/
this.vertSize = 6;
/**
* TODO-Alvin
* @property size
* @type Number
*/
this.size = 10000;//Math.pow(2, 16) / this.vertSize;
// console.log(this.size);
//the total number of floats in our batch
var numVerts = this.size * 4 * this.vertSize;
//the total number of indices in our batch
var numIndices = this.size * 6;
//vertex data
/**
* Holds the vertices
*
* @property vertices
* @type Float32Array
*/
this.vertices = new Float32Array(numVerts);
//index data
/**
* Holds the indices
*
* @property indices
* @type Uint16Array
*/
this.indices = new Uint16Array(numIndices);
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;
}
this.drawing = false;
this.currentBatchSize = 0;
this.currentBaseTexture = null;
this.setContext(gl);
};
/**
*
* @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;
};
/**
*
* @method begin
*
* @param renderSession {RenderSession} the RenderSession
*/
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 TODO-Alvin
*/
PIXI.WebGLSpriteBatch.prototype.render = function(sprite)
{
// check texture..
if(sprite.texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size)
{
this.flush();
this.currentBaseTexture = sprite.texture.baseTexture;
}
// check blend mode
if(sprite.blendMode !== this.currentBlendMode)
{
this.setBlendMode(sprite.blendMode);
}
// get the uvs for the texture
var uvs = sprite._uvs || sprite.texture._uvs;
// if the uvs have not updated then no point rendering just yet!
if(!uvs)return;
// get the sprites current alpha
var alpha = sprite.worldAlpha;
var tint = sprite.tint;
var verticies = this.vertices;
var width = sprite.texture.frame.width;
var height = sprite.texture.frame.height;
// TODO trim??
var aX = sprite.anchor.x;
var aY = sprite.anchor.y;
var w0, w1, h0, h1;
if (sprite.texture.trimmed)
{
// 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 - aX * trim.realWidth;
w0 = w1 + width;
h1 = trim.y - aY * trim.realHeight;
h0 = h1 + height;
}
else
{
w0 = (width ) * (1-aX);
w1 = (width ) * -aX;
h0 = height * (1-aY);
h1 = height * -aY;
}
var index = this.currentBatchSize * 4 * this.vertSize;
var worldTransform = sprite.worldTransform;//.toArray();
var a = worldTransform.a;//[0];
var b = worldTransform.c;//[3];
var c = worldTransform.b;//[1];
var d = worldTransform.d;//[4];
var tx = worldTransform.tx;//[2];
var ty = worldTransform.ty;///[5];
// xy
verticies[index++] = a * w1 + c * h1 + tx;
verticies[index++] = d * h1 + b * w1 + ty;
// uv
verticies[index++] = uvs.x0;
verticies[index++] = uvs.y0;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w0 + c * h1 + tx;
verticies[index++] = d * h1 + b * w0 + ty;
// uv
verticies[index++] = uvs.x1;
verticies[index++] = uvs.y1;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w0 + c * h0 + tx;
verticies[index++] = d * h0 + b * w0 + ty;
// uv
verticies[index++] = uvs.x2;
verticies[index++] = uvs.y2;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w1 + c * h0 + tx;
verticies[index++] = d * h0 + b * w1 + ty;
// uv
verticies[index++] = uvs.x3;
verticies[index++] = uvs.y3;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// increment the batchsize
this.currentBatchSize++;
};
/**
*
* @method renderTilingSprite
*
* @param sprite {TilingSprite} the sprite to render TODO-Alvin
*/
PIXI.WebGLSpriteBatch.prototype.renderTilingSprite = function(tilingSprite)
{
var texture = tilingSprite.tilingTexture;
if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size)
{
this.flush();
this.currentBaseTexture = texture.baseTexture;
}
// check blend mode
if(tilingSprite.blendMode !== this.currentBlendMode)
{
this.setBlendMode(tilingSprite.blendMode);
}
// set the textures uvs temporarily
// TODO create a separate texture so that we can tile part of a texture
if(!tilingSprite._uvs)tilingSprite._uvs = new Float32Array(8);
var uvs = tilingSprite._uvs;
tilingSprite.tilePosition.x %= texture.baseTexture.width;
tilingSprite.tilePosition.y %= texture.baseTexture.height;
var offsetX = tilingSprite.tilePosition.x/texture.baseTexture.width;
var offsetY = tilingSprite.tilePosition.y/texture.baseTexture.height;
var scaleX = (tilingSprite.width / texture.baseTexture.width) / (tilingSprite.tileScale.x * tilingSprite.tileScaleOffset.x);
var scaleY = (tilingSprite.height / texture.baseTexture.height) / (tilingSprite.tileScale.y * tilingSprite.tileScaleOffset.y);
uvs.x0 = 0 - offsetX;
uvs.y0 = 0 - offsetY;
uvs.x1 = (1 * scaleX) - offsetX;
uvs.y1 = 0 - offsetY;
uvs.x2 = (1 * scaleX) - offsetX;
uvs.y2 = (1 * scaleY) - offsetY;
uvs.x3 = 0 - offsetX;
uvs.y3 = (1 *scaleY) - offsetY;
// get the tilingSprites current alpha
var alpha = tilingSprite.worldAlpha;
var tint = tilingSprite.tint;
var verticies = this.vertices;
var width = tilingSprite.width;
var height = tilingSprite.height;
// TODO trim??
var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x
var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y
var w0 = width * (1-aX);
var w1 = width * -aX;
var h0 = height * (1-aY);
var h1 = height * -aY;
var index = this.currentBatchSize * 4 * this.vertSize;
var worldTransform = tilingSprite.worldTransform;
var a = worldTransform.a;//[0];
var b = worldTransform.c;//[3];
var c = worldTransform.b;//[1];
var d = worldTransform.d;//[4];
var tx = worldTransform.tx;//[2];
var ty = worldTransform.ty;///[5];
// xy
verticies[index++] = a * w1 + c * h1 + tx;
verticies[index++] = d * h1 + b * w1 + ty;
// uv
verticies[index++] = uvs.x0;
verticies[index++] = uvs.y0;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w0 + c * h1 + tx;
verticies[index++] = d * h1 + b * w0 + ty;
// uv
verticies[index++] = uvs.x1;
verticies[index++] = uvs.y1;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w0 + c * h0 + tx;
verticies[index++] = d * h0 + b * w0 + ty;
// uv
verticies[index++] = uvs.x2;
verticies[index++] = uvs.y2;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// xy
verticies[index++] = a * w1 + c * h0 + tx;
verticies[index++] = d * h0 + b * w1 + ty;
// uv
verticies[index++] = uvs.x3;
verticies[index++] = uvs.y3;
// color
verticies[index++] = alpha;
verticies[index++] = tint;
// increment the batchs
this.currentBatchSize++;
};
/**
*
*
* @method flush TODO-Alvin
*
*/
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;
// bind the current texture
gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl));
// 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);
}
// 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.WebGLSpriteBatch.prototype.stop = function()
{
this.flush();
};
/**
*
* @method start
*
*/
PIXI.WebGLSpriteBatch.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 pointers
var stride = this.vertSize * 4;
gl.vertexAttribPointer(this.shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
gl.vertexAttribPointer(this.shader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4);
gl.vertexAttribPointer(this.shader.colorAttribute, 2, gl.FLOAT, false, stride, 4 * 4);
// set the blend mode..
if(this.currentBlendMode !== PIXI.blendModes.NORMAL)
{
this.setBlendMode(PIXI.blendModes.NORMAL);
}
};
/**
*
* @method setBlendMode
*
* @param blendMode {Number} the blendMode, should be a Pixi const, such as PIXI.BlendModes.ADD
* TODO-Alvin
*/
PIXI.WebGLSpriteBatch.prototype.setBlendMode = function(blendMode)
{
this.flush();
this.currentBlendMode = blendMode;
var blendModeWebGL = PIXI.blendModesWebGL[this.currentBlendMode];
this.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
};
/**
* 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;
};
+34 -17
View File
@@ -9,16 +9,18 @@
* http://www.bmglyph.com/ for mac.
*
* @class BitmapText
* @extends DisplayObjectContainer
* @extends SpriteBatch
* @constructor
* @param text {String} The copy that you would like the text to display
* @param style {Object} The style parameters
* @param style.font {String} The size (optional) and bitmap font id (required) eq 'Arial' or '20px Arial' (must have loaded previously)
* @param [style.align='left'] {String} An alignment of the multiline text ('left', 'center' or 'right')
* @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
*/
PIXI.BitmapText = function(text, style)
{
PIXI.DisplayObjectContainer.call(this);
PIXI.SpriteBatch.call(this);
this._pool = [];
this.setText(text);
this.setStyle(style);
@@ -27,7 +29,7 @@ PIXI.BitmapText = function(text, style)
};
// constructor
PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
PIXI.BitmapText.prototype = Object.create(PIXI.SpriteBatch.prototype);
PIXI.BitmapText.prototype.constructor = PIXI.BitmapText;
/**
@@ -44,11 +46,11 @@ PIXI.BitmapText.prototype.setText = function(text)
/**
* Set the style of the text
* style.font {String} The size (optional) and bitmap font id (required) eq 'Arial' or '20px Arial' (must have loaded previously)
* [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
*
* @method setStyle
* @param style {Object} The style parameters
* @param style.font {String} The size (optional) and bitmap font id (required) eq 'Arial' or '20px Arial' (must have loaded previously)
* @param [style.align='left'] {String} An alignment of the multiline text ('left', 'center' or 'right')
* @param style {Object} The style parameters, contained as properties of an object
*/
PIXI.BitmapText.prototype.setStyle = function(style)
{
@@ -61,6 +63,7 @@ PIXI.BitmapText.prototype.setStyle = function(style)
this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size;
this.dirty = true;
this.tint = style.tint;
};
/**
@@ -79,6 +82,8 @@ PIXI.BitmapText.prototype.updateText = function()
var lineWidths = [];
var line = 0;
var scale = this.fontSize / data.size;
for(var i = 0; i < this.text.length; i++)
{
var charCode = this.text.charCodeAt(i);
@@ -125,13 +130,30 @@ PIXI.BitmapText.prototype.updateText = function()
lineAlignOffsets.push(alignOffset);
}
for(i = 0; i < chars.length; i++)
var lenChildren = this.children.length;
var lenChars = chars.length;
var tint = this.tint || 0xFFFFFF;
for(i = 0; i < lenChars; i++)
{
var c = new PIXI.Sprite(chars[i].texture); //PIXI.Sprite.fromFrame(chars[i].charCode);
var c = i < lenChildren ? this.children[i] : this._pool.pop(); // get old child if have. if not - take from pool.
if (c) c.setTexture(chars[i].texture); // check if got one before.
else c = new PIXI.Sprite(chars[i].texture); // if no create new one.
c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;
c.position.y = chars[i].position.y * scale;
c.scale.x = c.scale.y = scale;
this.addChild(c);
c.tint = tint;
if (!c.parent) this.addChild(c);
}
// remove unnecessary children.
// and put their into the pool.
while(this.children.length > lenChars)
{
var child = this.getChildAt(this.children.length - 1);
this._pool.push(child);
this.removeChild(child);
}
this.width = maxLineWidth * scale;
@@ -139,7 +161,7 @@ PIXI.BitmapText.prototype.updateText = function()
};
/**
* Updates the transfor of this object
* Updates the transform of this object
*
* @method updateTransform
* @private
@@ -148,16 +170,11 @@ PIXI.BitmapText.prototype.updateTransform = function()
{
if(this.dirty)
{
while(this.children.length > 0)
{
this.removeChild(this.getChildAt(0));
}
this.updateText();
this.dirty = false;
}
PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
PIXI.SpriteBatch.prototype.updateTransform.call(this);
};
PIXI.BitmapText.fonts = {};
+40 -5
View File
@@ -3,7 +3,7 @@
*/
/**
* A Text Object will create a line(s) of text to split a line you can use '\n'
* A Text Object will create a line(s) of text. To split a line you can use '\n'
*
* @class Text
* @extends Sprite
@@ -12,7 +12,7 @@
* @param [style] {Object} The style parameters
* @param [style.font] {String} default 'bold 20pt Arial' The style and size of the font
* @param [style.fill='black'] {Object} A canvas fillstyle that will be used on the text eg 'red', '#00FF00'
* @param [style.align='left'] {String} An alignment of the multiline text ('left', 'center' or 'right')
* @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
* @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'
* @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
* @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
@@ -20,8 +20,21 @@
*/
PIXI.Text = function(text, style)
{
/**
* The canvas element that everything is drawn to
*
* @property canvas
* @type HTMLCanvasElement
*/
this.canvas = document.createElement('canvas');
/**
* The canvas 2d context that everything is drawn with
* @property context
* @type HTMLCanvasElement 2d Context
*/
this.context = this.canvas.getContext('2d');
PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas));
this.setText(text);
@@ -42,7 +55,7 @@ PIXI.Text.prototype.constructor = PIXI.Text;
* @param [style] {Object} The style parameters
* @param [style.font='bold 20pt Arial'] {String} The style and size of the font
* @param [style.fill='black'] {Object} A canvas fillstyle that will be used on the text eg 'red', '#00FF00'
* @param [style.align='left'] {String} An alignment of the multiline text ('left', 'center' or 'right')
* @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
* @param [style.stroke='black'] {String} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'
* @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
* @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
@@ -72,6 +85,7 @@ PIXI.Text.prototype.setText = function(text)
{
this.text = text.toString() || ' ';
this.dirty = true;
};
/**
@@ -108,6 +122,8 @@ PIXI.Text.prototype.updateText = function()
var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness;
this.canvas.height = lineHeight * lines.length;
if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
//set canvas text styles
this.context.fillStyle = this.style.fill;
this.context.font = this.style.font;
@@ -161,11 +177,29 @@ PIXI.Text.prototype.updateTexture = function()
this._width = this.canvas.width;
this._height = this.canvas.height;
PIXI.texturesToUpdate.push(this.texture.baseTexture);
this.requiresUpdate = true;
};
/**
* Updates the transfor of this object
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.Text.prototype._renderWebGL = function(renderSession)
{
if(this.requiresUpdate)
{
this.requiresUpdate = false;
PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl);
}
PIXI.Sprite.prototype._renderWebGL.call(this, renderSession);
};
/**
* Updates the transform of this object
*
* @method updateTransform
* @private
@@ -184,6 +218,7 @@ PIXI.Text.prototype.updateTransform = function()
/*
* http://stackoverflow.com/users/34441/ellisbben
* great solution to the problem!
* returns the height of the given font
*
* @method determineFontHeight
* @param fontStyle {Object}
+54 -40
View File
@@ -6,6 +6,8 @@ PIXI.BaseTextureCache = {};
PIXI.texturesToUpdate = [];
PIXI.texturesToDestroy = [];
PIXI.BaseTextureCacheIdGenerator = 0;
/**
* A texture stores the information that represents an image. All textures have a base texture
*
@@ -13,6 +15,7 @@ PIXI.texturesToDestroy = [];
* @uses EventTarget
* @constructor
* @param source {String} the source object (image or canvas)
* @param scaleMode {Number} Should be one of the PIXI.scaleMode consts
*/
PIXI.BaseTexture = function(source, scaleMode)
{
@@ -39,10 +42,10 @@ PIXI.BaseTexture = function(source, scaleMode)
/**
* The scale mode to apply when scaling this texture
* @property scaleMode
* @type PIXI.BaseTexture.SCALE_MODE
* @default PIXI.BaseTexture.SCALE_MODE.LINEAR
* @type PIXI.scaleModes
* @default PIXI.scaleModes.LINEAR
*/
this.scaleMode = scaleMode || PIXI.BaseTexture.SCALE_MODE.DEFAULT;
this.scaleMode = scaleMode || PIXI.scaleModes.DEFAULT;
/**
* [read-only] Describes if the base texture has loaded or not
@@ -63,34 +66,7 @@ PIXI.BaseTexture = function(source, scaleMode)
if(!source)return;
if(this.source instanceof Image || this.source instanceof HTMLImageElement)
{
if(this.source.complete)
{
this.hasLoaded = true;
this.width = this.source.width;
this.height = this.source.height;
PIXI.texturesToUpdate.push(this);
}
else
{
var scope = this;
this.source.onload = function() {
scope.hasLoaded = true;
scope.width = scope.source.width;
scope.height = scope.source.height;
// add it to somewhere...
PIXI.texturesToUpdate.push(scope);
scope.dispatchEvent( { type: 'loaded', content: scope } );
};
//this.image.src = imageUrl;
}
}
else
if(this.source.complete || this.source.getContext)
{
this.hasLoaded = true;
this.width = this.source.width;
@@ -98,9 +74,32 @@ PIXI.BaseTexture = function(source, scaleMode)
PIXI.texturesToUpdate.push(this);
}
else
{
var scope = this;
this.source.onload = function() {
scope.hasLoaded = true;
scope.width = scope.source.width;
scope.height = scope.source.height;
// add it to somewhere...
PIXI.texturesToUpdate.push(scope);
scope.dispatchEvent( { type: 'loaded', content: scope } );
};
//this.image.src = imageUrl;
}
this.imageUrl = null;
this._powerOf2 = false;
//TODO will be used for futer pixi 1.5...
this.id = PIXI.BaseTextureCacheIdGenerator++;
// used for webGL
this._glTextures = [];
};
PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture;
@@ -112,10 +111,9 @@ PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture;
*/
PIXI.BaseTexture.prototype.destroy = function()
{
if(this.source instanceof Image)
if(this.imageUrl)
{
if (this.imageUrl in PIXI.BaseTextureCache)
delete PIXI.BaseTextureCache[this.imageUrl];
delete PIXI.BaseTextureCache[this.imageUrl];
this.imageUrl = null;
this.source.src = null;
}
@@ -138,7 +136,7 @@ PIXI.BaseTexture.prototype.updateSourceImage = function(newSrc)
/**
* Helper function that returns a base texture based on an image url
* If the image is not in the base texture cache it will be created and loaded
* If the image is not in the base texture cache it will be created and loaded
*
* @static
* @method fromImage
@@ -148,6 +146,8 @@ PIXI.BaseTexture.prototype.updateSourceImage = function(newSrc)
PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin, scaleMode)
{
var baseTexture = PIXI.BaseTextureCache[imageUrl];
crossorigin = !crossorigin;
if(!baseTexture)
{
// new Image() breaks tex loading in some versions of Chrome.
@@ -166,8 +166,22 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin, scaleMode)
return baseTexture;
};
PIXI.BaseTexture.SCALE_MODE = {
DEFAULT: 0, //default to LINEAR
LINEAR: 0,
NEAREST: 1
};
PIXI.BaseTexture.fromCanvas = function(canvas, scaleMode)
{
if(!canvas._pixiId)
{
canvas._pixiId = 'canvas_' + PIXI.TextureCacheIdGenerator++;
}
var baseTexture = PIXI.BaseTextureCache[canvas._pixiId];
if(!baseTexture)
{
baseTexture = new PIXI.BaseTexture(canvas, scaleMode);
PIXI.BaseTextureCache[canvas._pixiId] = baseTexture;
}
return baseTexture;
};
+58 -116
View File
@@ -5,7 +5,7 @@
/**
A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it.
__Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded.
__Hint__: All DisplayObjects (exmpl. Sprites) that render on RenderTexture should be preloaded.
Otherwise black rectangles will be drawn instead.
RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example:
@@ -30,112 +30,73 @@
@param width {Number} The width of the render texture
@param height {Number} The height of the render texture
*/
PIXI.RenderTexture = function(width, height)
PIXI.RenderTexture = function(width, height, renderer)
{
PIXI.EventTarget.call( this );
this.width = width || 100;
this.height = height || 100;
this.indetityMatrix = PIXI.mat3.create();
this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
if(PIXI.gl)
this.baseTexture = new PIXI.BaseTexture();
this.baseTexture.width = this.width;
this.baseTexture.height = this.height;
this.baseTexture._glTextures = [];
this.baseTexture.hasLoaded = true;
// each render texture can only belong to one renderer at the moment if its webGL
this.renderer = renderer || PIXI.defaultRenderer;
if(this.renderer.type === PIXI.WEBGL_RENDERER)
{
this.initWebGL();
var gl = this.renderer.gl;
this.textureBuffer = new PIXI.FilterTexture(gl, this.width, this.height);
this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture;
this.render = this.renderWebGL;
this.projection = new PIXI.Point(this.width/2 , -this.height/2);
}
else
{
this.initCanvas();
this.render = this.renderCanvas;
this.textureBuffer = new PIXI.CanvasBuffer(this.width, this.height);
this.baseTexture.source = this.textureBuffer.canvas;
}
PIXI.Texture.frameUpdates.push(this);
};
PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype );
PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture;
/**
* Initializes the webgl data for this texture
*
* @method initWebGL
* @private
*/
PIXI.RenderTexture.prototype.initWebGL = function()
{
var gl = PIXI.gl;
this.glFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
this.glFramebuffer.width = this.width;
this.glFramebuffer.height = this.height;
this.baseTexture = new PIXI.BaseTexture();
this.baseTexture.width = this.width;
this.baseTexture.height = this.height;
this.baseTexture._glTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);
this.baseTexture.isRender = true;
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0);
// create a projection matrix..
this.projection = new PIXI.Point(this.width/2 , -this.height/2);
// set the correct render function..
this.render = this.renderWebGL;
};
PIXI.RenderTexture.prototype.resize = function(width, height)
{
this.width = width;
this.height = height;
if(PIXI.gl)
this.frame.width = this.width;
this.frame.height = this.height;
if(this.renderer.type === PIXI.WEBGL_RENDERER)
{
this.projection.x = this.width / 2;
this.projection.y = -this.height / 2;
var gl = PIXI.gl;
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
var gl = this.gl;
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTextures[gl.id]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
}
else
{
this.frame.width = this.width;
this.frame.height = this.height;
this.renderer.resize(this.width, this.height);
this.textureBuffer.resize(this.width, this.height);
}
};
/**
* Initializes the canvas data for this texture
*
* @method initCanvas
* @private
*/
PIXI.RenderTexture.prototype.initCanvas = function()
{
this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0);
this.baseTexture = new PIXI.BaseTexture(this.renderer.view);
this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
this.render = this.renderCanvas;
PIXI.Texture.frameUpdates.push(this);
};
/**
@@ -148,64 +109,42 @@ PIXI.RenderTexture.prototype.initCanvas = function()
*/
PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear)
{
var gl = PIXI.gl;
var gl = this.renderer.gl;
// enable the alpha color mask..
gl.colorMask(true, true, true, true);
gl.viewport(0, 0, this.width, this.height);
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer );
if(clear)
{
gl.clearColor(0,0,0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
if(clear)this.textureBuffer.clear();
// THIS WILL MESS WITH HIT TESTING!
var children = displayObject.children;
//TODO -? create a new one??? dont think so!
var originalWorldTransform = displayObject.worldTransform;
displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix;
displayObject.worldTransform = PIXI.RenderTexture.tempMatrix;
// modify to flip...
displayObject.worldTransform[4] = -1;
displayObject.worldTransform[5] = this.projection.y * -2;
displayObject.worldTransform.d = -1;
displayObject.worldTransform.ty = this.projection.y * -2;
if(position)
{
displayObject.worldTransform[2] = position.x;
displayObject.worldTransform[5] -= position.y;
displayObject.worldTransform.tx = position.x;
displayObject.worldTransform.ty -= position.y;
}
PIXI.visibleCount++;
displayObject.vcount = PIXI.visibleCount;
for(var i=0,j=children.length; i<j; i++)
{
children[i].updateTransform();
}
var renderGroup = displayObject.__renderGroup;
// update the textures!
PIXI.WebGLRenderer.updateTextures();
if(renderGroup)
{
if(displayObject === renderGroup.root)
{
renderGroup.render(this.projection, this.glFramebuffer);
}
else
{
renderGroup.renderSpecific(displayObject, this.projection, this.glFramebuffer);
}
}
else
{
if(!this.renderGroup)this.renderGroup = new PIXI.WebGLRenderGroup(gl);
this.renderGroup.setRenderable(displayObject);
this.renderGroup.render(this.projection, this.glFramebuffer);
}
//
this.renderer.renderDisplayObject(displayObject, this.projection, this.textureBuffer.frameBuffer);
displayObject.worldTransform = originalWorldTransform;
};
@@ -221,27 +160,30 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle
*/
PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, position, clear)
{
//console.log("!!")
var children = displayObject.children;
displayObject.worldTransform = PIXI.mat3.create();
displayObject.worldTransform = PIXI.RenderTexture.tempMatrix;
if(position)
{
displayObject.worldTransform[2] = position.x;
displayObject.worldTransform[5] = position.y;
displayObject.worldTransform.tx = position.x;
displayObject.worldTransform.ty = position.y;
}
for(var i = 0, j = children.length; i < j; i++)
{
children[i].updateTransform();
}
if(clear) this.renderer.context.clearRect(0,0, this.width, this.height);
if(clear)this.textureBuffer.clear();
this.renderer.renderDisplayObject(displayObject);
var context = this.textureBuffer.context;
this.renderer.context.setTransform(1,0,0,1,0,0);
this.renderer.renderDisplayObject(displayObject, context);
//PIXI.texturesToUpdate.push(this.baseTexture);
context.setTransform(1,0,0,1,0,0);
};
PIXI.RenderTexture.tempMatrix = new PIXI.Matrix();
+54 -9
View File
@@ -5,6 +5,8 @@
PIXI.TextureCache = {};
PIXI.FrameCache = {};
PIXI.TextureCacheIdGenerator = 0;
/**
* A texture stores the information that represents an image or part of an image. It cannot be added
* to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used
@@ -57,8 +59,7 @@ PIXI.Texture = function(baseTexture, frame)
if(baseTexture.hasLoaded)
{
if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
//console.log(frame)
this.setFrame(frame);
}
else
@@ -83,9 +84,8 @@ PIXI.Texture.prototype.onBaseTextureLoaded = function()
baseTexture.removeEventListener( 'loaded', this.onLoaded );
if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
this.noFrame = false;
this.width = this.frame.width;
this.height = this.frame.height;
this.setFrame(this.frame);
this.scope.dispatchEvent( { type: 'update', content: this } );
};
@@ -121,9 +121,32 @@ PIXI.Texture.prototype.setFrame = function(frame)
this.updateFrame = true;
PIXI.Texture.frameUpdates.push(this);
//this.dispatchEvent( { type: 'update', content: this } );
};
PIXI.Texture.prototype._updateWebGLuvs = function()
{
if(!this._uvs)this._uvs = new PIXI.TextureUvs();
var frame = this.frame;
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 returns a texture based on an image url
* If the image is not in the texture cache it will be created and loaded
@@ -159,7 +182,7 @@ PIXI.Texture.fromImage = function(imageUrl, crossorigin, scaleMode)
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 ' + this);
if(!texture) throw new Error('The frameId "' + frameId + '" does not exist in the texture cache ');
return texture;
};
@@ -174,8 +197,10 @@ PIXI.Texture.fromFrame = function(frameId)
*/
PIXI.Texture.fromCanvas = function(canvas, scaleMode)
{
var baseTexture = new PIXI.BaseTexture(canvas, scaleMode);
return new PIXI.Texture(baseTexture);
var baseTexture = PIXI.BaseTexture.fromCanvas(canvas, scaleMode);
return new PIXI.Texture( baseTexture );
};
@@ -210,4 +235,24 @@ PIXI.Texture.removeTextureFromCache = function(id)
// this is more for webGL.. it contains updated frames..
PIXI.Texture.frameUpdates = [];
PIXI.Texture.SCALE_MODE = PIXI.BaseTexture.SCALE_MODE;
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.y4 = 0;
};
+11 -10
View File
@@ -4,16 +4,15 @@
/**
* This helper function will automatically detect which renderer you should be using.
* WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by
* WebGL is the preferred renderer as it is a lot faster. If webGL is not supported by
* the browser then this function will return a canvas renderer
*
* @method autoDetectRenderer
* @class autoDetectRenderer
* @static
* @param width {Number} the width of the renderers view
* @param height {Number} the height of the renderers view
* @param view {Canvas} the canvas to use as a view, optional
* @param transparent=false {Boolean} the transparency of the render view, default false
* @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment)
* @param width=800 {Number} the width of the renderers view
* @param height=600 {Number} the height of the renderers view
* @param [view] {Canvas} the canvas to use as a view, optional
* @param [transparent=false] {Boolean} the transparency of the render view, default false
* @param [antialias=false] {Boolean} sets antialias (only applicable in webGL chrome at the moment)
*
* antialias
*/
@@ -31,13 +30,15 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias)
}
} )();
if(webgl)
// used to detect ie 11 - no longer required
/* if(webgl)
{
var ie = (navigator.userAgent.toLowerCase().indexOf('trident') !== -1);
webgl = !ie;
}
*/
//console.log(webgl);
if( webgl )
{
return new PIXI.WebGLRenderer(width, height, view, transparent, antialias);
+37 -1
View File
@@ -1,3 +1,7 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* https://github.com/mrdoob/eventtarget.js/
* THankS mr DOob!
@@ -7,7 +11,7 @@
* Adds event emitter functionality to a class
*
* @class EventTarget
* @example
*
* function MyEmitter() {
* PIXI.EventTarget.call(this); //mixes in event target stuff
* }
@@ -17,8 +21,21 @@
*/
PIXI.EventTarget = function () {
/**
* Holds all the listeners
*
* @property listeneners
* @type Object
*/
var listeners = {};
/**
* Adds a listener for a specific event
*
* @method addEventListener
* @param type {string} A string representing the event type to listen for.
* @param listener {function} The callback function that will be fired when the event occurs
*/
this.addEventListener = this.on = function ( type, listener ) {
@@ -35,6 +52,12 @@ PIXI.EventTarget = function () {
};
/**
* Fires the event, ie pretends that the event has happened
*
* @method dispatchEvent
* @param event {Event} the event object
*/
this.dispatchEvent = this.emit = function ( event ) {
if ( !listeners[ event.type ] || !listeners[ event.type ].length ) {
@@ -51,6 +74,13 @@ PIXI.EventTarget = function () {
};
/**
* Removes the specified listener that was assigned to the specified event type
*
* @method removeEventListener
* @param type {string} A string representing the event type which will have its listener removed
* @param listener {function} The callback function that was be fired when the event occured
*/
this.removeEventListener = this.off = function ( type, listener ) {
var index = listeners[ type ].indexOf( listener );
@@ -63,6 +93,12 @@ PIXI.EventTarget = function () {
};
/**
* Removes all the listeners that were active for the specified event type
*
* @method removeAllEventListeners
* @param type {string} A string representing the event type which will have all its listeners removed
*/
this.removeAllEventListeners = function( type ) {
var a = listeners[type];
if (a)
+22 -9
View File
@@ -28,17 +28,23 @@
This is an amazing lib!
slightly modified by mat groves (matgroves.com);
slightly modified by Mat Groves (matgroves.com);
*/
/**
* Based on the Polyk library http://polyk.ivank.net released under MIT licence.
* This is an amazing lib!
* slightly modified by Mat Groves (matgroves.com);
* @class PolyK
*
*/
PIXI.PolyK = {};
/**
* Triangulates shapes for webGL graphic fills
*
* @method Triangulate
* @namespace PolyK
* @constructor
*
*/
PIXI.PolyK.Triangulate = function(p)
{
@@ -114,10 +120,17 @@ PIXI.PolyK.Triangulate = function(p)
};
/**
* Checks if a point is within a triangle
* Checks whether a point is within a triangle
*
* @class _PointInTriangle
* @namespace PolyK
* @method _PointInTriangle
* @param px {Number} x coordinate of the point to test
* @param py {Number} y coordinate of the point to test
* @param ax {Number} x coordinate of the a point of the triangle
* @param ay {Number} y coordinate of the a point of the triangle
* @param bx {Number} x coordinate of the b point of the triangle
* @param by {Number} y coordinate of the b point of the triangle
* @param cx {Number} x coordinate of the c point of the triangle
* @param cy {Number} y coordinate of the c point of the triangle
* @private
*/
PIXI.PolyK._PointInTriangle = function(px, py, ax, ay, bx, by, cx, cy)
@@ -144,10 +157,10 @@ PIXI.PolyK._PointInTriangle = function(px, py, ax, ay, bx, by, cx, cy)
};
/**
* Checks if a shape is convex
* Checks whether a shape is convex
*
* @class _convex
* @namespace PolyK
* @method _convex
*
* @private
*/
PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign)
+79 -26
View File
@@ -1,3 +1,7 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
@@ -7,6 +11,8 @@
/**
* A polyfill for requestAnimationFrame
* You can actually use both requestAnimationFrame and requestAnimFrame,
* you will still benefit from the polyfill
*
* @method requestAnimationFrame
*/
@@ -48,10 +54,20 @@ window.requestAnimFrame = window.requestAnimationFrame;
* @method hex2rgb
* @param hex {Number}
*/
PIXI.hex2rgb = function hex2rgb(hex) {
PIXI.hex2rgb = function(hex) {
return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
};
/**
* Converts a color as an [R, G, B] array to a hex number
*
* @method rgb2hex
* @param rgb {Array}
*/
PIXI.rgb2hex = function(rgb) {
return ((rgb[0]*255 << 16) + (rgb[1]*255 << 8) + rgb[2]*255);
};
/**
* A polyfill for Function.prototype.bind
*
@@ -86,7 +102,7 @@ if (typeof Function.prototype.bind !== 'function') {
* @class AjaxRequest
* @constructor
*/
PIXI.AjaxRequest = function AjaxRequest()
PIXI.AjaxRequest = function()
{
var activexmodes = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0', 'Microsoft.XMLHTTP']; //activeX versions to check for in IE
@@ -111,34 +127,71 @@ PIXI.AjaxRequest = function AjaxRequest()
return false;
}
};
/*
* DEBUGGING ONLY
*/
PIXI.runList = function(item)
PIXI.packColorRGBA = function(r, g, b, a)//r, g, b, a)
{
window.console.log('>>>>>>>>>');
window.console.log('_');
var safe = 0;
var tmp = item.first;
window.console.log(tmp);
// console.log(r, b, c, d)
return (Math.floor((r)*63) << 18) | (Math.floor((g)*63) << 12) | (Math.floor((b)*63) << 6);// | (Math.floor((a)*63))
// i = i | (Math.floor((a)*63));
// return i;
// var r = (i / 262144.0 ) / 64;
// var g = (i / 4096.0)%64 / 64;
// var b = (i / 64.0)%64 / 64;
// var a = (i)%64 / 64;
// console.log(r, g, b, a);
// return i;
while(tmp._iNext)
{
safe++;
tmp = tmp._iNext;
window.console.log(tmp);
// console.log(tmp);
if(safe > 100)
{
window.console.log('BREAK');
break;
}
}
};
*/
/*
PIXI.packColorRGB = function(r, g, b)//r, g, b, a)
{
return (Math.floor((r)*255) << 16) | (Math.floor((g)*255) << 8) | (Math.floor((b)*255));
};
PIXI.unpackColorRGB = function(r, g, b)//r, g, b, a)
{
return (Math.floor((r)*255) << 16) | (Math.floor((g)*255) << 8) | (Math.floor((b)*255));
};
*/
/**
* Checks whether the Canvas BlendModes are supported by the current browser
*
* @method canUseNewCanvasBlendModes
* @return {Boolean} whether they are supported
*/
PIXI.canUseNewCanvasBlendModes = function()
{
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
var context = canvas.getContext('2d');
context.fillStyle = '#000';
context.fillRect(0,0,1,1);
context.globalCompositeOperation = 'multiply';
context.fillStyle = '#fff';
context.fillRect(0,0,1,1);
return context.getImageData(0,0,1,1).data[0] === 0;
};
/**
* Given a number, this function returns the closest number that is a power of two
* this function is taken from Starling Framework as its pretty neat ;)
*
* @method getNextPowerOfTwo
* @param number {Number}
* @return {Number} the closest number that is a power of two
*/
PIXI.getNextPowerOfTwo = function(number)
{
if (number > 0 && (number & (number - 1)) === 0) // see: http://goo.gl/D9kPj
return number;
else
{
var result = 1;
while (result < number) result <<= 1;
return result;
}
};