updated pixi to v2

This commit is contained in:
logsol 2014-12-21 19:32:18 +01:00
parent a5b3d2f671
commit 58b83f7297
95 changed files with 44677 additions and 3522 deletions

View file

@ -0,0 +1,358 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* A set of functions used by the canvas renderer to draw the primitive graphics data.
*
* @class CanvasGraphics
* @static
*/
PIXI.CanvasGraphics = function()
{
};
/*
* Renders a PIXI.Graphics object to a canvas.
*
* @method renderGraphics
* @static
* @param graphics {Graphics} the actual graphics object to render
* @param context {CanvasRenderingContext2D} the 2d drawing method of the canvas
*/
PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
{
var worldAlpha = graphics.worldAlpha;
if(graphics.dirty)
{
this.updateGraphicsTint(graphics);
graphics.dirty = false;
}
for (var i = 0; i < graphics.graphicsData.length; i++)
{
var data = graphics.graphicsData[i];
var shape = data.shape;
var fillColor = data._fillTint;
var lineColor = data._lineTint;
context.lineWidth = data.lineWidth;
if(data.type === PIXI.Graphics.POLY)
{
context.beginPath();
var points = shape.points;
context.moveTo(points[0], points[1]);
for (var j=1; j < points.length/2; j++)
{
context.lineTo(points[j * 2], points[j * 2 + 1]);
}
if(shape.closed)
{
context.lineTo(points[0], points[1]);
}
// if the first and last point are the same close the path - much neater :)
if(points[0] === points[points.length-2] && points[1] === points[points.length-1])
{
context.closePath();
}
if(data.fill)
{
context.globalAlpha = data.fillAlpha * worldAlpha;
context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
context.fill();
}
if(data.lineWidth)
{
context.globalAlpha = data.lineAlpha * worldAlpha;
context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
context.stroke();
}
}
else if(data.type === PIXI.Graphics.RECT)
{
if(data.fillColor || data.fillColor === 0)
{
context.globalAlpha = data.fillAlpha * worldAlpha;
context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
context.fillRect(shape.x, shape.y, shape.width, shape.height);
}
if(data.lineWidth)
{
context.globalAlpha = data.lineAlpha * worldAlpha;
context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
context.strokeRect(shape.x, shape.y, shape.width, shape.height);
}
}
else if(data.type === PIXI.Graphics.CIRC)
{
// TODO - need to be Undefined!
context.beginPath();
context.arc(shape.x, shape.y, shape.radius,0,2*Math.PI);
context.closePath();
if(data.fill)
{
context.globalAlpha = data.fillAlpha * worldAlpha;
context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
context.fill();
}
if(data.lineWidth)
{
context.globalAlpha = data.lineAlpha * worldAlpha;
context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
context.stroke();
}
}
else if(data.type === PIXI.Graphics.ELIP)
{
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
var w = shape.width * 2;
var h = shape.height * 2;
var x = shape.x - w/2;
var y = shape.y - h/2;
context.beginPath();
var kappa = 0.5522848,
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
context.moveTo(x, ym);
context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
context.closePath();
if(data.fill)
{
context.globalAlpha = data.fillAlpha * worldAlpha;
context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
context.fill();
}
if(data.lineWidth)
{
context.globalAlpha = data.lineAlpha * worldAlpha;
context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
context.stroke();
}
}
else if (data.type === PIXI.Graphics.RREC)
{
var rx = shape.x;
var ry = shape.y;
var width = shape.width;
var height = shape.height;
var radius = shape.radius;
var maxRadius = Math.min(width, height) / 2 | 0;
radius = radius > maxRadius ? maxRadius : radius;
context.beginPath();
context.moveTo(rx, ry + radius);
context.lineTo(rx, ry + height - radius);
context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
context.lineTo(rx + width - radius, ry + height);
context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
context.lineTo(rx + width, ry + radius);
context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
context.lineTo(rx + radius, ry);
context.quadraticCurveTo(rx, ry, rx, ry + radius);
context.closePath();
if(data.fillColor || data.fillColor === 0)
{
context.globalAlpha = data.fillAlpha * worldAlpha;
context.fillStyle = '#' + ('00000' + ( fillColor | 0).toString(16)).substr(-6);
context.fill();
}
if(data.lineWidth)
{
context.globalAlpha = data.lineAlpha * worldAlpha;
context.strokeStyle = '#' + ('00000' + ( lineColor | 0).toString(16)).substr(-6);
context.stroke();
}
}
}
};
/*
* Renders a graphics mask
*
* @static
* @private
* @method renderGraphicsMask
* @param graphics {Graphics} the graphics which will be used as a mask
* @param context {CanvasRenderingContext2D} the context 2d method of the canvas
*/
PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
{
var len = graphics.graphicsData.length;
if(len === 0) return;
if(len > 1)
{
len = 1;
window.console.log('Pixi.js warning: masks in canvas can only mask using the first path in the graphics object');
}
for (var i = 0; i < 1; i++)
{
var data = graphics.graphicsData[i];
var shape = data.shape;
if(data.type === PIXI.Graphics.POLY)
{
context.beginPath();
var points = shape.points;
context.moveTo(points[0], points[1]);
for (var j=1; j < points.length/2; j++)
{
context.lineTo(points[j * 2], points[j * 2 + 1]);
}
// if the first and last point are the same close the path - much neater :)
if(points[0] === points[points.length-2] && points[1] === points[points.length-1])
{
context.closePath();
}
}
else if(data.type === PIXI.Graphics.RECT)
{
context.beginPath();
context.rect(shape.x, shape.y, shape.width, shape.height);
context.closePath();
}
else if(data.type === PIXI.Graphics.CIRC)
{
// TODO - need to be Undefined!
context.beginPath();
context.arc(shape.x, shape.y, shape.radius,0,2*Math.PI);
context.closePath();
}
else if(data.type === PIXI.Graphics.ELIP)
{
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
var w = shape.width * 2;
var h = shape.height * 2;
var x = shape.x - w/2;
var y = shape.y - h/2;
context.beginPath();
var kappa = 0.5522848,
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
context.moveTo(x, ym);
context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
context.closePath();
}
else if (data.type === PIXI.Graphics.RREC)
{
var pts = shape.points;
var rx = pts[0];
var ry = pts[1];
var width = pts[2];
var height = pts[3];
var radius = pts[4];
var maxRadius = Math.min(width, height) / 2 | 0;
radius = radius > maxRadius ? maxRadius : radius;
context.beginPath();
context.moveTo(rx, ry + radius);
context.lineTo(rx, ry + height - radius);
context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
context.lineTo(rx + width - radius, ry + height);
context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
context.lineTo(rx + width, ry + radius);
context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
context.lineTo(rx + radius, ry);
context.quadraticCurveTo(rx, ry, rx, ry + radius);
context.closePath();
}
}
};
PIXI.CanvasGraphics.updateGraphicsTint = function(graphics)
{
if(graphics.tint === 0xFFFFFF)return;
var tintR = (graphics.tint >> 16 & 0xFF) / 255;
var tintG = (graphics.tint >> 8 & 0xFF) / 255;
var tintB = (graphics.tint & 0xFF)/ 255;
for (var i = 0; i < graphics.graphicsData.length; i++)
{
var data = graphics.graphicsData[i];
var fillColor = data.fillColor | 0;
var lineColor = data.lineColor | 0;
/*
var colorR = (fillColor >> 16 & 0xFF) / 255;
var colorG = (fillColor >> 8 & 0xFF) / 255;
var colorB = (fillColor & 0xFF) / 255;
colorR *= tintR;
colorG *= tintG;
colorB *= tintB;
fillColor = ((colorR*255 << 16) + (colorG*255 << 8) + colorB*255);
colorR = (lineColor >> 16 & 0xFF) / 255;
colorG = (lineColor >> 8 & 0xFF) / 255;
colorB = (lineColor & 0xFF) / 255;
colorR *= tintR;
colorG *= tintG;
colorB *= tintB;
lineColor = ((colorR*255 << 16) + (colorG*255 << 8) + colorB*255);
*/
// super inline cos im an optimization NAZI :)
data._fillTint = (((fillColor >> 16 & 0xFF) / 255 * tintR*255 << 16) + ((fillColor >> 8 & 0xFF) / 255 * tintG*255 << 8) + (fillColor & 0xFF) / 255 * tintB*255);
data._lineTint = (((lineColor >> 16 & 0xFF) / 255 * tintR*255 << 16) + ((lineColor >> 8 & 0xFF) / 255 * tintG*255 << 8) + (lineColor & 0xFF) / 255 * tintB*255);
}
};

View file

@ -0,0 +1,345 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* The CanvasRenderer draws the Stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL.
* Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :)
*
* @class CanvasRenderer
* @constructor
* @param [width=800] {Number} the width of the canvas view
* @param [height=600] {Number} the height of the canvas view
* @param [options] {Object} The optional renderer parameters
* @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional
* @param [options.transparent=false] {Boolean} If the render view is transparent, default false
* @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false
* @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2
* @param [options.clearBeforeRender=true] {Boolean} This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
*/
PIXI.CanvasRenderer = function(width, height, options)
{
if(options)
{
for (var i in PIXI.defaultRenderOptions)
{
if (typeof options[i] === "undefined") options[i] = PIXI.defaultRenderOptions[i];
}
}
else
{
options = PIXI.defaultRenderOptions;
}
if(!PIXI.defaultRenderer)
{
PIXI.sayHello("Canvas");
PIXI.defaultRenderer = this;
}
/**
* The renderer type.
*
* @property type
* @type Number
*/
this.type = PIXI.CANVAS_RENDERER;
/**
* The resolution of the canvas.
*
* @property resolution
* @type Number
*/
this.resolution = options.resolution;
/**
* This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
* If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color.
* If the Stage is transparent Pixi will use clearRect to clear the canvas every frame.
* Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set.
*
* @property clearBeforeRender
* @type Boolean
* @default
*/
this.clearBeforeRender = options.clearBeforeRender;
/**
* Whether the render view is transparent
*
* @property transparent
* @type Boolean
*/
this.transparent = options.transparent;
/**
* Whether the render view should be resized automatically
*
* @property autoResize
* @type Boolean
*/
this.autoResize = options.autoResize || false;
/**
* 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;
this.width *= this.resolution;
this.height *= this.resolution;
/**
* The canvas element that everything is drawn to.
*
* @property view
* @type HTMLCanvasElement
*/
this.view = options.view || document.createElement( "canvas" );
/**
* The canvas 2d context that everything is drawn with
* @property context
* @type CanvasRenderingContext2D
*/
this.context = this.view.getContext( "2d", { alpha: this.transparent } );
/**
* Boolean flag controlling canvas refresh.
*
* @property refresh
* @type Boolean
*/
this.refresh = true;
this.view.width = this.width * this.resolution;
this.view.height = this.height * this.resolution;
/**
* Internal var.
*
* @property count
* @type Number
*/
this.count = 0;
/**
* Instance of a PIXI.CanvasMaskManager, handles masking when using the canvas renderer
* @property CanvasMaskManager
* @type CanvasMaskManager
*/
this.maskManager = new PIXI.CanvasMaskManager();
/**
* The render session is just a bunch of parameter used for rendering
* @property renderSession
* @type Object
*/
this.renderSession = {
context: this.context,
maskManager: this.maskManager,
scaleMode: null,
smoothProperty: null,
/**
* If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
* Handy for crisp pixel art and speed on legacy devices.
*
*/
roundPixels: false
};
this.mapBlendModes();
this.resize(width, height);
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";
else if ("msImageSmoothingEnabled" in this.context)
this.renderSession.smoothProperty = "msImageSmoothingEnabled";
};
// constructor
PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer;
/**
* Renders the Stage to this canvas view
*
* @method render
* @param stage {Stage} the Stage element to be rendered
*/
PIXI.CanvasRenderer.prototype.render = function(stage)
{
stage.updateTransform();
this.context.setTransform(1,0,0,1,0,0);
this.context.globalAlpha = 1;
this.renderSession.currentBlendMode = PIXI.blendModes.NORMAL;
this.context.globalCompositeOperation = PIXI.blendModesCanvas[PIXI.blendModes.NORMAL];
if (navigator.isCocoonJS && this.view.screencanvas) {
this.context.fillStyle = "black";
this.context.clear();
}
if (this.clearBeforeRender)
{
if (this.transparent)
{
this.context.clearRect(0, 0, this.width, this.height);
}
else
{
this.context.fillStyle = stage.backgroundColorString;
this.context.fillRect(0, 0, this.width , this.height);
}
}
this.renderDisplayObject(stage);
// run interaction!
if(stage.interactive)
{
//need to add some events!
if(!stage._interactiveEventsAdded)
{
stage._interactiveEventsAdded = true;
stage.interactionManager.setTarget(this);
}
}
};
/**
* Removes everything from the renderer and optionally removes the Canvas DOM element.
*
* @method destroy
* @param [removeView=true] {boolean} Removes the Canvas element from the DOM.
*/
PIXI.CanvasRenderer.prototype.destroy = function(removeView)
{
if (typeof removeView === "undefined") { removeView = true; }
if (removeView && this.view.parent)
{
this.view.parent.removeChild(this.view);
}
this.view = null;
this.context = null;
this.maskManager = null;
this.renderSession = null;
};
/**
* Resizes the canvas view to the specified width and height
*
* @method resize
* @param width {Number} the new width of the canvas view
* @param height {Number} the new height of the canvas view
*/
PIXI.CanvasRenderer.prototype.resize = function(width, height)
{
this.width = width * this.resolution;
this.height = height * this.resolution;
this.view.width = this.width;
this.view.height = this.height;
if (this.autoResize) {
this.view.style.width = this.width / this.resolution + "px";
this.view.style.height = this.height / this.resolution + "px";
}
};
/**
* Renders a display object
*
* @method renderDisplayObject
* @param displayObject {DisplayObject} The displayObject to render
* @param context {CanvasRenderingContext2D} the context 2d method of the canvas
* @private
*/
PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject, context)
{
this.renderSession.context = context || this.context;
this.renderSession.resolution = this.resolution;
displayObject._renderCanvas(this.renderSession);
};
/**
* Maps Pixi blend modes to canvas blend modes.
*
* @method mapBlendModes
* @private
*/
PIXI.CanvasRenderer.prototype.mapBlendModes = function()
{
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";
}
}
};

View file

@ -0,0 +1,76 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* Creates a Canvas element of the given size.
*
* @class CanvasBuffer
* @constructor
* @param width {Number} the width for the newly created canvas
* @param height {Number} the height for the newly created canvas
*/
PIXI.CanvasBuffer = function(width, height)
{
/**
* The width of the Canvas in pixels.
*
* @property width
* @type Number
*/
this.width = width;
/**
* The height of the Canvas in pixels.
*
* @property height
* @type Number
*/
this.height = height;
/**
* The Canvas object that belongs to this CanvasBuffer.
*
* @property canvas
* @type HTMLCanvasElement
*/
this.canvas = document.createElement("canvas");
/**
* A CanvasRenderingContext2D object representing a two-dimensional rendering context.
*
* @property context
* @type CanvasRenderingContext2D
*/
this.context = this.canvas.getContext("2d");
this.canvas.width = width;
this.canvas.height = height;
};
PIXI.CanvasBuffer.prototype.constructor = PIXI.CanvasBuffer;
/**
* Clears the canvas that was created by the CanvasBuffer class.
*
* @method clear
* @private
*/
PIXI.CanvasBuffer.prototype.clear = function()
{
this.context.setTransform(1, 0, 0, 1, 0, 0);
this.context.clearRect(0,0, this.width, this.height);
};
/**
* Resizes the canvas to the specified width and height.
*
* @method resize
* @param width {Number} the new width of the canvas
* @param height {Number} the new height of the canvas
*/
PIXI.CanvasBuffer.prototype.resize = function(width, height)
{
this.width = this.canvas.width = width;
this.height = this.canvas.height = height;
};

View file

@ -0,0 +1,58 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* A set of functions used to handle masking.
*
* @class CanvasMaskManager
* @constructor
*/
PIXI.CanvasMaskManager = function()
{
};
PIXI.CanvasMaskManager.prototype.constructor = PIXI.CanvasMaskManager;
/**
* This method adds it to the current stack of masks.
*
* @method pushMask
* @param maskData {Object} the maskData that will be pushed
* @param renderSession {Object} The renderSession whose context will be used for this mask manager.
*/
PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession)
{
var context = renderSession.context;
context.save();
var cacheAlpha = maskData.alpha;
var transform = maskData.worldTransform;
var resolution = renderSession.resolution;
context.setTransform(transform.a * resolution,
transform.b * resolution,
transform.c * resolution,
transform.d * resolution,
transform.tx * resolution,
transform.ty * resolution);
PIXI.CanvasGraphics.renderGraphicsMask(maskData, context);
context.clip();
maskData.worldAlpha = cacheAlpha;
};
/**
* Restores the current drawing context to the state it was before the mask was applied.
*
* @method popMask
* @param renderSession {Object} The renderSession whose context will be used for this mask manager.
*/
PIXI.CanvasMaskManager.prototype.popMask = function(renderSession)
{
renderSession.context.restore();
};

View file

@ -0,0 +1,242 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* Utility methods for Sprite/Texture tinting.
*
* @class CanvasTinter
* @static
*/
PIXI.CanvasTinter = function()
{
};
/**
* Basically this method just needs a sprite and a color and tints the sprite with the given color.
*
* @method getTintedTexture
* @static
* @param sprite {Sprite} the sprite to tint
* @param color {Number} the color to use to tint the sprite with
* @return {HTMLCanvasElement} The tinted canvas
*/
PIXI.CanvasTinter.getTintedTexture = function(sprite, color)
{
var 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
* @static
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithMultiply = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, crop.width, crop.height);
context.globalCompositeOperation = "multiply";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
};
/**
* Tint a texture using the "overlay" operation.
*
* @method tintWithOverlay
* @static
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithOverlay = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.globalCompositeOperation = "copy";
context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
context.fillRect(0, 0, crop.width, crop.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
//context.globalCompositeOperation = "copy";
};
/**
* Tint a texture pixel per pixel.
*
* @method tintPerPixel
* @static
* @param texture {Texture} the texture to tint
* @param color {Number} the color to use to tint the sprite with
* @param canvas {HTMLCanvasElement} the current canvas
*/
PIXI.CanvasTinter.tintWithPerPixel = function(texture, color, canvas)
{
var context = canvas.getContext( "2d" );
var crop = texture.crop;
canvas.width = crop.width;
canvas.height = crop.height;
context.globalCompositeOperation = "copy";
context.drawImage(texture.baseTexture.source,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height);
var rgbValues = PIXI.hex2rgb(color);
var r = rgbValues[0], g = rgbValues[1], b = rgbValues[2];
var pixelData = context.getImageData(0, 0, crop.width, crop.height);
var pixels = pixelData.data;
for (var i = 0; i < pixels.length; i += 4)
{
pixels[i+0] *= r;
pixels[i+1] *= g;
pixels[i+2] *= b;
}
context.putImageData(pixelData, 0, 0);
};
/**
* Rounds the specified color according to the PIXI.CanvasTinter.cacheStepsPerColorChannel.
*
* @method roundColor
* @static
* @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
* @static
*/
PIXI.CanvasTinter.cacheStepsPerColorChannel = 8;
/**
* Tint cache boolean flag.
*
* @property convertTintToImage
* @type Boolean
* @static
*/
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
* @static
*/
PIXI.CanvasTinter.canUseMultiply = PIXI.canUseNewCanvasBlendModes();
/**
* The tinting method that will be used.
*
* @method tintMethod
* @static
*/
PIXI.CanvasTinter.tintMethod = PIXI.CanvasTinter.canUseMultiply ? PIXI.CanvasTinter.tintWithMultiply : PIXI.CanvasTinter.tintWithPerPixel;