var Container = require('../display/Container');
/**
* The ParticleContainer class is a really fast version of the Container built solely for speed,
* so use when you need a lot of sprites or particles. The tradeoff of the ParticleContainer is that advanced
* functionality will not work. ParticleContainer implements only the basic object transform (position, scale, rotation).
* Any other functionality like tinting, masking, etc will not work on sprites in this batch.
*
* It's extremely easy to use :
*
* ```js
* var container = new ParticleContainer();
*
* for (var i = 0; i < 100; ++i)
* {
* var sprite = new PIXI.Sprite.fromImage("myImage.png");
* container.addChild(sprite);
* }
* ```
*
* And here you have a hundred sprites that will be renderer at the speed of light.
*
* @class
* @extends Container
* @memberof PIXI
*
* @param size {number} The number of images in the SpriteBatch before it flushes.
*/
function ParticleContainer(size, properties)
{
Container.call(this);
// set properties to be dynamic (true) / static (false)
// TODO this could be easier to understand!
this._properties = properties || [false, true, false, false, false];
this._size = size || 15000;
this._buffers = null;
this._updateStatic = false;
this.interactiveChildren = false;
}
ParticleContainer.prototype = Object.create(Container.prototype);
ParticleContainer.prototype.constructor = ParticleContainer;
module.exports = ParticleContainer;
/**
* Updates the object transform for rendering
*
* @private
*/
ParticleContainer.prototype.updateTransform = function ()
{
// TODO don't need to!
this.displayObjectUpdateTransform();
// PIXI.Container.prototype.updateTransform.call( this );
};
/**
* Renders the container using the WebGL renderer
*
* @param renderer {WebGLRenderer} The webgl renderer
* @private
*/
ParticleContainer.prototype.renderWebGL = function (renderer)
{
if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable)
{
return;
}
renderer.setObjectRenderer( renderer.plugins.particle );
renderer.plugins.particle.render( this );
};
/**
* Adds a child to this particle container at a specified index. If the index is out of bounds an error will be thrown
*
* @param child {DisplayObject} The child to add
* @param index {Number} The index to place the child in
* @return {DisplayObject} The child that was added.
*/
ParticleContainer.prototype.addChildAt = function (child, index)
{
// prevent adding self as child
if (child === this)
{
return child;
}
if (index >= 0 && index <= this.children.length)
{
if (child.parent)
{
child.parent.removeChild(child);
}
child.parent = this;
this.children.splice(index, 0, child);
this._updateStatic = true;
return child;
}
else
{
throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length);
}
};
/**
* Removes a child from the specified index position.
*
* @param index {Number} The index to get the child from
* @return {DisplayObject} The child that was removed.
*/
ParticleContainer.prototype.removeChildAt = function (index)
{
var child = this.getChildAt(index);
child.parent = null;
this.children.splice(index, 1);
this._updateStatic = true;
return child;
};
/**
* Renders the object using the Canvas renderer
*
* @param renderer {CanvasRenderer} The canvas renderer
* @private
*/
ParticleContainer.prototype.renderCanvas = function (renderer)
{
if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable)
{
return;
}
var context = renderer.context;
var transform = this.worldTransform;
var isRotated = true;
context.globalAlpha = this.worldAlpha;
this.displayObjectUpdateTransform();
for (var i = 0; i < this.children.length; ++i)
{
var child = this.children[i];
if (!child.visible)
{
continue;
}
var frame = child.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
if (isRotated)
{
context.setTransform(
transform.a,
transform.b,
transform.c,
transform.d,
transform.tx,
transform.ty
);
isRotated = false;
}
context.drawImage(
child.texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5) | 0,
((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5) | 0,
frame.width * child.scale.x,
frame.height * child.scale.y
);
}
else
{
if (!isRotated)
{
isRotated = true;
}
child.displayObjectUpdateTransform();
var childTransform = child.worldTransform;
if (renderer.roundPixels)
{
context.setTransform(
childTransform.a,
childTransform.b,
childTransform.c,
childTransform.d,
childTransform.tx | 0,
childTransform.ty | 0
);
}
else
{
context.setTransform(
childTransform.a,
childTransform.b,
childTransform.c,
childTransform.d,
childTransform.tx,
childTransform.ty
);
}
context.drawImage(
child.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
);
}
}
};