diff --git a/.gitignore b/.gitignore index a4803b47..3e99daa5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ docs/docs docs/examples/libs node_modules assets -npm-debug.log \ No newline at end of file +npm-debug.log +ts-dist \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 53457c2c..830ad63b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,3 @@ language: node_js node_js: - - "0.12" -before_install: - - npm install -g grunt-cli + - "8.9.4" diff --git a/README.md b/README.md index ec3329f3..8dd425db 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ A particle system library for the [PixiJS](https://github.com/pixijs/pixi.js) library. Also, we created an [interactive particle editor](http://pixijs.github.io/pixi-particles-editor/) to design and preview custom particle emitters which utilitze PixiParticles. +## Breaking changes in v3 from v2 +* On `Emitter`, `playOnce()` no longer sets `autoUpdate` to true. Set it manually before use. + `playOnceAndDestroy()` is unaffected. +* On `Emitter`, `start*` and `end*` properties for alpha, color, scale, and speed have been + replaced by a singly linked list of `PropertyNode` objects. +* Dropped support for PIXI v3. Please use v4. +* The library is no longer exported as a node export, only adding itself to the global PIXI namespace. + ## Sample Usage Please see the examples for various pre-made particle configurations. @@ -24,20 +32,56 @@ var emitter = new PIXI.particles.Emitter( // of the emitter { alpha: { - start: 0.8, - end: 0.1 + list: [ + { + value: 0.8, + time: 0 + }, + { + value: 0.1, + time: 1 + } + ], + isStepped: false }, scale: { - start: 1, - end: 0.3 + list: [ + { + value: 1, + time: 0 + }, + { + value: 0.3, + time: 1 + } + ], + isStepped: false }, color: { - start: "fb1010", - end: "f5b830" + list: [ + { + value: "fb1010", + time: 0 + }, + { + value: "f5b830", + time: 1 + } + ], + isStepped: false }, speed: { - start: 200, - end: 100 + list: [ + { + value: 200, + time: 0 + }, + { + value: 100, + time: 1 + } + ], + isStepped: false }, startRotation: { min: 0, @@ -52,6 +96,8 @@ var emitter = new PIXI.particles.Emitter( max: 0.5 }, frequency: 0.008, + spawnChance: 1, + particlesPerWave: 1, emitterLifetime: 0.31, maxParticles: 1000, pos: { diff --git a/ambient.d.ts b/ambient.d.ts index 689434d2..87d736ee 100644 --- a/ambient.d.ts +++ b/ambient.d.ts @@ -1,6 +1,13 @@ // Typings for pixi-particles 2.1.9, requires Pixi.js typings declare namespace PIXI.particles { type TexSrc = string|PIXI.Texture; + type Color = {r:number, g:number, b:number}; + + export interface ValueList { + list: {value:number|string, time:number}[], + isStepped?: boolean; + ease?: (lerp:number)=>number|EaseSegment[]; + } export interface ParticleConstructor { new (emitter:Emitter):Particle; @@ -38,7 +45,6 @@ declare namespace PIXI.particles { private _prevEmitterPos:PIXI.Point; private _prevPosIsValid:boolean; private _posChanged:boolean; - private _parentIsPC:boolean; private _parent:PIXI.Container; private _emit:boolean; private _spawnTimer:number; @@ -53,18 +59,14 @@ declare namespace PIXI.particles { private _completeCallback:()=>void; public particleImages:any[]; - public startAlpha:number; - public endAlpha:number; - public startSpeed:number; - public endSpeed:number; + public startAlpha:PropertyNode; + public startSpeed:PropertyNode; public minimumSpeedMultiplier:number; public acceleration:PIXI.Point; public maxSpeed:number; - public startScale:number; - public endScale:number; + public startScale:PropertyNode; public minimumScaleMultiplier:number; - public startColor:[number, number, number]; - public endColor:[number, number, number]; + public startColor:PropertyNode; public minLifetime:number; public maxLifetime:number; public minStartRotation:number; @@ -89,6 +91,7 @@ declare namespace PIXI.particles { public addAtBack:boolean; public readonly particleCount:number; public frequency:number; + public spawnChance:number; public particleConstructor:ParticleConstructor; public parent:PIXI.Container; public emit:boolean; @@ -116,12 +119,6 @@ declare namespace PIXI.particles { } export class Particle extends PIXI.Sprite { - private _sR:number; - private _sG:number; - private _sB:number; - private _eR:number; - private _eG:number; - private _eB:number; private _doAlpha:boolean; private _doScale:boolean; private _doSpeed:boolean; @@ -138,16 +135,12 @@ declare namespace PIXI.particles { public age:number; public ease:(time:number)=>number; public extraData:any; - public startAlpha:number; - public endAlpha:number; - public startSpeed:number; - public endSpeed:number; + public alphaList:PropertyList; + public speedList:PropertyList; public acceleration:PIXI.Point; public maxSpeed:number; - public startScale:number; - public endScale:number; - public startColor:number[]; - public endColor:number[]; + public scaleList:PropertyList; + public colorList:PropertyList; /** Note that for Particle, the parameter is an array of strings or PIXI.Textures, and an array of Textures is returned. */ public static parseArt(art:any):any; @@ -182,6 +175,7 @@ declare namespace PIXI.particles { public static hexToRGB(color:string, output?:[number, number, number]):[number, number, number]; public static generateEase(segments:EaseSegment[]):(time:number)=>number; public static getBlendMode(name:string):number; + public static createSteppedGradient(list:{value:string, time:number}, numSteps?:number):PropertyNode; } export class PathParticle extends Particle { @@ -193,4 +187,26 @@ declare namespace PIXI.particles { public static parseArt(art:TexSrc[]):PIXI.Texture[]; public static parseData(data:{path:string}):any; } + + export class PropertyList { + public current: PropertyNode; + protected next: PropertyNode; + private isColor: boolean; + private ease: Function; + + constructor(isColor?:boolean); + public interpolate(lerp:number):number; + public reset(first:PropertyNode):void; + } + + export class PropertyNode { + public value: number|Color; + public time: number; + public next: PropertyNode; + public isStepped: boolean; + private interpolate: (lerp:number)=>number; + private ease: (lerp:number)=>number; + + public static createList(data:ValueList):PropertyNode; + } } \ No newline at end of file diff --git a/dist/pixi-particles.js b/dist/pixi-particles.js index 521e3eae..ead95371 100644 --- a/dist/pixi-particles.js +++ b/dist/pixi-particles.js @@ -1,17 +1,25 @@ /*! * pixi-particles - v2.1.9 - * Compiled Thu, 16 Nov 2017 01:52:38 UTC + * Compiled Mon, 12 Feb 2018 03:27:46 UTC * * pixi-particles is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license */ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pixiParticles = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) - { - this.elapsed += delta; - if(this.elapsed > this.duration) - { - //loop elapsed back around - if(this.loop) - this.elapsed = this.elapsed % this.duration; - //subtract a small amount to prevent attempting to go past the end of the animation - else - this.elapsed = this.duration - 0.000001; - } - var frame = (this.elapsed * this.framerate + 0.0000001) | 0; - this.texture = this.textures[frame] || ParticleUtils.EMPTY_TEXTURE; - } -}; - -p.Particle_destroy = Particle.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.AnimatedParticle#destroy - */ -p.destroy = function() -{ - this.Particle_destroy(); - this.textures = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. - * @method PIXI.particles.AnimatedParticle.parseArt - * @static - * @param {Array} art The array of art data, properly formatted for AnimatedParticle. - * @return {Array} The art, after any needed modifications. - */ -AnimatedParticle.parseArt = function(art) -{ - var i, data, output = [], j, textures, tex, outTextures; - for(i = 0; i < art.length; ++i) - { - data = art[i]; - art[i] = output = {}; - output.textures = outTextures = []; - textures = data.textures; - for(j = 0; j < textures.length; ++j) - { - tex = textures[j]; - if(typeof tex == "string") - outTextures.push(Texture.fromImage(tex)); - else if(tex instanceof Texture) - outTextures.push(tex); - //assume an object with extra data determining duplicate frame data - else - { - var dupe = tex.count || 1; - if(typeof tex.texture == "string") - tex = Texture.fromImage(tex.texture); - else// if(tex.texture instanceof Texture) - tex = tex.texture; - for(; dupe > 0; --dupe) - { - outTextures.push(tex); - } - } - } - - //use these values to signify that the animation should match the particle life time. - if(data.framerate == "matchLife") - { - //-1 means that it should be calculated - output.framerate = -1; - output.duration = 0; - output.loop = false; - } - else - { - //determine if the animation should loop - output.loop = !!data.loop; - //get the framerate, default to 60 - output.framerate = data.framerate > 0 ? data.framerate : 60; - //determine the duration - output.duration = outTextures.length / output.framerate; - } - } - - return art; -}; - -module.exports = AnimatedParticle; -},{"./Particle":3,"./ParticleUtils":4}],2:[function(_dereq_,module,exports){ +var AnimatedParticle = /** @class */ (function (_super) { + __extends(AnimatedParticle, _super); + function AnimatedParticle(emitter) { + var _this = _super.call(this, emitter) || this; + _this.textures = null; + _this.duration = 0; + _this.framerate = 0; + _this.elapsed = 0; + _this.loop = false; + return _this; + } + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.AnimatedParticle#init + */ + AnimatedParticle.prototype.init = function () { + this.Particle_init(); + this.elapsed = 0; + //if the animation needs to match the particle's life, then cacluate variables + if (this.framerate < 0) { + this.duration = this.maxLife; + this.framerate = this.textures.length / this.duration; + } + }; + /** + * Sets the textures for the particle. + * @method PIXI.particles.AnimatedParticle#applyArt + * @param {Array} art An array of PIXI.Texture objects for this animated particle. + */ + AnimatedParticle.prototype.applyArt = function (art) { + this.textures = art.textures; + this.framerate = art.framerate; + this.duration = art.duration; + this.loop = art.loop; + }; + /** + * Updates the particle. + * @method PIXI.particles.AnimatedParticle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + AnimatedParticle.prototype.update = function (delta) { + var lerp = this.Particle_update(delta); + //only animate the particle if it is still alive + if (lerp >= 0) { + this.elapsed += delta; + if (this.elapsed > this.duration) { + //loop elapsed back around + if (this.loop) + this.elapsed = this.elapsed % this.duration; + else + this.elapsed = this.duration - 0.000001; + } + var frame = (this.elapsed * this.framerate + 0.0000001) | 0; + this.texture = this.textures[frame] || PIXI.Texture.EMPTY; + } + return lerp; + }; + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.AnimatedParticle#destroy + */ + AnimatedParticle.prototype.destroy = function () { + this.Particle_destroy(); + this.textures = null; + }; + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. + * @method PIXI.particles.AnimatedParticle.parseArt + * @static + * @param {Array} art The array of art data, properly formatted for AnimatedParticle. + * @return {Array} The art, after any needed modifications. + */ + AnimatedParticle.parseArt = function (art) { + var data, output, textures, tex, outTextures; + var outArr = []; + for (var i = 0; i < art.length; ++i) { + data = art[i]; + outArr[i] = output = {}; + output.textures = outTextures = []; + textures = data.textures; + for (var j = 0; j < textures.length; ++j) { + tex = textures[j]; + if (typeof tex == "string") + outTextures.push(Texture.fromImage(tex)); + else if (tex instanceof Texture) + outTextures.push(tex); + else { + var dupe = tex.count || 1; + if (typeof tex.texture == "string") + tex = Texture.fromImage(tex.texture); + else + tex = tex.texture; + for (; dupe > 0; --dupe) { + outTextures.push(tex); + } + } + } + //use these values to signify that the animation should match the particle life time. + if (data.framerate == "matchLife") { + //-1 means that it should be calculated + output.framerate = -1; + output.duration = 0; + output.loop = false; + } + else { + //determine if the animation should loop + output.loop = !!data.loop; + //get the framerate, default to 60 + output.framerate = data.framerate > 0 ? data.framerate : 60; + //determine the duration + output.duration = outTextures.length / output.framerate; + } + } + return outArr; + }; + return AnimatedParticle; +}(Particle_1.default)); +exports.default = AnimatedParticle; + +},{"./Particle":3}],2:[function(_dereq_,module,exports){ "use strict"; - -var ParticleUtils = _dereq_("./ParticleUtils"), - Particle = _dereq_("./Particle"), - ParticleContainer = PIXI.particles.ParticleContainer || PIXI.ParticleContainer, - ticker = PIXI.ticker.shared; - +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_1 = _dereq_("./ParticleUtils"); +var Particle_1 = _dereq_("./Particle"); +var PropertyNode_1 = _dereq_("./PropertyNode"); +var ticker = PIXI.ticker.shared; +var helperPoint = new PIXI.Point(); /** * A particle emitter. * @memberof PIXI.particles @@ -246,1221 +200,805 @@ var ParticleUtils = _dereq_("./ParticleUtils"), * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter * will automatically call update via the PIXI shared ticker. */ -var Emitter = function(particleParent, particleImages, config) -{ - /** - * The constructor used to create new particles. The default is - * the built in particle class. - * @property {Function} _particleConstructor - * @private - */ - this._particleConstructor = Particle; - //properties for individual particles - /** - * An array of PIXI Texture objects. - * @property {Array} particleImages - */ - this.particleImages = null; - /** - * The starting alpha of all particles. - * @property {Number} startAlpha - * @default 1 - */ - this.startAlpha = 1; - /** - * The ending alpha of all particles. - * @property {Number} endAlpha - * @default 1 - */ - this.endAlpha = 1; - /** - * The starting speed of all particles. - * @property {Number} startSpeed - * @default 0 - */ - this.startSpeed = 0; - /** - * The ending speed of all particles. - * @property {Number} endSpeed - * @default 0 - */ - this.endSpeed = 0; - /** - * A minimum multiplier for the speed of a particle at both start and - * end. A value between minimumSpeedMultiplier and 1 is randomly generated - * and multiplied with startSpeed and endSpeed to provide the actual - * startSpeed and endSpeed for each particle. - * @property {Number} minimumSpeedMultiplier - * @default 1 - */ - this.minimumSpeedMultiplier = 1; - /** - * Acceleration to apply to particles. Using this disables - * any interpolation of particle speed. If the particles do - * not have a rotation speed, then they will be rotated to - * match the direction of travel. - * @property {PIXI.Point} acceleration - * @default null - */ - this.acceleration = null; - /** - * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN - * will disable the maximum speed. - * @property {Number} maxSpeed - * @default NaN - */ - this.maxSpeed = NaN; - /** - * The starting scale of all particles. - * @property {Number} startScale - * @default 1 - */ - this.startScale = 1; - /** - * The ending scale of all particles. - * @property {Number} endScale - * @default 1 - */ - this.endScale = 1; - /** - * A minimum multiplier for the scale of a particle at both start and - * end. A value between minimumScaleMultiplier and 1 is randomly generated - * and multiplied with startScale and endScale to provide the actual - * startScale and endScale for each particle. - * @property {Number} minimumScaleMultiplier - * @default 1 - */ - this.minimumScaleMultiplier = 1; - /** - * The starting color of all particles, as red, green, and blue uints from 0-255. - * @property {Array} startColor - */ - this.startColor = null; - /** - * The ending color of all particles, as red, green, and blue uints from 0-255. - * @property {Array} endColor - */ - this.endColor = null; - /** - * The minimum lifetime for a particle, in seconds. - * @property {Number} minLifetime - */ - this.minLifetime = 0; - /** - * The maximum lifetime for a particle, in seconds. - * @property {Number} maxLifetime - */ - this.maxLifetime = 0; - /** - * The minimum start rotation for a particle, in degrees. This value - * is ignored if the spawn type is "burst" or "arc". - * @property {Number} minStartRotation - */ - this.minStartRotation = 0; - /** - * The maximum start rotation for a particle, in degrees. This value - * is ignored if the spawn type is "burst" or "arc". - * @property {Number} maxStartRotation - */ - this.maxStartRotation = 0; - /** - * If no particle rotation should occur. Starting rotation will still - * affect the direction in which particles move. If the rotation speed - * is set, then this will be ignored. - * @property {Boolean} maxStartRotation - */ - this.noRotation = false; - /** - * The minimum rotation speed for a particle, in degrees per second. - * This only visually spins the particle, it does not change direction - * of movement. - * @property {Number} minRotationSpeed - */ - this.minRotationSpeed = 0; - /** - * The maximum rotation speed for a particle, in degrees per second. - * This only visually spins the particle, it does not change direction - * of movement. - * @property {Number} maxRotationSpeed - */ - this.maxRotationSpeed = 0; - /** - * The blend mode for all particles, as named by PIXI.blendModes. - * @property {int} particleBlendMode - */ - this.particleBlendMode = 0; - /** - * An easing function for nonlinear interpolation of values. Accepts a single - * parameter of time as a value from 0-1, inclusive. Expected outputs are values - * from 0-1, inclusive. - * @property {Function} customEase - */ - this.customEase = null; - /** - * Extra data for use in custom particles. The emitter doesn't look inside, but - * passes it on to the particle to use in init(). - * @property {Object} extraData - */ - this.extraData = null; - //properties for spawning particles - /** - * Time between particle spawns in seconds. - * @property {Number} _frequency - * @private - */ - this._frequency = 1; - /** - * Maximum number of particles to keep alive at a time. If this limit - * is reached, no more particles will spawn until some have died. - * @property {int} maxParticles - * @default 1000 - */ - this.maxParticles = 1000; - /** - * The amount of time in seconds to emit for before setting emit to false. - * A value of -1 is an unlimited amount of time. - * @property {Number} emitterLifetime - * @default -1 - */ - this.emitterLifetime = -1; - /** - * Position at which to spawn particles, relative to the emitter's owner's origin. - * For example, the flames of a rocket travelling right might have a spawnPos - * of {x:-50, y:0}. - * to spawn at the rear of the rocket. - * To change this, use updateSpawnPos(). - * @property {PIXI.Point} spawnPos - * @readOnly - */ - this.spawnPos = null; - /** - * How the particles will be spawned. Valid types are "point", "rectangle", - * "circle", "burst", "ring". - * @property {String} spawnType - * @readOnly - */ - this.spawnType = null; - /** - * A reference to the emitter function specific to the spawn type. - * @property {Function} _spawnFunc - * @private - */ - this._spawnFunc = null; - /** - * A rectangle relative to spawnPos to spawn particles inside if the spawn type is "rect". - * @property {PIXI.Rectangle} spawnRect - */ - this.spawnRect = null; - /** - * A circle relative to spawnPos to spawn particles inside if the spawn type is "circle". - * @property {PIXI.Circle} spawnCircle - */ - this.spawnCircle = null; - /** - * Number of particles to spawn each wave in a burst. - * @property {int} particlesPerWave - * @default 1 - */ - this.particlesPerWave = 1; - /** - * Spacing between particles in a burst. 0 gives a random angle for each particle. - * @property {Number} particleSpacing - * @default 0 - */ - this.particleSpacing = 0; - /** - * Angle at which to start spawning particles in a burst. - * @property {Number} angleStart - * @default 0 - */ - this.angleStart = 0; - /** - * Rotation of the emitter or emitter's owner in degrees. This is added to - * the calculated spawn angle. - * To change this, use rotate(). - * @property {Number} rotation - * @default 0 - * @readOnly - */ - this.rotation = 0; - /** - * The world position of the emitter's owner, to add spawnPos to when - * spawning particles. To change this, use updateOwnerPos(). - * @property {PIXI.Point} ownerPos - * @default {x:0, y:0} - * @readOnly - */ - this.ownerPos = null; - /** - * The origin + spawnPos in the previous update, so that the spawn position - * can be interpolated to space out particles better. - * @property {PIXI.Point} _prevEmitterPos - * @private - */ - this._prevEmitterPos = null; - /** - * If _prevEmitterPos is valid, to prevent interpolation on the first update - * @property {Boolean} _prevPosIsValid - * @private - * @default false - */ - this._prevPosIsValid = false; - /** - * If either ownerPos or spawnPos has changed since the previous update. - * @property {Boolean} _posChanged - * @private - */ - this._posChanged = false; - /** - * If the parent is a ParticleContainer from Pixi V3 - * @property {Boolean} _parentIsPC - * @private - */ - this._parentIsPC = false; - /** - * The container to add particles to. - * @property {PIXI.Container} _parent - * @private - */ - this._parent = null; - /** - * If particles should be added at the back of the display list instead of the front. - * @property {Boolean} addAtBack - */ - this.addAtBack = false; - /** - * The current number of active particles. - * @property {Number} particleCount - * @readOnly - */ - this.particleCount = 0; - /** - * If particles should be emitted during update() calls. Setting this to false - * stops new particles from being created, but allows existing ones to die out. - * @property {Boolean} _emit - * @private - */ - this._emit = false; - /** - * The timer for when to spawn particles in seconds, where numbers less - * than 0 mean that particles should be spawned. - * @property {Number} _spawnTimer - * @private - */ - this._spawnTimer = 0; - /** - * The life of the emitter in seconds. - * @property {Number} _emitterLife - * @private - */ - this._emitterLife = -1; - /** - * The particles that are active and on the display list. This is the first particle in a - * linked list. - * @property {Particle} _activeParticlesFirst - * @private - */ - this._activeParticlesFirst = null; - /** - * The particles that are active and on the display list. This is the last particle in a - * linked list. - * @property {Particle} _activeParticlesLast - * @private - */ - this._activeParticlesLast = null; - /** - * The particles that are not currently being used. This is the first particle in a - * linked list. - * @property {Particle} _poolFirst - * @private - */ - this._poolFirst = null; - /** - * The original config object that this emitter was initialized with. - * @property {Object} _origConfig - * @private - */ - this._origConfig = null; - /** - * The original particle image data that this emitter was initialized with. - * @property {PIXI.Texture|Array|String} _origArt - * @private - */ - this._origArt = null; - /** - * If the update function is called automatically from the shared ticker. - * Setting this to false requires calling the update function manually. - * @property {Boolean} _autoUpdate - * @private - */ - this._autoUpdate = false; - /** - * If the emitter should destroy itself when all particles have died out. This is set by - * playOnceAndDestroy(); - * @property {Boolean} _destroyWhenComplete - * @private - */ - this._destroyWhenComplete = false; - /** - * A callback for when all particles have died out. This is set by - * playOnceAndDestroy() or playOnce(); - * @property {Function} _completeCallback - * @private - */ - this._completeCallback = null; - - //set the initial parent - this.parent = particleParent; - - if(particleImages && config) - this.init(particleImages, config); - - //save often used functions on the instance instead of the prototype for better speed - this.recycle = this.recycle; - this.update = this.update; - this.rotate = this.rotate; - this.updateSpawnPos = this.updateSpawnPos; - this.updateOwnerPos = this.updateOwnerPos; -}; - -// Reference to the prototype -var p = Emitter.prototype = {}; - -var helperPoint = new PIXI.Point(); - -/** - * Time between particle spawns in seconds. If this value is not a number greater than 0, - * it will be set to 1 (particle per second) to prevent infinite loops. - * @member {Number} PIXI.particles.Emitter#frequency - */ -Object.defineProperty(p, "frequency", -{ - get: function() { return this._frequency; }, - set: function(value) - { - //do some error checking to prevent infinite loops - if(typeof value == "number" && value > 0) - this._frequency = value; - else - this._frequency = 1; - } -}); - -/** - * The constructor used to create new particles. The default is - * the built in Particle class. Setting this will dump any active or - * pooled particles, if the emitter has already been used. - * @member {Function} PIXI.particles.Emitter#particleConstructor - */ -Object.defineProperty(p, "particleConstructor", -{ - get: function() { return this._particleConstructor; }, - set: function(value) - { - if(value != this._particleConstructor) - { - this._particleConstructor = value; - //clean up existing particles - this.cleanup(); - //scrap all the particles - for (var particle = this._poolFirst; particle; particle = particle.next) - { - particle.destroy(); - } - this._poolFirst = null; - //re-initialize the emitter so that the new constructor can do anything it needs to - if(this._origConfig && this._origArt) - this.init(this._origArt, this._origConfig); - } - } -}); - -/** -* The container to add particles to. Settings this will dump any active particles. -* @member {PIXI.Container} PIXI.particles.Emitter#parent -*/ -Object.defineProperty(p, "parent", -{ - get: function() { return this._parent; }, - set: function(value) - { - //if our previous parent was a ParticleContainer, then we need to remove - //pooled particles from it - if (this._parentIsPC) { - for (var particle = this._poolFirst; particle; particle = particle.next) - { - if(particle.parent) - particle.parent.removeChild(particle); - } - } - this.cleanup(); - this._parent = value; - this._parentIsPC = ParticleContainer && value && value instanceof ParticleContainer; - } -}); - -/** - * Sets up the emitter based on the config settings. - * @method PIXI.particles.Emitter#init - * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles. - * @param {Object} config A configuration object containing settings for the emitter. - */ -p.init = function(art, config) -{ - if(!art || !config) - return; - //clean up any existing particles - this.cleanup(); - - //store the original config and particle images, in case we need to re-initialize - //when the particle constructor is changed - this._origConfig = config; - this._origArt = art; - - //set up the array of data, also ensuring that it is an array - art = Array.isArray(art) ? art.slice() : [art]; - //run the art through the particle class's parsing function - var partClass = this._particleConstructor; - this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art; - /////////////////////////// - // Particle Properties // - /////////////////////////// - //set up the alpha - if (config.alpha) - { - this.startAlpha = config.alpha.start; - this.endAlpha = config.alpha.end; - } - else - this.startAlpha = this.endAlpha = 1; - //set up the speed - if (config.speed) - { - this.startSpeed = config.speed.start; - this.endSpeed = config.speed.end; - this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1; - } - else - { - this.minimumSpeedMultiplier = 1; - this.startSpeed = this.endSpeed = 0; - } - //set up acceleration - var acceleration = config.acceleration; - if(acceleration && (acceleration.x || acceleration.y)) - { - this.endSpeed = this.startSpeed; - this.acceleration = new PIXI.Point(acceleration.x, acceleration.y); - this.maxSpeed = config.maxSpeed || NaN; - } - else - this.acceleration = new PIXI.Point(); - //set up the scale - if (config.scale) - { - this.startScale = config.scale.start; - this.endScale = config.scale.end; - this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1; - } - else - this.startScale = this.endScale = this.minimumScaleMultiplier = 1; - //set up the color - if (config.color) - { - this.startColor = ParticleUtils.hexToRGB(config.color.start); - //if it's just one color, only use the start color - if (config.color.start != config.color.end) - { - this.endColor = ParticleUtils.hexToRGB(config.color.end); - } - else - this.endColor = null; - } - //set up the start rotation - if (config.startRotation) - { - this.minStartRotation = config.startRotation.min; - this.maxStartRotation = config.startRotation.max; - } - else - this.minStartRotation = this.maxStartRotation = 0; - if (config.noRotation && - (this.minStartRotation || this.maxStartRotation)) - { - this.noRotation = !!config.noRotation; - } - else - this.noRotation = false; - //set up the rotation speed - if (config.rotationSpeed) - { - this.minRotationSpeed = config.rotationSpeed.min; - this.maxRotationSpeed = config.rotationSpeed.max; - } - else - this.minRotationSpeed = this.maxRotationSpeed = 0; - //set up the lifetime - this.minLifetime = config.lifetime.min; - this.maxLifetime = config.lifetime.max; - //get the blend mode - this.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode); - //use the custom ease if provided - if (config.ease) - { - this.customEase = typeof config.ease == "function" ? - config.ease : - ParticleUtils.generateEase(config.ease); - } - else - this.customEase = null; - //set up the extra data, running it through the particle class's parseData function. - if(partClass.parseData) - this.extraData = partClass.parseData(config.extraData); - else - this.extraData = config.extraData || null; - ////////////////////////// - // Emitter Properties // - ////////////////////////// - //reset spawn type specific settings - this.spawnRect = this.spawnCircle = null; - this.particlesPerWave = 1; - this.particleSpacing = 0; - this.angleStart = 0; - var spawnCircle; - //determine the spawn function to use - switch(config.spawnType) - { - case "rect": - this.spawnType = "rect"; - this._spawnFunc = this._spawnRect; - var spawnRect = config.spawnRect; - this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h); - break; - case "circle": - this.spawnType = "circle"; - this._spawnFunc = this._spawnCircle; - spawnCircle = config.spawnCircle; - this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); - break; - case "ring": - this.spawnType = "ring"; - this._spawnFunc = this._spawnRing; - spawnCircle = config.spawnCircle; - this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); - this.spawnCircle.minRadius = spawnCircle.minR; - break; - case "burst": - this.spawnType = "burst"; - this._spawnFunc = this._spawnBurst; - this.particlesPerWave = config.particlesPerWave; - this.particleSpacing = config.particleSpacing; - this.angleStart = config.angleStart ? config.angleStart : 0; - break; - case "point": - this.spawnType = "point"; - this._spawnFunc = this._spawnPoint; - break; - default: - this.spawnType = "point"; - this._spawnFunc = this._spawnPoint; - break; - } - //set the spawning frequency - this.frequency = config.frequency; - //set the emitter lifetime - this.emitterLifetime = config.emitterLifetime || -1; - //set the max particles - this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000; - //determine if we should add the particle at the back of the list or not - this.addAtBack = !!config.addAtBack; - //reset the emitter position and rotation variables - this.rotation = 0; - this.ownerPos = new PIXI.Point(); - this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y); - this._prevEmitterPos = this.spawnPos.clone(); - //previous emitter position is invalid and should not be used for interpolation - this._prevPosIsValid = false; - //start emitting - this._spawnTimer = 0; - this.emit = config.emit === undefined ? true : !!config.emit; - this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate; -}; - -/** - * Recycles an individual particle. - * @method PIXI.particles.Emitter#recycle - * @param {Particle} particle The particle to recycle. - * @private - */ -p.recycle = function(particle) -{ - if(particle.next) - particle.next.prev = particle.prev; - if(particle.prev) - particle.prev.next = particle.next; - if(particle == this._activeParticlesLast) - this._activeParticlesLast = particle.prev; - if(particle == this._activeParticlesFirst) - this._activeParticlesFirst = particle.next; - //add to pool - particle.prev = null; - particle.next = this._poolFirst; - this._poolFirst = particle; - //remove child from display, or make it invisible if it is in a ParticleContainer - if(this._parentIsPC) - { - particle.alpha = 0; - particle.visible = false; - } - else - { - if(particle.parent) - particle.parent.removeChild(particle); - } - //decrease count - --this.particleCount; -}; - -/** - * Sets the rotation of the emitter to a new value. - * @method PIXI.particles.Emitter#rotate - * @param {Number} newRot The new rotation, in degrees. - */ -p.rotate = function(newRot) -{ - if (this.rotation == newRot) return; - //caclulate the difference in rotation for rotating spawnPos - var diff = newRot - this.rotation; - this.rotation = newRot; - //rotate spawnPos - ParticleUtils.rotatePoint(diff, this.spawnPos); - //mark the position as having changed - this._posChanged = true; -}; - -/** - * Changes the spawn position of the emitter. - * @method PIXI.particles.Emitter#updateSpawnPos - * @param {Number} x The new x value of the spawn position for the emitter. - * @param {Number} y The new y value of the spawn position for the emitter. - */ -p.updateSpawnPos = function(x, y) -{ - this._posChanged = true; - this.spawnPos.x = x; - this.spawnPos.y = y; -}; - -/** - * Changes the position of the emitter's owner. You should call this if you are adding - * particles to the world container that your emitter's owner is moving around in. - * @method PIXI.particles.Emitter#updateOwnerPos - * @param {Number} x The new x value of the emitter's owner. - * @param {Number} y The new y value of the emitter's owner. - */ -p.updateOwnerPos = function(x, y) -{ - this._posChanged = true; - this.ownerPos.x = x; - this.ownerPos.y = y; -}; - -/** - * Prevents emitter position interpolation in the next update. - * This should be used if you made a major position change of your emitter's owner - * that was not normal movement. - * @method PIXI.particles.Emitter#resetPositionTracking - */ -p.resetPositionTracking = function() -{ - this._prevPosIsValid = false; -}; - -/** - * If particles should be emitted during update() calls. Setting this to false - * stops new particles from being created, but allows existing ones to die out. - * @member {Boolean} PIXI.particles.Emitter#emit - */ -Object.defineProperty(p, "emit", -{ - get: function() { return this._emit; }, - set: function(value) - { - this._emit = !!value; - this._emitterLife = this.emitterLifetime; - } -}); - -/** - * If the update function is called automatically from the shared ticker. - * Setting this to false requires calling the update function manually. - * @member {Boolean} PIXI.particles.Emitter#autoUpdate - */ -Object.defineProperty(p, "autoUpdate", -{ - get: function() { return this._autoUpdate; }, - set: function(value) - { - if (this._autoUpdate && !value) - { - ticker.remove(this.update, this); - } - else if (!this._autoUpdate && value) - { - ticker.add(this.update, this); - } - this._autoUpdate = !!value; - } -}); - -/** - * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself - * when particle emission is complete. - * @method PIXI.particles.Emitter#playOnceAndDestroy - * @param {Function} [callback] Callback for when emission is complete (all particles have died off) - */ -p.playOnceAndDestroy = function(callback) -{ - this.autoUpdate = true; - this.emit = true; - this._destroyWhenComplete = true; - this._completeCallback = callback; -}; - -/** - * Starts emitting particles, sets autoUpdate to true, and optionally calls a callback - * when particle emission is complete. - * @method PIXI.particles.Emitter#playOnce - * @param {Function} [callback] Callback for when emission is complete (all particles have died off) - */ -p.playOnce = function(callback) -{ - this.autoUpdate = true; - this.emit = true; - this._completeCallback = callback; -}; - -/** - * Updates all particles spawned by this emitter and emits new ones. - * @method PIXI.particles.Emitter#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - */ -p.update = function(delta) -{ - if (this._autoUpdate) - { - delta = delta / PIXI.settings.TARGET_FPMS / 1000; - } - - //if we don't have a parent to add particles to, then don't do anything. - //this also works as a isDestroyed check - if (!this._parent) return; - //update existing particles - var i, particle, next; - for (particle = this._activeParticlesFirst; particle; particle = next) - { - next = particle.next; - particle.update(delta); - } - var prevX, prevY; - //if the previous position is valid, store these for later interpolation - if(this._prevPosIsValid) - { - prevX = this._prevEmitterPos.x; - prevY = this._prevEmitterPos.y; - } - //store current position of the emitter as local variables - var curX = this.ownerPos.x + this.spawnPos.x; - var curY = this.ownerPos.y + this.spawnPos.y; - //spawn new particles - if (this._emit) - { - //decrease spawn timer - this._spawnTimer -= delta; - //while _spawnTimer < 0, we have particles to spawn - while(this._spawnTimer <= 0) - { - //determine if the emitter should stop spawning - if(this._emitterLife > 0) - { - this._emitterLife -= this._frequency; - if(this._emitterLife <= 0) - { - this._spawnTimer = 0; - this._emitterLife = 0; - this.emit = false; - break; - } - } - //determine if we have hit the particle limit - if(this.particleCount >= this.maxParticles) - { - this._spawnTimer += this._frequency; - continue; - } - //determine the particle lifetime - var lifetime; - if (this.minLifetime == this.maxLifetime) - lifetime = this.minLifetime; - else - lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime; - //only make the particle if it wouldn't immediately destroy itself - if(-this._spawnTimer < lifetime) - { - //If the position has changed and this isn't the first spawn, - //interpolate the spawn position - var emitPosX, emitPosY; - if (this._prevPosIsValid && this._posChanged) - { - //1 - _spawnTimer / delta, but _spawnTimer is negative - var lerp = 1 + this._spawnTimer / delta; - emitPosX = (curX - prevX) * lerp + prevX; - emitPosY = (curY - prevY) * lerp + prevY; - } - else//otherwise just set to the spawn position - { - emitPosX = curX; - emitPosY = curY; - } - //create enough particles to fill the wave (non-burst types have a wave of 1) - i = 0; - for(var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) - { - //create particle - var p, rand; - if(this._poolFirst) - { - p = this._poolFirst; - this._poolFirst = this._poolFirst.next; - p.next = null; - } - else - { - p = new this.particleConstructor(this); - } - - //set a random texture if we have more than one - if(this.particleImages.length > 1) - { - p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]); - } - else - { - //if they are actually the same texture, a standard particle - //will quit early from the texture setting in setTexture(). - p.applyArt(this.particleImages[0]); - } - //set up the start and end values - p.startAlpha = this.startAlpha; - p.endAlpha = this.endAlpha; - if(this.minimumSpeedMultiplier != 1) - { - rand = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier; - p.startSpeed = this.startSpeed * rand; - p.endSpeed = this.endSpeed * rand; - } - else - { - p.startSpeed = this.startSpeed; - p.endSpeed = this.endSpeed; - } - p.acceleration.x = this.acceleration.x; - p.acceleration.y = this.acceleration.y; - p.maxSpeed = this.maxSpeed; - if(this.minimumScaleMultiplier != 1) - { - rand = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier; - p.startScale = this.startScale * rand; - p.endScale = this.endScale * rand; - } - else - { - p.startScale = this.startScale; - p.endScale = this.endScale; - } - p.startColor = this.startColor; - p.endColor = this.endColor; - //randomize the rotation speed - if(this.minRotationSpeed == this.maxRotationSpeed) - p.rotationSpeed = this.minRotationSpeed; - else - p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed; - p.noRotation = this.noRotation; - //set up the lifetime - p.maxLife = lifetime; - //set the blend mode - p.blendMode = this.particleBlendMode; - //set the custom ease, if any - p.ease = this.customEase; - //set the extra data, if any - p.extraData = this.extraData; - //call the proper function to handle rotation and position of particle - this._spawnFunc(p, emitPosX, emitPosY, i); - //initialize particle - p.init(); - //update the particle by the time passed, so the particles are spread out properly - p.update(-this._spawnTimer);//we want a positive delta, because a negative delta messes things up - //add the particle to the display list - if(!this._parentIsPC || !p.parent) - { - if (this.addAtBack) - this._parent.addChildAt(p, 0); - else - this._parent.addChild(p); - } - else - { - //kind of hacky, but performance friendly - //shuffle children to correct place - var children = this._parent.children; - //avoid using splice if possible - if(children[0] == p) - children.shift(); - else if(children[children.length-1] == p) - children.pop(); - else - { - var index = children.indexOf(p); - children.splice(index, 1); - } - if(this.addAtBack) - children.unshift(p); - else - children.push(p); - } - //add particle to list of active particles - if(this._activeParticlesLast) - { - this._activeParticlesLast.next = p; - p.prev = this._activeParticlesLast; - this._activeParticlesLast = p; - } - else - { - this._activeParticlesLast = this._activeParticlesFirst = p; - } - ++this.particleCount; - } - } - //increase timer and continue on to any other particles that need to be created - this._spawnTimer += this._frequency; - } - } - //if the position changed before this update, then keep track of that - if(this._posChanged) - { - this._prevEmitterPos.x = curX; - this._prevEmitterPos.y = curY; - this._prevPosIsValid = true; - this._posChanged = false; - } - - //if we are all done and should destroy ourselves, take care of that - if (!this._emit && !this._activeParticlesFirst) - { - if (this._completeCallback) - { - this._completeCallback(); - } - if (this._destroyWhenComplete) - { - this.destroy(); - } - } -}; - -/** - * Positions a particle for a point type emitter. - * @method PIXI.particles.Emitter#_spawnPoint - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnPoint = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on - //starting particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; - //drop the particle at the emitter's position - p.position.x = emitPosX; - p.position.y = emitPosY; -}; - -/** - * Positions a particle for a rectangle type emitter. - * @method PIXI.particles.Emitter#_spawnRect - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnRect = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; - //place the particle at a random point in the rectangle - helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x; - helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y; - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a circle type emitter. - * @method PIXI.particles.Emitter#_spawnCircle - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnCircle = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + - this.minStartRotation + this.rotation; - //place the particle at a random radius in the circle - helperPoint.x = Math.random() * this.spawnCircle.radius; - helperPoint.y = 0; - //rotate the point to a random angle in the circle - ParticleUtils.rotatePoint(Math.random() * 360, helperPoint); - //offset by the circle's center - helperPoint.x += this.spawnCircle.x; - helperPoint.y += this.spawnCircle.y; - //rotate the point by the emitter's rotation - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - //set the position, offset by the emitter's position - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a ring type emitter. - * @method PIXI.particles.Emitter#_spawnRing - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnRing = function(p, emitPosX, emitPosY) -{ - var spawnCircle = this.spawnCircle; - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + - this.minStartRotation + this.rotation; - //place the particle at a random radius in the ring - if(spawnCircle.minRadius == spawnCircle.radius) - { - helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) + - spawnCircle.minRadius; - } - else - helperPoint.x = spawnCircle.radius; - helperPoint.y = 0; - //rotate the point to a random angle in the circle - var angle = Math.random() * 360; - p.rotation += angle; - ParticleUtils.rotatePoint(angle, helperPoint); - //offset by the circle's center - helperPoint.x += this.spawnCircle.x; - helperPoint.y += this.spawnCircle.y; - //rotate the point by the emitter's rotation - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - //set the position, offset by the emitter's position - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a burst type emitter. - * @method PIXI.particles.Emitter#_spawnBurst - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. - */ -p._spawnBurst = function(p, emitPosX, emitPosY, i) -{ - //set the initial rotation/direction of the particle based on spawn - //angle and rotation of emitter - if(this.particleSpacing === 0) - p.rotation = Math.random() * 360; - else - p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation; - //drop the particle at the emitter's position - p.position.x = emitPosX; - p.position.y = emitPosY; -}; - -/** - * Kills all active particles immediately. - * @method PIXI.particles.Emitter#cleanup - */ -p.cleanup = function() -{ - var particle, next; - for (particle = this._activeParticlesFirst; particle; particle = next) - { - next = particle.next; - this.recycle(particle); - if(particle.parent) - particle.parent.removeChild(particle); - } - this._activeParticlesFirst = this._activeParticlesLast = null; - this.particleCount = 0; -}; - -/** - * Destroys the emitter and all of its particles. - * @method PIXI.particles.Emitter#destroy - */ -p.destroy = function() -{ - //make sure we aren't still listening to any tickers - this.autoUpdate = false; - //puts all active particles in the pool, and removes them from the particle parent - this.cleanup(); - //wipe the pool clean - var next; - for (var particle = this._poolFirst; particle; particle = next) - { - //store next value so we don't lose it in our destroy call - next = particle.next; - particle.destroy(); - } - this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos = - this.startColor = this.endColor = this.customEase = this._completeCallback = null; -}; - -module.exports = Emitter; -},{"./Particle":3,"./ParticleUtils":4}],3:[function(_dereq_,module,exports){ -var ParticleUtils = _dereq_("./ParticleUtils"); +var Emitter = /** @class */ (function () { + function Emitter(particleParent, particleImages, config) { + this._particleConstructor = Particle_1.default; + //properties for individual particles + this.particleImages = null; + this.startAlpha = null; + this.startSpeed = null; + this.minimumSpeedMultiplier = 1; + this.acceleration = null; + this.maxSpeed = NaN; + this.startScale = null; + this.minimumScaleMultiplier = 1; + this.startColor = null; + this.minLifetime = 0; + this.maxLifetime = 0; + this.minStartRotation = 0; + this.maxStartRotation = 0; + this.noRotation = false; + this.minRotationSpeed = 0; + this.maxRotationSpeed = 0; + this.particleBlendMode = 0; + this.customEase = null; + this.extraData = null; + //properties for spawning particles + this._frequency = 1; + this.spawnChance = 1; + this.maxParticles = 1000; + this.emitterLifetime = -1; + this.spawnPos = null; + this.spawnType = null; + this._spawnFunc = null; + this.spawnRect = null; + this.spawnCircle = null; + this.particlesPerWave = 1; + this.particleSpacing = 0; + this.angleStart = 0; + //emitter properties + this.rotation = 0; + this.ownerPos = null; + this._prevEmitterPos = null; + this._prevPosIsValid = false; + this._posChanged = false; + this._parent = null; + this.addAtBack = false; + this.particleCount = 0; + this._emit = false; + this._spawnTimer = 0; + this._emitterLife = -1; + this._activeParticlesFirst = null; + this._activeParticlesLast = null; + this._poolFirst = null; + this._origConfig = null; + this._origArt = null; + this._autoUpdate = false; + this._destroyWhenComplete = false; + this._completeCallback = null; + //set the initial parent + this.parent = particleParent; + if (particleImages && config) + this.init(particleImages, config); + //save often used functions on the instance instead of the prototype for better speed + this.recycle = this.recycle; + this.update = this.update; + this.rotate = this.rotate; + this.updateSpawnPos = this.updateSpawnPos; + this.updateOwnerPos = this.updateOwnerPos; + } + Object.defineProperty(Emitter.prototype, "frequency", { + /** + * Time between particle spawns in seconds. If this value is not a number greater than 0, + * it will be set to 1 (particle per second) to prevent infinite loops. + * @member {Number} PIXI.particles.Emitter#frequency + */ + get: function () { return this._frequency; }, + set: function (value) { + //do some error checking to prevent infinite loops + if (typeof value == "number" && value > 0) + this._frequency = value; + else + this._frequency = 1; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Emitter.prototype, "particleConstructor", { + /** + * The constructor used to create new particles. The default is + * the built in Particle class. Setting this will dump any active or + * pooled particles, if the emitter has already been used. + * @member {Function} PIXI.particles.Emitter#particleConstructor + */ + get: function () { return this._particleConstructor; }, + set: function (value) { + if (value != this._particleConstructor) { + this._particleConstructor = value; + //clean up existing particles + this.cleanup(); + //scrap all the particles + for (var particle = this._poolFirst; particle; particle = particle.next) { + particle.destroy(); + } + this._poolFirst = null; + //re-initialize the emitter so that the new constructor can do anything it needs to + if (this._origConfig && this._origArt) + this.init(this._origArt, this._origConfig); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Emitter.prototype, "parent", { + /** + * The container to add particles to. Settings this will dump any active particles. + * @member {PIXI.Container} PIXI.particles.Emitter#parent + */ + get: function () { return this._parent; }, + set: function (value) { + this.cleanup(); + this._parent = value; + }, + enumerable: true, + configurable: true + }); + /** + * Sets up the emitter based on the config settings. + * @method PIXI.particles.Emitter#init + * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles. + * @param {Object} config A configuration object containing settings for the emitter. + */ + Emitter.prototype.init = function (art, config) { + if (!art || !config) + return; + //clean up any existing particles + this.cleanup(); + //store the original config and particle images, in case we need to re-initialize + //when the particle constructor is changed + this._origConfig = config; + this._origArt = art; + //set up the array of data, also ensuring that it is an array + art = Array.isArray(art) ? art.slice() : [art]; + //run the art through the particle class's parsing function + var partClass = this._particleConstructor; + this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art; + /////////////////////////// + // Particle Properties // + /////////////////////////// + //set up the alpha + if (config.alpha) { + this.startAlpha = PropertyNode_1.default.createList(config.alpha); + } + else + this.startAlpha = new PropertyNode_1.default(1, 0); + //set up the speed + if (config.speed) { + this.startSpeed = PropertyNode_1.default.createList(config.speed); + this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1; + } + else { + this.minimumSpeedMultiplier = 1; + this.startSpeed = new PropertyNode_1.default(0, 0); + } + //set up acceleration + var acceleration = config.acceleration; + if (acceleration && (acceleration.x || acceleration.y)) { + //make sure we disable speed interpolation + this.startSpeed.next = null; + this.acceleration = new PIXI.Point(acceleration.x, acceleration.y); + this.maxSpeed = config.maxSpeed || NaN; + } + else + this.acceleration = new PIXI.Point(); + //set up the scale + if (config.scale) { + this.startScale = PropertyNode_1.default.createList(config.scale); + this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1; + } + else { + this.startScale = new PropertyNode_1.default(1, 0); + this.minimumScaleMultiplier = 1; + } + //set up the color + if (config.color) { + this.startColor = PropertyNode_1.default.createList(config.color); + } + else { + this.startColor = new PropertyNode_1.default({ r: 0xFF, g: 0xFF, b: 0xFF }, 0); + } + //set up the start rotation + if (config.startRotation) { + this.minStartRotation = config.startRotation.min; + this.maxStartRotation = config.startRotation.max; + } + else + this.minStartRotation = this.maxStartRotation = 0; + if (config.noRotation && + (this.minStartRotation || this.maxStartRotation)) { + this.noRotation = !!config.noRotation; + } + else + this.noRotation = false; + //set up the rotation speed + if (config.rotationSpeed) { + this.minRotationSpeed = config.rotationSpeed.min; + this.maxRotationSpeed = config.rotationSpeed.max; + } + else + this.minRotationSpeed = this.maxRotationSpeed = 0; + //set up the lifetime + this.minLifetime = config.lifetime.min; + this.maxLifetime = config.lifetime.max; + //get the blend mode + this.particleBlendMode = ParticleUtils_1.default.getBlendMode(config.blendMode); + //use the custom ease if provided + if (config.ease) { + this.customEase = typeof config.ease == "function" ? + config.ease : + ParticleUtils_1.default.generateEase(config.ease); + } + else + this.customEase = null; + //set up the extra data, running it through the particle class's parseData function. + if (partClass.parseData) + this.extraData = partClass.parseData(config.extraData); + else + this.extraData = config.extraData || null; + ////////////////////////// + // Emitter Properties // + ////////////////////////// + //reset spawn type specific settings + this.spawnRect = this.spawnCircle = null; + this.particlesPerWave = 1; + if (config.particlesPerWave && config.particlesPerWave > 1) + this.particlesPerWave = config.particlesPerWave; + this.particleSpacing = 0; + this.angleStart = 0; + var spawnCircle; + //determine the spawn function to use + switch (config.spawnType) { + case "rect": + this.spawnType = "rect"; + this._spawnFunc = this._spawnRect; + var spawnRect = config.spawnRect; + this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h); + break; + case "circle": + this.spawnType = "circle"; + this._spawnFunc = this._spawnCircle; + spawnCircle = config.spawnCircle; + this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); + break; + case "ring": + this.spawnType = "ring"; + this._spawnFunc = this._spawnRing; + spawnCircle = config.spawnCircle; + this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); + this.spawnCircle.minRadius = spawnCircle.minR; + break; + case "burst": + this.spawnType = "burst"; + this._spawnFunc = this._spawnBurst; + this.particleSpacing = config.particleSpacing; + this.angleStart = config.angleStart ? config.angleStart : 0; + break; + case "point": + this.spawnType = "point"; + this._spawnFunc = this._spawnPoint; + break; + default: + this.spawnType = "point"; + this._spawnFunc = this._spawnPoint; + break; + } + //set the spawning frequency + this.frequency = config.frequency; + this.spawnChance = (typeof config.spawnChance === 'number' && config.spawnChance > 0) ? config.spawnChance : 1; + //set the emitter lifetime + this.emitterLifetime = config.emitterLifetime || -1; + //set the max particles + this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000; + //determine if we should add the particle at the back of the list or not + this.addAtBack = !!config.addAtBack; + //reset the emitter position and rotation variables + this.rotation = 0; + this.ownerPos = new PIXI.Point(); + this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y); + this._prevEmitterPos = this.spawnPos.clone(); + //previous emitter position is invalid and should not be used for interpolation + this._prevPosIsValid = false; + //start emitting + this._spawnTimer = 0; + this.emit = config.emit === undefined ? true : !!config.emit; + this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate; + }; + /** + * Recycles an individual particle. + * @method PIXI.particles.Emitter#recycle + * @param {Particle} particle The particle to recycle. + * @private + */ + Emitter.prototype.recycle = function (particle) { + if (particle.next) + particle.next.prev = particle.prev; + if (particle.prev) + particle.prev.next = particle.next; + if (particle == this._activeParticlesLast) + this._activeParticlesLast = particle.prev; + if (particle == this._activeParticlesFirst) + this._activeParticlesFirst = particle.next; + //add to pool + particle.prev = null; + particle.next = this._poolFirst; + this._poolFirst = particle; + //remove child from display, or make it invisible if it is in a ParticleContainer + if (particle.parent) + particle.parent.removeChild(particle); + //decrease count + --this.particleCount; + }; + /** + * Sets the rotation of the emitter to a new value. + * @method PIXI.particles.Emitter#rotate + * @param {Number} newRot The new rotation, in degrees. + */ + Emitter.prototype.rotate = function (newRot) { + if (this.rotation == newRot) + return; + //caclulate the difference in rotation for rotating spawnPos + var diff = newRot - this.rotation; + this.rotation = newRot; + //rotate spawnPos + ParticleUtils_1.default.rotatePoint(diff, this.spawnPos); + //mark the position as having changed + this._posChanged = true; + }; + /** + * Changes the spawn position of the emitter. + * @method PIXI.particles.Emitter#updateSpawnPos + * @param {Number} x The new x value of the spawn position for the emitter. + * @param {Number} y The new y value of the spawn position for the emitter. + */ + Emitter.prototype.updateSpawnPos = function (x, y) { + this._posChanged = true; + this.spawnPos.x = x; + this.spawnPos.y = y; + }; + /** + * Changes the position of the emitter's owner. You should call this if you are adding + * particles to the world container that your emitter's owner is moving around in. + * @method PIXI.particles.Emitter#updateOwnerPos + * @param {Number} x The new x value of the emitter's owner. + * @param {Number} y The new y value of the emitter's owner. + */ + Emitter.prototype.updateOwnerPos = function (x, y) { + this._posChanged = true; + this.ownerPos.x = x; + this.ownerPos.y = y; + }; + /** + * Prevents emitter position interpolation in the next update. + * This should be used if you made a major position change of your emitter's owner + * that was not normal movement. + * @method PIXI.particles.Emitter#resetPositionTracking + */ + Emitter.prototype.resetPositionTracking = function () { + this._prevPosIsValid = false; + }; + Object.defineProperty(Emitter.prototype, "emit", { + /** + * If particles should be emitted during update() calls. Setting this to false + * stops new particles from being created, but allows existing ones to die out. + * @member {Boolean} PIXI.particles.Emitter#emit + */ + get: function () { return this._emit; }, + set: function (value) { + this._emit = !!value; + this._emitterLife = this.emitterLifetime; + }, + enumerable: true, + configurable: true + }); + ; + Object.defineProperty(Emitter.prototype, "autoUpdate", { + /** + * If the update function is called automatically from the shared ticker. + * Setting this to false requires calling the update function manually. + * @member {Boolean} PIXI.particles.Emitter#autoUpdate + */ + get: function () { return this._autoUpdate; }, + set: function (value) { + if (this._autoUpdate && !value) { + ticker.remove(this.update, this); + } + else if (!this._autoUpdate && value) { + ticker.add(this.update, this); + } + this._autoUpdate = !!value; + }, + enumerable: true, + configurable: true + }); + /** + * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself + * when particle emission is complete. + * @method PIXI.particles.Emitter#playOnceAndDestroy + * @param {Function} [callback] Callback for when emission is complete (all particles have died off) + */ + Emitter.prototype.playOnceAndDestroy = function (callback) { + this.autoUpdate = true; + this.emit = true; + this._destroyWhenComplete = true; + this._completeCallback = callback; + }; + /** + * Starts emitting particles and optionally calls a callback when particle emission is complete. + * @method PIXI.particles.Emitter#playOnce + * @param {Function} [callback] Callback for when emission is complete (all particles have died off) + */ + Emitter.prototype.playOnce = function (callback) { + this.emit = true; + this._completeCallback = callback; + }; + /** + * Updates all particles spawned by this emitter and emits new ones. + * @method PIXI.particles.Emitter#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + Emitter.prototype.update = function (delta) { + if (this._autoUpdate) { + delta = delta / PIXI.settings.TARGET_FPMS / 1000; + } + //if we don't have a parent to add particles to, then don't do anything. + //this also works as a isDestroyed check + if (!this._parent) + return; + //update existing particles + var i, particle, next; + for (particle = this._activeParticlesFirst; particle; particle = next) { + next = particle.next; + particle.update(delta); + } + var prevX, prevY; + //if the previous position is valid, store these for later interpolation + if (this._prevPosIsValid) { + prevX = this._prevEmitterPos.x; + prevY = this._prevEmitterPos.y; + } + //store current position of the emitter as local variables + var curX = this.ownerPos.x + this.spawnPos.x; + var curY = this.ownerPos.y + this.spawnPos.y; + //spawn new particles + if (this._emit) { + //decrease spawn timer + this._spawnTimer -= delta; + //while _spawnTimer < 0, we have particles to spawn + while (this._spawnTimer <= 0) { + //determine if the emitter should stop spawning + if (this._emitterLife > 0) { + this._emitterLife -= this._frequency; + if (this._emitterLife <= 0) { + this._spawnTimer = 0; + this._emitterLife = 0; + this.emit = false; + break; + } + } + //determine if we have hit the particle limit + if (this.particleCount >= this.maxParticles) { + this._spawnTimer += this._frequency; + continue; + } + //determine the particle lifetime + var lifetime = void 0; + if (this.minLifetime == this.maxLifetime) + lifetime = this.minLifetime; + else + lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime; + //only make the particle if it wouldn't immediately destroy itself + if (-this._spawnTimer < lifetime) { + //If the position has changed and this isn't the first spawn, + //interpolate the spawn position + var emitPosX = void 0, emitPosY = void 0; + if (this._prevPosIsValid && this._posChanged) { + //1 - _spawnTimer / delta, but _spawnTimer is negative + var lerp = 1 + this._spawnTimer / delta; + emitPosX = (curX - prevX) * lerp + prevX; + emitPosY = (curY - prevY) * lerp + prevY; + } + else { + emitPosX = curX; + emitPosY = curY; + } + //create enough particles to fill the wave (non-burst types have a wave of 1) + i = 0; + for (var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) { + //see if we actually spawn one + if (this.spawnChance < 1 && Math.random() >= this.spawnChance) + continue; + //create particle + var p = void 0; + if (this._poolFirst) { + p = this._poolFirst; + this._poolFirst = this._poolFirst.next; + p.next = null; + } + else { + p = new this.particleConstructor(this); + } + //set a random texture if we have more than one + if (this.particleImages.length > 1) { + p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]); + } + else { + //if they are actually the same texture, a standard particle + //will quit early from the texture setting in setTexture(). + p.applyArt(this.particleImages[0]); + } + //set up the start and end values + p.alphaList.reset(this.startAlpha); + if (this.minimumSpeedMultiplier != 1) { + p.speedMultiplier = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier; + } + p.speedList.reset(this.startSpeed); + p.acceleration.x = this.acceleration.x; + p.acceleration.y = this.acceleration.y; + p.maxSpeed = this.maxSpeed; + if (this.minimumScaleMultiplier != 1) { + p.scaleMultiplier = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier; + } + p.scaleList.reset(this.startScale); + p.colorList.reset(this.startColor); + //randomize the rotation speed + if (this.minRotationSpeed == this.maxRotationSpeed) + p.rotationSpeed = this.minRotationSpeed; + else + p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed; + p.noRotation = this.noRotation; + //set up the lifetime + p.maxLife = lifetime; + //set the blend mode + p.blendMode = this.particleBlendMode; + //set the custom ease, if any + p.ease = this.customEase; + //set the extra data, if any + p.extraData = this.extraData; + //call the proper function to handle rotation and position of particle + this._spawnFunc(p, emitPosX, emitPosY, i); + //initialize particle + p.init(); + //update the particle by the time passed, so the particles are spread out properly + p.update(-this._spawnTimer); //we want a positive delta, because a negative delta messes things up + //add the particle to the display list + if (!p.parent) { + if (this.addAtBack) + this._parent.addChildAt(p, 0); + else + this._parent.addChild(p); + } + else { + //kind of hacky, but performance friendly + //shuffle children to correct place + var children = this._parent.children; + //avoid using splice if possible + if (children[0] == p) + children.shift(); + else if (children[children.length - 1] == p) + children.pop(); + else { + var index = children.indexOf(p); + children.splice(index, 1); + } + if (this.addAtBack) + children.unshift(p); + else + children.push(p); + } + //add particle to list of active particles + if (this._activeParticlesLast) { + this._activeParticlesLast.next = p; + p.prev = this._activeParticlesLast; + this._activeParticlesLast = p; + } + else { + this._activeParticlesLast = this._activeParticlesFirst = p; + } + ++this.particleCount; + } + } + //increase timer and continue on to any other particles that need to be created + this._spawnTimer += this._frequency; + } + } + //if the position changed before this update, then keep track of that + if (this._posChanged) { + this._prevEmitterPos.x = curX; + this._prevEmitterPos.y = curY; + this._prevPosIsValid = true; + this._posChanged = false; + } + //if we are all done and should destroy ourselves, take care of that + if (!this._emit && !this._activeParticlesFirst) { + if (this._completeCallback) { + this._completeCallback(); + } + if (this._destroyWhenComplete) { + this.destroy(); + } + } + }; + /** + * Positions a particle for a point type emitter. + * @method PIXI.particles.Emitter#_spawnPoint + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + Emitter.prototype._spawnPoint = function (p, emitPosX, emitPosY) { + //set the initial rotation/direction of the particle based on + //starting particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; + //drop the particle at the emitter's position + p.position.x = emitPosX; + p.position.y = emitPosY; + }; + /** + * Positions a particle for a rectangle type emitter. + * @method PIXI.particles.Emitter#_spawnRect + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + Emitter.prototype._spawnRect = function (p, emitPosX, emitPosY) { + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; + //place the particle at a random point in the rectangle + helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x; + helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y; + if (this.rotation !== 0) + ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint); + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + }; + /** + * Positions a particle for a circle type emitter. + * @method PIXI.particles.Emitter#_spawnCircle + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + Emitter.prototype._spawnCircle = function (p, emitPosX, emitPosY) { + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + + this.minStartRotation + this.rotation; + //place the particle at a random radius in the circle + helperPoint.x = Math.random() * this.spawnCircle.radius; + helperPoint.y = 0; + //rotate the point to a random angle in the circle + ParticleUtils_1.default.rotatePoint(Math.random() * 360, helperPoint); + //offset by the circle's center + helperPoint.x += this.spawnCircle.x; + helperPoint.y += this.spawnCircle.y; + //rotate the point by the emitter's rotation + if (this.rotation !== 0) + ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint); + //set the position, offset by the emitter's position + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + }; + /** + * Positions a particle for a ring type emitter. + * @method PIXI.particles.Emitter#_spawnRing + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + Emitter.prototype._spawnRing = function (p, emitPosX, emitPosY) { + var spawnCircle = this.spawnCircle; + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + + this.minStartRotation + this.rotation; + //place the particle at a random radius in the ring + if (spawnCircle.minRadius == spawnCircle.radius) { + helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) + + spawnCircle.minRadius; + } + else + helperPoint.x = spawnCircle.radius; + helperPoint.y = 0; + //rotate the point to a random angle in the circle + var angle = Math.random() * 360; + p.rotation += angle; + ParticleUtils_1.default.rotatePoint(angle, helperPoint); + //offset by the circle's center + helperPoint.x += this.spawnCircle.x; + helperPoint.y += this.spawnCircle.y; + //rotate the point by the emitter's rotation + if (this.rotation !== 0) + ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint); + //set the position, offset by the emitter's position + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + }; + /** + * Positions a particle for a burst type emitter. + * @method PIXI.particles.Emitter#_spawnBurst + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. + */ + Emitter.prototype._spawnBurst = function (p, emitPosX, emitPosY, i) { + //set the initial rotation/direction of the particle based on spawn + //angle and rotation of emitter + if (this.particleSpacing === 0) + p.rotation = Math.random() * 360; + else + p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation; + //drop the particle at the emitter's position + p.position.x = emitPosX; + p.position.y = emitPosY; + }; + /** + * Kills all active particles immediately. + * @method PIXI.particles.Emitter#cleanup + */ + Emitter.prototype.cleanup = function () { + var particle, next; + for (particle = this._activeParticlesFirst; particle; particle = next) { + next = particle.next; + this.recycle(particle); + if (particle.parent) + particle.parent.removeChild(particle); + } + this._activeParticlesFirst = this._activeParticlesLast = null; + this.particleCount = 0; + }; + /** + * Destroys the emitter and all of its particles. + * @method PIXI.particles.Emitter#destroy + */ + Emitter.prototype.destroy = function () { + //make sure we aren't still listening to any tickers + this.autoUpdate = false; + //puts all active particles in the pool, and removes them from the particle parent + this.cleanup(); + //wipe the pool clean + var next; + for (var particle = this._poolFirst; particle; particle = next) { + //store next value so we don't lose it in our destroy call + next = particle.next; + particle.destroy(); + } + this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos = + this.startColor = this.startScale = this.startAlpha = this.startSpeed = + this.customEase = this._completeCallback = null; + }; + return Emitter; +}()); +exports.default = Emitter; + +},{"./Particle":3,"./ParticleUtils":4,"./PropertyNode":7}],3:[function(_dereq_,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_1 = _dereq_("./ParticleUtils"); +var PropertyList_1 = _dereq_("./PropertyList"); var Sprite = PIXI.Sprite; - /** * An individual particle image. You shouldn't have to deal with these. * @memberof PIXI.particles @@ -1469,651 +1007,569 @@ var Sprite = PIXI.Sprite; * @constructor * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle. */ -var Particle = function(emitter) -{ - //start off the sprite with a blank texture, since we are going to replace it - //later when the particle is initialized. - Sprite.call(this); - - /** - * The emitter that controls this particle. - * @property {Emitter} emitter - */ - this.emitter = emitter; - //particles should be centered - this.anchor.x = this.anchor.y = 0.5; - /** - * The velocity of the particle. Speed may change, but the angle also - * contained in velocity is constant. - * @property {PIXI.Point} velocity - */ - this.velocity = new PIXI.Point(); - /** - * The maximum lifetime of this particle, in seconds. - * @property {Number} maxLife - */ - this.maxLife = 0; - /** - * The current age of the particle, in seconds. - * @property {Number} age - */ - this.age = 0; - /** - * A simple easing function to be applied to all properties that - * are being interpolated. - * @property {Function} ease - */ - this.ease = null; - /** - * Extra data that the emitter passes along for custom particles. - * @property {Object} extraData - */ - this.extraData = null; - /** - * The alpha of the particle at the start of its life. - * @property {Number} startAlpha - */ - this.startAlpha = 0; - /** - * The alpha of the particle at the end of its life. - * @property {Number} endAlpha - */ - this.endAlpha = 0; - /** - * The speed of the particle at the start of its life. - * @property {Number} startSpeed - */ - this.startSpeed = 0; - /** - * The speed of the particle at the end of its life. - * @property {Number} endSpeed - */ - this.endSpeed = 0; - /** - * Acceleration to apply to the particle. - * @property {PIXI.Point} accleration - */ - this.acceleration = new PIXI.Point(); - /** - * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN - * will disable the maximum speed. - * @property {Number} maxSpeed - * @default NaN - */ - this.maxSpeed = NaN; - /** - * The scale of the particle at the start of its life. - * @property {Number} startScale - */ - this.startScale = 0; - /** - * The scale of the particle at the start of its life. - * @property {Number} endScale - */ - this.endScale = 0; - /** - * The tint of the particle at the start of its life. - * @property {Array} startColor - */ - this.startColor = null; - /** - * The red tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sR - * @private - */ - this._sR = 0; - /** - * The green tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sG - * @private - */ - this._sG = 0; - /** - * The blue tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sB - * @private - */ - this._sB = 0; - /** - * The tint of the particle at the start of its life. - * @property {Array} endColor - */ - this.endColor = null; - /** - * The red tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _eR - * @private - */ - this._eR = 0; - /** - * The green tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _sG - * @private - */ - this._eG = 0; - /** - * The blue tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _sB - * @private - */ - this._eB = 0; - /** - * If alpha should be interpolated at all. - * @property {Boolean} _doAlpha - * @private - */ - this._doAlpha = false; - /** - * If scale should be interpolated at all. - * @property {Boolean} _doScale - * @private - */ - this._doScale = false; - /** - * If speed should be interpolated at all. - * @property {Boolean} _doSpeed - * @private - */ - this._doSpeed = false; - /** - * If acceleration should be handled at all. _doSpeed is mutually exclusive with this, - * and _doSpeed gets priority. - * @property {Boolean} _doAcceleration - * @private - */ - this._doAcceleration = false; - /** - * If color should be interpolated at all. - * @property {Boolean} _doColor - * @private - */ - this._doColor = false; - /** - * If normal movement should be handled. Subclasses wishing to override movement - * can set this to false in init(). - * @property {Boolean} _doNormalMovement - * @private - */ - this._doNormalMovement = false; - /** - * One divided by the max life of the particle, saved for slightly faster math. - * @property {Number} _oneOverLife - * @private - */ - this._oneOverLife = 0; - - /** - * Reference to the next particle in the list. - * @property {Particle} next - * @private - */ - this.next = null; - - /** - * Reference to the previous particle in the list. - * @property {Particle} prev - * @private - */ - this.prev = null; - - //save often used functions on the instance instead of the prototype for better speed - this.init = this.init; - this.Particle_init = this.Particle_init; - this.update = this.update; - this.Particle_update = this.Particle_update; - this.applyArt = this.applyArt; - this.kill = this.kill; -}; - -// Reference to the prototype -var p = Particle.prototype = Object.create(Sprite.prototype); - -/** - * Initializes the particle for use, based on the properties that have to - * have been set already on the particle. - * @method PIXI.particles.Particle#init - */ -/** - * A reference to init, so that subclasses can access it without the penalty of Function.call() - * @method PIXI.particles.Particle#Particle_init - * @protected - */ -p.init = p.Particle_init = function() -{ - //reset the age - this.age = 0; - //set up the velocity based on the start speed and rotation - this.velocity.x = this.startSpeed; - this.velocity.y = 0; - ParticleUtils.rotatePoint(this.rotation, this.velocity); - if (this.noRotation) - { - this.rotation = 0; - } - else - { - //convert rotation to Radians from Degrees - this.rotation *= ParticleUtils.DEG_TO_RADS; - } - //convert rotation speed to Radians from Degrees - this.rotationSpeed *= ParticleUtils.DEG_TO_RADS; - //set alpha to inital alpha - this.alpha = this.startAlpha; - //set scale to initial scale - this.scale.x = this.scale.y = this.startScale; - //determine start and end color values - if (this.startColor) - { - this._sR = this.startColor[0]; - this._sG = this.startColor[1]; - this._sB = this.startColor[2]; - if(this.endColor) - { - this._eR = this.endColor[0]; - this._eG = this.endColor[1]; - this._eB = this.endColor[2]; - } - } - //figure out what we need to interpolate - this._doAlpha = this.startAlpha != this.endAlpha; - this._doSpeed = this.startSpeed != this.endSpeed; - this._doScale = this.startScale != this.endScale; - this._doColor = !!this.endColor; - this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0; - //_doNormalMovement can be cancelled by subclasses - this._doNormalMovement = this._doSpeed || this.startSpeed !== 0 || this._doAcceleration; - //save our lerp helper - this._oneOverLife = 1 / this.maxLife; - //set the inital color - this.tint = ParticleUtils.combineRGBComponents(this._sR, this._sG, this._sB); - //ensure visibility - this.visible = true; -}; - -/** - * Sets the texture for the particle. This can be overridden to allow - * for an animated particle. - * @method PIXI.particles.Particle#applyArt - * @param {PIXI.Texture} art The texture to set. - */ -p.applyArt = function(art) -{ - this.texture = art || ParticleUtils.EMPTY_TEXTURE; -}; - -/** - * Updates the particle. - * @method PIXI.particles.Particle#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle - * properties. A value of -1 means the particle died of old age instead. - */ -/** - * A reference to update so that subclasses can access the original without the overhead - * of Function.call(). - * @method PIXI.particles.Particle#Particle_update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle - * properties. A value of -1 means the particle died of old age instead. - * @protected - */ -p.update = p.Particle_update = function(delta) -{ - //increase age - this.age += delta; - //recycle particle if it is too old - if(this.age >= this.maxLife) - { - this.kill(); - return -1; - } - - //determine our interpolation value - var lerp = this.age * this._oneOverLife;//lifetime / maxLife; - if (this.ease) - { - if(this.ease.length == 4) - { - //the t, b, c, d parameters that some tween libraries use - //(time, initial value, end value, duration) - lerp = this.ease(lerp, 0, 1, 1); - } - else - { - //the simplified version that we like that takes - //one parameter, time from 0-1. TweenJS eases provide this usage. - lerp = this.ease(lerp); - } - } - - //interpolate alpha - if (this._doAlpha) - this.alpha = (this.endAlpha - this.startAlpha) * lerp + this.startAlpha; - //interpolate scale - if (this._doScale) - { - var scale = (this.endScale - this.startScale) * lerp + this.startScale; - this.scale.x = this.scale.y = scale; - } - //handle movement - if(this._doNormalMovement) - { - //interpolate speed - if (this._doSpeed) - { - var speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed; - ParticleUtils.normalize(this.velocity); - ParticleUtils.scaleBy(this.velocity, speed); - } - else if(this._doAcceleration) - { - this.velocity.x += this.acceleration.x * delta; - this.velocity.y += this.acceleration.y * delta; - if (this.maxSpeed) - { - var currentSpeed = ParticleUtils.length(this.velocity); - //if we are going faster than we should, clamp at the max speed - //DO NOT recalculate vector length - if (currentSpeed > this.maxSpeed) - { - ParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed); - } - } - } - //adjust position based on velocity - this.position.x += this.velocity.x * delta; - this.position.y += this.velocity.y * delta; - } - //interpolate color - if (this._doColor) - { - var r = (this._eR - this._sR) * lerp + this._sR; - var g = (this._eG - this._sG) * lerp + this._sG; - var b = (this._eB - this._sB) * lerp + this._sB; - this.tint = ParticleUtils.combineRGBComponents(r, g, b); - } - //update rotation - if(this.rotationSpeed !== 0) - { - this.rotation += this.rotationSpeed * delta; - } - else if(this.acceleration && !this.noRotation) - { - this.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2; - } - return lerp; -}; - -/** - * Kills the particle, removing it from the display list - * and telling the emitter to recycle it. - * @method PIXI.particles.Particle#kill - */ -p.kill = function() -{ - this.emitter.recycle(this); -}; - -p.Sprite_Destroy = Sprite.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.Particle#destroy - */ -p.destroy = function() -{ - if (this.parent) - this.parent.removeChild(this); - if (this.Sprite_Destroy) - this.Sprite_Destroy(); - this.emitter = this.velocity = this.startColor = this.endColor = this.ease = - this.next = this.prev = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. - * @method PIXI.particles.Particle.parseArt - * @static - * @param {Array} art The array of art data. For Particle, it should be an array of Textures. - * Any strings in the array will be converted to Textures via - * Texture.fromImage(). - * @return {Array} The art, after any needed modifications. - */ -Particle.parseArt = function(art) -{ - //convert any strings to Textures. - var i; - for(i = art.length; i >= 0; --i) - { - if(typeof art[i] == "string") - art[i] = PIXI.Texture.fromImage(art[i]); - } - //particles from different base textures will be slower in WebGL than if they - //were from one spritesheet - if(ParticleUtils.verbose) - { - for(i = art.length - 1; i > 0; --i) - { - if(art[i].baseTexture != art[i - 1].baseTexture) - { - if (window.console) - console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL"); - break; - } - } - } - - return art; -}; - -/** - * Parses extra emitter data to ensure it is set up for this particle class. - * Particle does nothing to the extra data. - * @method PIXI.particles.Particle.parseData - * @static - * @param {Object} extraData The extra data from the particle config. - * @return {Object} The parsed extra data. - */ -Particle.parseData = function(extraData) -{ - return extraData; -}; - -module.exports = Particle; -},{"./ParticleUtils":4}],4:[function(_dereq_,module,exports){ +var Particle = /** @class */ (function (_super) { + __extends(Particle, _super); + function Particle(emitter) { + var _this = + //start off the sprite with a blank texture, since we are going to replace it + //later when the particle is initialized. + _super.call(this) || this; + _this.emitter = emitter; + //particles should be centered + _this.anchor.x = _this.anchor.y = 0.5; + _this.velocity = new PIXI.Point(); + _this.maxLife = 0; + _this.age = 0; + _this.ease = null; + _this.extraData = null; + _this.alphaList = new PropertyList_1.default(); + _this.speedList = new PropertyList_1.default(); + _this.speedMultiplier = 1; + /** + * Acceleration to apply to the particle. + * @property {PIXI.Point} accleration + */ + _this.acceleration = new PIXI.Point(); + /** + * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN + * will disable the maximum speed. + * @property {Number} maxSpeed + * @default NaN + */ + _this.maxSpeed = NaN; + /** + * The scale of the particle throughout its life. + * @property {PIXI.particles.PropertyList} scaleList + */ + _this.scaleList = new PropertyList_1.default(); + /** + * A multiplier from 0-1 applied to the scale of the particle at all times. + * @property {number} scaleMultiplier + */ + _this.scaleMultiplier = 1; + /** + * The tint of the particle throughout its life. + * @property {PIXI.particles.PropertyList} colorList + */ + _this.colorList = new PropertyList_1.default(true); + /** + * If alpha should be interpolated at all. + * @property {Boolean} _doAlpha + * @private + */ + _this._doAlpha = false; + /** + * If scale should be interpolated at all. + * @property {Boolean} _doScale + * @private + */ + _this._doScale = false; + /** + * If speed should be interpolated at all. + * @property {Boolean} _doSpeed + * @private + */ + _this._doSpeed = false; + /** + * If acceleration should be handled at all. _doSpeed is mutually exclusive with this, + * and _doSpeed gets priority. + * @property {Boolean} _doAcceleration + * @private + */ + _this._doAcceleration = false; + /** + * If color should be interpolated at all. + * @property {Boolean} _doColor + * @private + */ + _this._doColor = false; + /** + * If normal movement should be handled. Subclasses wishing to override movement + * can set this to false in init(). + * @property {Boolean} _doNormalMovement + * @private + */ + _this._doNormalMovement = false; + /** + * One divided by the max life of the particle, saved for slightly faster math. + * @property {Number} _oneOverLife + * @private + */ + _this._oneOverLife = 0; + /** + * Reference to the next particle in the list. + * @property {Particle} next + * @private + */ + _this.next = null; + /** + * Reference to the previous particle in the list. + * @property {Particle} prev + * @private + */ + _this.prev = null; + //save often used functions on the instance instead of the prototype for better speed + _this.init = _this.init; + _this.Particle_init = Particle.prototype.init; + _this.update = _this.update; + _this.Particle_update = Particle.prototype.update; + _this.Sprite_destroy = _super.prototype.destroy; + _this.Particle_destroy = Particle.prototype.destroy; + _this.applyArt = _this.applyArt; + _this.kill = _this.kill; + return _this; + } + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.Particle#init + */ + Particle.prototype.init = function () { + //reset the age + this.age = 0; + //set up the velocity based on the start speed and rotation + this.velocity.x = this.speedList.current.value * this.speedMultiplier; + this.velocity.y = 0; + ParticleUtils_1.default.rotatePoint(this.rotation, this.velocity); + if (this.noRotation) { + this.rotation = 0; + } + else { + //convert rotation to Radians from Degrees + this.rotation *= ParticleUtils_1.default.DEG_TO_RADS; + } + //convert rotation speed to Radians from Degrees + this.rotationSpeed *= ParticleUtils_1.default.DEG_TO_RADS; + //set alpha to inital alpha + this.alpha = this.alphaList.current.value; + //set scale to initial scale + this.scale.x = this.scale.y = this.scaleList.current.value; + //figure out what we need to interpolate + this._doAlpha = !!this.alphaList.current.next; + this._doSpeed = !!this.speedList.current.next; + this._doScale = !!this.scaleList.current.next; + this._doColor = !!this.colorList.current.next; + this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0; + //_doNormalMovement can be cancelled by subclasses + this._doNormalMovement = this._doSpeed || this.speedList.current.value !== 0 || this._doAcceleration; + //save our lerp helper + this._oneOverLife = 1 / this.maxLife; + //set the inital color + var color = this.colorList.current.value; + this.tint = ParticleUtils_1.default.combineRGBComponents(color.r, color.g, color.b); + //ensure visibility + this.visible = true; + }; + /** + * Sets the texture for the particle. This can be overridden to allow + * for an animated particle. + * @method PIXI.particles.Particle#applyArt + * @param {PIXI.Texture} art The texture to set. + */ + Particle.prototype.applyArt = function (art) { + this.texture = art || PIXI.Texture.EMPTY; + }; + /** + * Updates the particle. + * @method PIXI.particles.Particle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle + * properties. A value of -1 means the particle died of old age instead. + */ + Particle.prototype.update = function (delta) { + //increase age + this.age += delta; + //recycle particle if it is too old + if (this.age >= this.maxLife) { + this.kill(); + return -1; + } + //determine our interpolation value + var lerp = this.age * this._oneOverLife; //lifetime / maxLife; + if (this.ease) { + if (this.ease.length == 4) { + //the t, b, c, d parameters that some tween libraries use + //(time, initial value, end value, duration) + lerp = this.ease(lerp, 0, 1, 1); + } + else { + //the simplified version that we like that takes + //one parameter, time from 0-1. TweenJS eases provide this usage. + lerp = this.ease(lerp); + } + } + //interpolate alpha + if (this._doAlpha) + this.alpha = this.alphaList.interpolate(lerp); + //interpolate scale + if (this._doScale) { + var scale = this.scaleList.interpolate(lerp) * this.scaleMultiplier; + this.scale.x = this.scale.y = scale; + } + //handle movement + if (this._doNormalMovement) { + //interpolate speed + if (this._doSpeed) { + var speed = this.speedList.interpolate(lerp) * this.speedMultiplier; + ParticleUtils_1.default.normalize(this.velocity); + ParticleUtils_1.default.scaleBy(this.velocity, speed); + } + else if (this._doAcceleration) { + this.velocity.x += this.acceleration.x * delta; + this.velocity.y += this.acceleration.y * delta; + if (this.maxSpeed) { + var currentSpeed = ParticleUtils_1.default.length(this.velocity); + //if we are going faster than we should, clamp at the max speed + //DO NOT recalculate vector length + if (currentSpeed > this.maxSpeed) { + ParticleUtils_1.default.scaleBy(this.velocity, this.maxSpeed / currentSpeed); + } + } + } + //adjust position based on velocity + this.position.x += this.velocity.x * delta; + this.position.y += this.velocity.y * delta; + } + //interpolate color + if (this._doColor) { + this.tint = this.colorList.interpolate(lerp); + } + //update rotation + if (this.rotationSpeed !== 0) { + this.rotation += this.rotationSpeed * delta; + } + else if (this.acceleration && !this.noRotation) { + this.rotation = Math.atan2(this.velocity.y, this.velocity.x); // + Math.PI / 2; + } + return lerp; + }; + /** + * Kills the particle, removing it from the display list + * and telling the emitter to recycle it. + * @method PIXI.particles.Particle#kill + */ + Particle.prototype.kill = function () { + this.emitter.recycle(this); + }; + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.Particle#destroy + */ + Particle.prototype.destroy = function () { + if (this.parent) + this.parent.removeChild(this); + this.Sprite_destroy(); + this.emitter = this.velocity = this.colorList = this.scaleList = this.alphaList = + this.speedList = this.ease = this.next = this.prev = null; + }; + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. + * @method PIXI.particles.Particle.parseArt + * @static + * @param {Array} art The array of art data. For Particle, it should be an array of Textures. + * Any strings in the array will be converted to Textures via + * Texture.fromImage(). + * @return {Array} The art, after any needed modifications. + */ + Particle.parseArt = function (art) { + //convert any strings to Textures. + var i; + for (i = art.length; i >= 0; --i) { + if (typeof art[i] == "string") + art[i] = PIXI.Texture.fromImage(art[i]); + } + //particles from different base textures will be slower in WebGL than if they + //were from one spritesheet + if (ParticleUtils_1.default.verbose) { + for (i = art.length - 1; i > 0; --i) { + if (art[i].baseTexture != art[i - 1].baseTexture) { + if (window.console) + console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL"); + break; + } + } + } + return art; + }; + /** + * Parses extra emitter data to ensure it is set up for this particle class. + * Particle does nothing to the extra data. + * @method PIXI.particles.Particle.parseData + * @static + * @param {Object} extraData The extra data from the particle config. + * @return {Object} The parsed extra data. + */ + Particle.parseData = function (extraData) { + return extraData; + }; + return Particle; +}(Sprite)); +exports.default = Particle; + +},{"./ParticleUtils":4,"./PropertyList":6}],4:[function(_dereq_,module,exports){ "use strict"; - -var BLEND_MODES = PIXI.BLEND_MODES || PIXI.blendModes; -var Texture = PIXI.Texture; - +Object.defineProperty(exports, "__esModule", { value: true }); +var BLEND_MODES = PIXI.BLEND_MODES; +var PropertyNode_1 = _dereq_("./PropertyNode"); /** * Contains helper functions for particles and emitters to use. * @memberof PIXI.particles * @class ParticleUtils * @static */ -var ParticleUtils = {}; - -/** - * If errors and warnings should be logged within the library. - * @name PIXI.particles.ParticleUtils.verbose - * @default false - * @static - */ -ParticleUtils.verbose = false; - -var DEG_TO_RADS = ParticleUtils.DEG_TO_RADS = Math.PI / 180; - -var empty = ParticleUtils.EMPTY_TEXTURE = Texture.EMPTY; -//prevent any events from being used on the empty texture, as well as destruction of it -//v4 of Pixi does this, but doing it again won't hurt -empty.on = empty.destroy = empty.once = empty.emit = function() {}; - -/** - * Rotates a point by a given angle. - * @method PIXI.particles.ParticleUtils.rotatePoint - * @param {Number} angle The angle to rotate by in degrees - * @param {PIXI.Point} p The point to rotate around 0,0. - * @static - */ -ParticleUtils.rotatePoint = function(angle, p) -{ - if(!angle) return; - angle *= DEG_TO_RADS; - var s = Math.sin(angle); - var c = Math.cos(angle); - var xnew = p.x * c - p.y * s; - var ynew = p.x * s + p.y * c; - p.x = xnew; - p.y = ynew; -}; - -/** - * Combines separate color components (0-255) into a single uint color. - * @method PIXI.particles.ParticleUtils.combineRGBComponents - * @param {uint} r The red value of the color - * @param {uint} g The green value of the color - * @param {uint} b The blue value of the color - * @return {uint} The color in the form of 0xRRGGBB - * @static - */ -ParticleUtils.combineRGBComponents = function(r, g, b/*, a*/) -{ - return /*a << 24 |*/ r << 16 | g << 8 | b; -}; - -/** - * Reduces the point to a length of 1. - * @method PIXI.particles.ParticleUtils.normalize - * @static - * @param {PIXI.Point} point The point to normalize - */ -ParticleUtils.normalize = function(point) -{ - var oneOverLen = 1 / ParticleUtils.length(point); - point.x *= oneOverLen; - point.y *= oneOverLen; -}; - -/** - * Multiplies the x and y values of this point by a value. - * @method PIXI.particles.ParticleUtils.scaleBy - * @static - * @param {PIXI.Point} point The point to scaleBy - * @param value {Number} The value to scale by. - */ -ParticleUtils.scaleBy = function(point, value) -{ - point.x *= value; - point.y *= value; -}; - -/** - * Returns the length (or magnitude) of this point. - * @method PIXI.particles.ParticleUtils.length - * @static - * @param {PIXI.Point} point The point to measure length - * @return The length of this point. - */ -ParticleUtils.length = function(point) -{ - return Math.sqrt(point.x * point.x + point.y * point.y); -}; - -/** - * Converts a hex string from "#AARRGGBB", "#RRGGBB", "0xAARRGGBB", "0xRRGGBB", - * "AARRGGBB", or "RRGGBB" to an array of ints of 0-255 or Numbers from 0-1, as - * [r, g, b, (a)]. - * @method PIXI.particles.ParticleUtils.hexToRGB - * @param {String} color The input color string. - * @param {Array} output An array to put the output in. If omitted, a new array is created. - * @return The array of numeric color values. - * @static - */ -ParticleUtils.hexToRGB = function(color, output) -{ - if (output) - output.length = 0; - else - output = []; - if (color.charAt(0) == "#") - color = color.substr(1); - else if (color.indexOf("0x") === 0) - color = color.substr(2); - var alpha; - if (color.length == 8) - { - alpha = color.substr(0, 2); - color = color.substr(2); - } - output.push(parseInt(color.substr(0, 2), 16));//Red - output.push(parseInt(color.substr(2, 2), 16));//Green - output.push(parseInt(color.substr(4, 2), 16));//Blue - if (alpha) - output.push(parseInt(alpha, 16)); - return output; +var ParticleUtils = { + /** + * If errors and warnings should be logged within the library. + * @name PIXI.particles.ParticleUtils.verbose + * @default false + * @static + */ + verbose: false, + DEG_TO_RADS: Math.PI / 180, + /** + * Rotates a point by a given angle. + * @method PIXI.particles.ParticleUtils.rotatePoint + * @param {Number} angle The angle to rotate by in degrees + * @param {PIXI.Point} p The point to rotate around 0,0. + * @static + */ + rotatePoint: function (angle, p) { + if (!angle) + return; + angle *= ParticleUtils.DEG_TO_RADS; + var s = Math.sin(angle); + var c = Math.cos(angle); + var xnew = p.x * c - p.y * s; + var ynew = p.x * s + p.y * c; + p.x = xnew; + p.y = ynew; + }, + /** + * Combines separate color components (0-255) into a single uint color. + * @method PIXI.particles.ParticleUtils.combineRGBComponents + * @param {uint} r The red value of the color + * @param {uint} g The green value of the color + * @param {uint} b The blue value of the color + * @return {uint} The color in the form of 0xRRGGBB + * @static + */ + combineRGBComponents: function (r, g, b /*, a*/) { + return /*a << 24 |*/ r << 16 | g << 8 | b; + }, + /** + * Reduces the point to a length of 1. + * @method PIXI.particles.ParticleUtils.normalize + * @static + * @param {PIXI.Point} point The point to normalize + */ + normalize: function (point) { + var oneOverLen = 1 / ParticleUtils.length(point); + point.x *= oneOverLen; + point.y *= oneOverLen; + }, + /** + * Multiplies the x and y values of this point by a value. + * @method PIXI.particles.ParticleUtils.scaleBy + * @static + * @param {PIXI.Point} point The point to scaleBy + * @param {number} value The value to scale by. + */ + scaleBy: function (point, value) { + point.x *= value; + point.y *= value; + }, + /** + * Returns the length (or magnitude) of this point. + * @method PIXI.particles.ParticleUtils.length + * @static + * @param {PIXI.Point} point The point to measure length + * @return The length of this point. + */ + length: function (point) { + return Math.sqrt(point.x * point.x + point.y * point.y); + }, + /** + * Converts a hex string from "#AARRGGBB", "#RRGGBB", "0xAARRGGBB", "0xRRGGBB", + * "AARRGGBB", or "RRGGBB" to an object of ints of 0-255, as + * {r, g, b, (a)}. + * @method PIXI.particles.ParticleUtils.hexToRGB + * @param {string} color The input color string. + * @param {Object} [output] An object to put the output in. If omitted, a new object is created. + * @return The object with r, g, and b properties, possibly with an a property. + * @static + */ + hexToRGB: function (color, output) { + if (!output) + output = {}; + if (color.charAt(0) == "#") + color = color.substr(1); + else if (color.indexOf("0x") === 0) + color = color.substr(2); + var alpha; + if (color.length == 8) { + alpha = color.substr(0, 2); + color = color.substr(2); + } + output.r = parseInt(color.substr(0, 2), 16); //Red + output.g = parseInt(color.substr(2, 2), 16); //Green + output.b = parseInt(color.substr(4, 2), 16); //Blue + if (alpha) + output.a = parseInt(alpha, 16); + return output; + }, + /** + * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated + * by the related tool at http://www.greensock.com/customease/. + * @method PIXI.particles.ParticleUtils.generateEase + * @param {Array} segments An array of segments, as created by + * http://www.greensock.com/customease/. + * @return {Function} A function that calculates the percentage of change at + * a given point in time (0-1 inclusive). + * @static + */ + generateEase: function (segments) { + var qty = segments.length; + var oneOverQty = 1 / qty; + /* + * Calculates the percentage of change at a given point in time (0-1 inclusive). + * @param {Number} time The time of the ease, 0-1 inclusive. + * @return {Number} The percentage of the change, 0-1 inclusive (unless your + * ease goes outside those bounds). + */ + return function (time) { + var t, s; + var i = (qty * time) | 0; //do a quick floor operation + t = (time - (i * oneOverQty)) * qty; + s = segments[i] || segments[qty - 1]; + return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s))); + }; + }, + /** + * Gets a blend mode, ensuring that it is valid. + * @method PIXI.particles.ParticleUtils.getBlendMode + * @param {string} name The name of the blend mode to get. + * @return {int} The blend mode as specified in the PIXI.BLEND_MODES enumeration. + * @static + */ + getBlendMode: function (name) { + if (!name) + return BLEND_MODES.NORMAL; + name = name.toUpperCase(); + while (name.indexOf(" ") >= 0) + name = name.replace(" ", "_"); + return BLEND_MODES[name] || BLEND_MODES.NORMAL; + }, + /** + * Converts a list of {value, time} objects starting at time 0 and ending at time 1 into an evenly + * spaced stepped list of PropertyNodes for color values. This is primarily to handle conversion of + * linear gradients to fewer colors, allowing for some optimization for Canvas2d fallbacks. + * @method PIXI.particles.ParticleUtils.createSteppedGradient + * @param {Array} list The list of data to convert. + * @param {number} [numSteps=10] The number of steps to use. + * @return {PIXI.particles.PropertyNode} The blend mode as specified in the PIXI.blendModes enumeration. + * @static + */ + createSteppedGradient: function (list, numSteps) { + if (numSteps === void 0) { numSteps = 10; } + if (typeof numSteps !== 'number' || numSteps <= 0) + numSteps = 10; + var first = new PropertyNode_1.default(list[0].value, list[0].time); + first.isStepped = true; + var currentNode = first; + var current = list[0]; + var nextIndex = 1; + var next = list[nextIndex]; + for (var i = 1; i < numSteps; ++i) { + var lerp = i / numSteps; + //ensure we are on the right segment, if multiple + while (lerp > next.time) { + current = next; + next = list[++nextIndex]; + } + //convert the lerp value to the segment range + lerp = (lerp - current.time) / (next.time - current.time); + var curVal = ParticleUtils.hexToRGB(current.value); + var nextVal = ParticleUtils.hexToRGB(next.value); + var output = {}; + output.r = (nextVal.r - curVal.r) * lerp + curVal.r; + output.g = (nextVal.g - curVal.g) * lerp + curVal.g; + output.b = (nextVal.b - curVal.b) * lerp + curVal.b; + currentNode.next = new PropertyNode_1.default(output, i / numSteps); + currentNode = currentNode.next; + } + //we don't need to have a PropertyNode for time of 1, because in a stepped version at that point + //the particle has died of old age + return first; + } }; +exports.default = ParticleUtils; +},{"./PropertyNode":7}],5:[function(_dereq_,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_1 = _dereq_("./ParticleUtils"); +var Particle_1 = _dereq_("./Particle"); /** - * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated - * by the related tool at http://www.greensock.com/customease/. - * @method PIXI.particles.ParticleUtils.generateEase - * @param {Array} segments An array of segments, as created by - * http://www.greensock.com/customease/. - * @return {Function} A function that calculates the percentage of change at - * a given point in time (0-1 inclusive). - * @static + * A helper point for math things. + * @private */ -ParticleUtils.generateEase = function(segments) -{ - var qty = segments.length; - var oneOverQty = 1 / qty; - /* - * Calculates the percentage of change at a given point in time (0-1 inclusive). - * @param {Number} time The time of the ease, 0-1 inclusive. - * @return {Number} The percentage of the change, 0-1 inclusive (unless your - * ease goes outside those bounds). - */ - var simpleEase = function(time) - { - var t, s; - var i = (qty * time) | 0;//do a quick floor operation - t = (time - (i * oneOverQty)) * qty; - s = segments[i] || segments[qty - 1]; - return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s))); - }; - return simpleEase; -}; - +var helperPoint = new PIXI.Point(); +//a hand picked list of Math functions (and a couple properties) that are allowable. +//they should be used without the preceding "Math." +var MATH_FUNCS = [ + "pow", + "sqrt", + "abs", + "floor", + "round", + "ceil", + "E", + "PI", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "atan2", + "log" +]; +//create an actual regular expression object from the string +var WHITELISTER = new RegExp([ + //Allow the 4 basic operations, parentheses and all numbers/decimals, as well + //as 'x', for the variable usage. + "[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]", +].concat(MATH_FUNCS).join("|"), "g"); /** - * Gets a blend mode, ensuring that it is valid. - * @method PIXI.particles.ParticleUtils.getBlendMode - * @param {String} name The name of the blend mode to get. - * @return {int} The blend mode as specified in the PIXI.blendModes enumeration. + * Parses a string into a function for path following. + * This involves whitelisting the string for safety, inserting "Math." to math function + * names, and using `new Function()` to generate a function. + * @method PIXI.particles.PathParticle~parsePath + * @private * @static + * @param {String} pathString The string to parse. + * @return {Function} The path function - takes x, outputs y. */ -ParticleUtils.getBlendMode = function(name) -{ - if (!name) return BLEND_MODES.NORMAL; - name = name.toUpperCase(); - while (name.indexOf(" ") >= 0) - name = name.replace(" ", "_"); - return BLEND_MODES[name] || BLEND_MODES.NORMAL; +var parsePath = function (pathString) { + var matches = pathString.match(WHITELISTER); + for (var i = matches.length - 1; i >= 0; --i) { + if (MATH_FUNCS.indexOf(matches[i]) >= 0) + matches[i] = "Math." + matches[i]; + } + pathString = matches.join(""); + return new Function("x", "return " + pathString + ";"); }; - -module.exports = ParticleUtils; -},{}],5:[function(_dereq_,module,exports){ -"use strict"; - -var ParticleUtils = _dereq_("./ParticleUtils"), - Particle = _dereq_("./Particle"); - /** * An particle that follows a path defined by an algebraic expression, e.g. "sin(x)" or * "5x + 3". @@ -2139,253 +1595,318 @@ var ParticleUtils = _dereq_("./ParticleUtils"), * @constructor * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle. */ -var PathParticle = function(emitter) -{ - Particle.call(this, emitter); - /** - * The function representing the path the particle should take. - * @property {Function} path - */ - this.path = null; - /** - * The initial rotation in degrees of the particle, because the direction of the path - * is based on that. - * @property {Number} initialRotation - */ - this.initialRotation = 0; - /** - * The initial position of the particle, as all path movement is added to that. - * @property {PIXI.Point} initialPosition - */ - this.initialPosition = new PIXI.Point(); - /** - * Total single directional movement, due to speed. - * @property {Number} movement - */ - this.movement = 0; -}; - -// Reference to the super class -var s = Particle.prototype; -// Reference to the prototype -var p = PathParticle.prototype = Object.create(s); - -/** - * A helper point for math things. - * @property {Function} helperPoint - * @private - * @static - */ -var helperPoint = new PIXI.Point(); +var PathParticle = /** @class */ (function (_super) { + __extends(PathParticle, _super); + function PathParticle(emitter) { + var _this = _super.call(this, emitter) || this; + _this.path = null; + _this.initialRotation = 0; + _this.initialPosition = new PIXI.Point(); + _this.movement = 0; + return _this; + } + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.PathParticle#init + */ + PathParticle.prototype.init = function () { + //get initial rotation before it is converted to radians + this.initialRotation = this.rotation; + //standard init + this.Particle_init(); + //set the path for the particle + this.path = this.extraData.path; + //cancel the normal movement behavior + this._doNormalMovement = !this.path; + //reset movement + this.movement = 0; + //grab position + this.initialPosition.x = this.position.x; + this.initialPosition.y = this.position.y; + }; + /** + * Updates the particle. + * @method PIXI.particles.PathParticle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + PathParticle.prototype.update = function (delta) { + var lerp = this.Particle_update(delta); + //if the particle died during the update, then don't bother + if (lerp >= 0 && this.path) { + //increase linear movement based on speed + var speed = this.speedList.interpolate(lerp) * this.speedMultiplier; + this.movement += speed * delta; + //set up the helper point for rotation + helperPoint.x = this.movement; + helperPoint.y = this.path(this.movement); + ParticleUtils_1.default.rotatePoint(this.initialRotation, helperPoint); + this.position.x = this.initialPosition.x + helperPoint.x; + this.position.y = this.initialPosition.y + helperPoint.y; + } + return lerp; + }; + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.PathParticle#destroy + */ + PathParticle.prototype.destroy = function () { + this.Particle_destroy(); + this.path = this.initialPosition = null; + }; + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. This just runs Particle.parseArt(). + * @method PIXI.particles.PathParticle.parseArt + * @static + * @param {Array} art The array of art data. For Particle, it should be an array of Textures. + * Any strings in the array will be converted to Textures via + * Texture.fromImage(). + * @return {Array} The art, after any needed modifications. + */ + PathParticle.parseArt = function (art) { + return Particle_1.default.parseArt(art); + }; + /** + * Parses extra emitter data to ensure it is set up for this particle class. + * PathParticle checks for the existence of path data, and parses the path data for use + * by particle instances. + * @method PIXI.particles.PathParticle.parseData + * @static + * @param {Object} extraData The extra data from the particle config. + * @return {Object} The parsed extra data. + */ + PathParticle.parseData = function (extraData) { + var output = {}; + if (extraData && extraData.path) { + try { + output.path = parsePath(extraData.path); + } + catch (e) { + if (ParticleUtils_1.default.verbose) + console.error("PathParticle: error in parsing path expression"); + output.path = null; + } + } + else { + if (ParticleUtils_1.default.verbose) + console.error("PathParticle requires a path string in extraData!"); + output.path = null; + } + return output; + }; + return PathParticle; +}(Particle_1.default)); +exports.default = PathParticle; +},{"./Particle":3,"./ParticleUtils":4}],6:[function(_dereq_,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_1 = _dereq_("./ParticleUtils"); /** - * Initializes the particle for use, based on the properties that have to - * have been set already on the particle. - * @method PIXI.particles.PathParticle#init + * Singly linked list container for keeping track of interpolated properties for particles. + * Each Particle will have one of these for each interpolated property. + * @memberof PIXI.particles + * @class PropertyList + * @constructor + * @param {boolean} isColor If this list handles color values */ -p.init = function() -{ - //get initial rotation before it is converted to radians - this.initialRotation = this.rotation; - //standard init - this.Particle_init(); - - //set the path for the particle - this.path = this.extraData.path; - //cancel the normal movement behavior - this._doNormalMovement = !this.path; - //reset movement - this.movement = 0; - //grab position - this.initialPosition.x = this.position.x; - this.initialPosition.y = this.position.y; -}; - -//a hand picked list of Math functions (and a couple properties) that are allowable. -//they should be used without the preceding "Math." -var MATH_FUNCS = -[ - "pow", - "sqrt", - "abs", - "floor", - "round", - "ceil", - "E", - "PI", - "sin", - "cos", - "tan", - "asin", - "acos", - "atan", - "atan2", - "log" -]; -//Allow the 4 basic operations, parentheses and all numbers/decimals, as well -//as 'x', for the variable usage. -var WHITELISTER = "[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]"; -//add the math functions to the regex string. -for(var index = MATH_FUNCS.length - 1; index >= 0; --index) -{ - WHITELISTER += "|" + MATH_FUNCS[index]; +var PropertyList = /** @class */ (function () { + function PropertyList(isColor) { + if (isColor === void 0) { isColor = false; } + this.current = null; + this.next = null; + this.isColor = !!isColor; + this.interpolate = null; + this.ease = null; + } + /** + * Resets the list for use. + * @method interpolate + * @param {PIXI.particles.PropertyNode} first The first node in the list. + * @param {boolean} [isStepped=false] If the values should be stepped instead of interpolated linearly. + */ + PropertyList.prototype.reset = function (first) { + this.current = first; + this.next = first.next; + var isSimple = this.next && this.next.time >= 1; + if (isSimple) { + this.interpolate = this.isColor ? intColorSimple : intValueSimple; + } + else if (first.isStepped) { + this.interpolate = this.isColor ? intColorStepped : intValueStepped; + } + else { + this.interpolate = this.isColor ? intColorComplex : intValueComplex; + } + this.ease = this.current.ease; + }; + return PropertyList; +}()); +exports.default = PropertyList; +function intValueSimple(lerp) { + if (this.ease) + lerp = this.ease(lerp); + return (this.next.value - this.current.value) * lerp + this.current.value; +} +function intColorSimple(lerp) { + if (this.ease) + lerp = this.ease(lerp); + var curVal = this.current.value, nextVal = this.next.value; + var r = (nextVal.r - curVal.r) * lerp + curVal.r; + var g = (nextVal.g - curVal.g) * lerp + curVal.g; + var b = (nextVal.b - curVal.b) * lerp + curVal.b; + return ParticleUtils_1.default.combineRGBComponents(r, g, b); +} +function intValueComplex(lerp) { + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (lerp > this.next.time) { + this.current = this.next; + this.next = this.next.next; + } + //convert the lerp value to the segment range + lerp = (lerp - this.current.time) / (this.next.time - this.current.time); + return (this.next.value - this.current.value) * lerp + this.current.value; +} +function intColorComplex(lerp) { + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (lerp > this.next.time) { + this.current = this.next; + this.next = this.next.next; + } + //convert the lerp value to the segment range + lerp = (lerp - this.current.time) / (this.next.time - this.current.time); + var curVal = this.current.value, nextVal = this.next.value; + var r = (nextVal.r - curVal.r) * lerp + curVal.r; + var g = (nextVal.g - curVal.g) * lerp + curVal.g; + var b = (nextVal.b - curVal.b) * lerp + curVal.b; + return ParticleUtils_1.default.combineRGBComponents(r, g, b); +} +function intValueStepped(lerp) { + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (this.next && lerp > this.next.time) { + this.current = this.next; + this.next = this.next.next; + } + return this.current.value; +} +function intColorStepped(lerp) { + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (this.next && lerp > this.next.time) { + this.current = this.next; + this.next = this.next.next; + } + var curVal = this.current.value; + return ParticleUtils_1.default.combineRGBComponents(curVal.r, curVal.g, curVal.b); } -//create an actual regular expression object from the string -WHITELISTER = new RegExp(WHITELISTER, "g"); - -/** - * Parses a string into a function for path following. - * This involves whitelisting the string for safety, inserting "Math." to math function - * names, and using `new Function()` to generate a function. - * @method PIXI.particles.PathParticle~parsePath - * @private - * @static - * @param {String} pathString The string to parse. - * @return {Function} The path function - takes x, outputs y. - */ -var parsePath = function(pathString) -{ - var matches = pathString.match(WHITELISTER); - for(var i = matches.length - 1; i >= 0; --i) - { - if(MATH_FUNCS.indexOf(matches[i]) >= 0) - matches[i] = "Math." + matches[i]; - } - pathString = matches.join(""); - return new Function("x", "return "+ pathString + ";"); -}; - -/** - * Updates the particle. - * @method PIXI.particles.PathParticle#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - */ -p.update = function(delta) -{ - var lerp = this.Particle_update(delta); - //if the particle died during the update, then don't bother - if(lerp >= 0 && this.path) - { - //increase linear movement based on speed - var speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed; - this.movement += speed * delta; - //set up the helper point for rotation - helperPoint.x = this.movement; - helperPoint.y = this.path(this.movement); - ParticleUtils.rotatePoint(this.initialRotation, helperPoint); - this.position.x = this.initialPosition.x + helperPoint.x; - this.position.y = this.initialPosition.y + helperPoint.y; - } -}; - -p.Particle_destroy = Particle.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.PathParticle#destroy - */ -p.destroy = function() -{ - this.Particle_destroy(); - this.path = this.initialPosition = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. This just runs Particle.parseArt(). - * @method PIXI.particles.PathParticle.parseArt - * @static - * @param {Array} art The array of art data. For Particle, it should be an array of Textures. - * Any strings in the array will be converted to Textures via - * Texture.fromImage(). - * @return {Array} The art, after any needed modifications. - */ -PathParticle.parseArt = function(art) -{ - return Particle.parseArt(art); -}; +},{"./ParticleUtils":4}],7:[function(_dereq_,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_1 = _dereq_("./ParticleUtils"); /** - * Parses extra emitter data to ensure it is set up for this particle class. - * PathParticle checks for the existence of path data, and parses the path data for use - * by particle instances. - * @method PIXI.particles.PathParticle.parseData - * @static - * @param {Object} extraData The extra data from the particle config. - * @return {Object} The parsed extra data. + * A single node in a PropertyList. + * @memberof PIXI.particles + * @class PropertyNode + * @constructor + * @param {number|string} value The value for this node + * @param {number} time The time for this node, between 0-1 + * @param {Function|Array} [ease] Custom ease for this list. Only relevant for the first node. */ -PathParticle.parseData = function(extraData) -{ - var output = {}; - if(extraData && extraData.path) - { - try - { - output.path = parsePath(extraData.path); - } - catch(e) - { - if(ParticleUtils.verbose) - console.error("PathParticle: error in parsing path expression"); - output.path = null; - } - } - else - { - if(ParticleUtils.verbose) - console.error("PathParticle requires a path string in extraData!"); - output.path = null; - } - return output; -}; - -module.exports = PathParticle; -},{"./Particle":3,"./ParticleUtils":4}],6:[function(_dereq_,module,exports){ -//Nothing to deprecate right now! -},{}],7:[function(_dereq_,module,exports){ -exports.ParticleUtils = _dereq_("./ParticleUtils.js"); -exports.Particle = _dereq_("./Particle.js"); -exports.Emitter = _dereq_("./Emitter.js"); -exports.PathParticle = _dereq_("./PathParticle.js"); -exports.AnimatedParticle = _dereq_("./AnimatedParticle.js"); -_dereq_("./deprecation.js"); -},{"./AnimatedParticle.js":1,"./Emitter.js":2,"./Particle.js":3,"./ParticleUtils.js":4,"./PathParticle.js":5,"./deprecation.js":6}],8:[function(_dereq_,module,exports){ +var PropertyNode = /** @class */ (function () { + function PropertyNode(value, time, ease) { + this.value = typeof value == "string" ? ParticleUtils_1.default.hexToRGB(value) : value; + this.time = time; + this.next = null; + this.isStepped = false; + if (ease) { + this.ease = typeof ease == "function" ? ease : ParticleUtils_1.default.generateEase(ease); + } + else { + this.ease = null; + } + } + /** + * Creates a list of property values from a data object {list, isStepped} with a list of objects in + * the form {value, time}. Alternatively, the data object can be in the deprecated form of + * {start, end}. + * @method PIXI.particles.PropertyNode.createListFromArray + * @static + * @param {Object} data The data for the list. + * @param {Array} data.list The array of value and time objects. + * @param {boolean} [data.isStepped] If the list is stepped rather than interpolated. + * @param {Function|Array} [data.ease] Custom ease for this list. + * @return {PIXI.particles.PropertyNode} The first node in the list + */ + PropertyNode.createList = function (data) { + if (Array.isArray(data.list)) { + var array = data.list; + var node = void 0, first = void 0; + first = node = new PropertyNode(array[0].value, array[0].time, data.ease); + //only set up subsequent nodes if there are a bunch or the 2nd one is different from the first + if (array.length > 2 || (array.length === 2 && array[1].value !== array[0].value)) { + for (var i = 1; i < array.length; ++i) { + node.next = new PropertyNode(array[i].value, array[i].time); + node = node.next; + } + } + first.isStepped = !!data.isStepped; + return first; + } + else { + //Handle deprecated version here + var start = new PropertyNode(data.start, 0); + //only set up a next value if it is different from the starting value + if (data.end !== data.start) + start.next = new PropertyNode(data.end, 1); + return start; + } + }; + return PropertyNode; +}()); +exports.default = PropertyNode; + +},{"./ParticleUtils":4}],8:[function(_dereq_,module,exports){ "use strict"; - -// Check for window, fallback to global -var global = typeof window !== 'undefined' ? window : GLOBAL; - -//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not -if (!global.PIXI.particles) { - global.PIXI.particles = {}; -} - -// Export for Node-compatible environments like Electron -if (typeof module !== 'undefined' && module.exports) -{ - // Attempt to require the pixi module - if (typeof PIXI === 'undefined') - { - // Include the Pixi.js module - _dereq_('pixi.js'); - } - - // Export the module - module.exports = global.PIXI.particles || particles; -} +Object.defineProperty(exports, "__esModule", { value: true }); +var ParticleUtils_js_1 = _dereq_("./ParticleUtils.js"); +exports.ParticleUtils = ParticleUtils_js_1.default; +var Particle_js_1 = _dereq_("./Particle.js"); +exports.Particle = Particle_js_1.default; +var Emitter_js_1 = _dereq_("./Emitter.js"); +exports.Emitter = Emitter_js_1.default; +var PathParticle_js_1 = _dereq_("./PathParticle.js"); +exports.PathParticle = PathParticle_js_1.default; +var AnimatedParticle_js_1 = _dereq_("./AnimatedParticle.js"); +exports.AnimatedParticle = AnimatedParticle_js_1.default; + +},{"./AnimatedParticle.js":1,"./Emitter.js":2,"./Particle.js":3,"./ParticleUtils.js":4,"./PathParticle.js":5}],9:[function(_dereq_,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); // If we're in the browser make sure PIXI is available -else if (typeof PIXI === 'undefined') -{ - throw "pixi-particles requires pixi.js to be loaded first"; +if (typeof PIXI === 'undefined') { + throw "pixi-particles requires pixi.js to be loaded first"; +} +//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not +if (!PIXI.particles) { + PIXI.particles = {}; } - // get the library itself -var particles = _dereq_('./particles'); - -// insert the lirbary into the particles namespace on PIXI +var particles = _dereq_("./particles"); +// insert the library into the particles namespace on PIXI for (var prop in particles) { - global.PIXI.particles[prop] = particles[prop]; + PIXI.particles[prop] = particles[prop]; } -},{"./particles":7,"pixi.js":undefined}]},{},[8])(8) + +},{"./particles":8}]},{},[9])(9) }); diff --git a/dist/pixi-particles.js.map b/dist/pixi-particles.js.map index f4e89d72..e02a6d5c 100644 --- a/dist/pixi-particles.js.map +++ b/dist/pixi-particles.js.map @@ -1 +1 @@ -{"version":3,"sources":["node_modules/browser-pack/_prelude.js","src/AnimatedParticle.js","src/Emitter.js","src/Particle.js","src/ParticleUtils.js","src/PathParticle.js","src/deprecation.js","src/particles.js","src"],"names":[],"mappings":";;;;;;;AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACndA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrOA;;ACAA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"pixi-particles.js","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0)\n\t{\n\t\tthis.elapsed += delta;\n\t\tif(this.elapsed > this.duration)\n\t\t{\n\t\t\t//loop elapsed back around\n\t\t\tif(this.loop)\n\t\t\t\tthis.elapsed = this.elapsed % this.duration;\n\t\t\t//subtract a small amount to prevent attempting to go past the end of the animation\n\t\t\telse\n\t\t\t\tthis.elapsed = this.duration - 0.000001;\n\t\t}\n\t\tvar frame = (this.elapsed * this.framerate + 0.0000001) | 0;\n\t\tthis.texture = this.textures[frame] || ParticleUtils.EMPTY_TEXTURE;\n\t}\n};\n\np.Particle_destroy = Particle.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.AnimatedParticle#destroy\n */\np.destroy = function()\n{\n\tthis.Particle_destroy();\n\tthis.textures = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @method PIXI.particles.AnimatedParticle.parseArt\n * @static\n * @param {Array} art The array of art data, properly formatted for AnimatedParticle.\n * @return {Array} The art, after any needed modifications.\n */\nAnimatedParticle.parseArt = function(art)\n{\n\tvar i, data, output = [], j, textures, tex, outTextures;\n\tfor(i = 0; i < art.length; ++i)\n\t{\n\t\tdata = art[i];\n\t\tart[i] = output = {};\n\t\toutput.textures = outTextures = [];\n\t\ttextures = data.textures;\n\t\tfor(j = 0; j < textures.length; ++j)\n\t\t{\n\t\t\ttex = textures[j];\n\t\t\tif(typeof tex == \"string\")\n\t\t\t\toutTextures.push(Texture.fromImage(tex));\n\t\t\telse if(tex instanceof Texture)\n\t\t\t\toutTextures.push(tex);\n\t\t\t//assume an object with extra data determining duplicate frame data\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar dupe = tex.count || 1;\n\t\t\t\tif(typeof tex.texture == \"string\")\n\t\t\t\t\ttex = Texture.fromImage(tex.texture);\n\t\t\t\telse// if(tex.texture instanceof Texture)\n\t\t\t\t\ttex = tex.texture;\n\t\t\t\tfor(; dupe > 0; --dupe)\n\t\t\t\t{\n\t\t\t\t\toutTextures.push(tex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//use these values to signify that the animation should match the particle life time.\n\t\tif(data.framerate == \"matchLife\")\n\t\t{\n\t\t\t//-1 means that it should be calculated\n\t\t\toutput.framerate = -1;\n\t\t\toutput.duration = 0;\n\t\t\toutput.loop = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//determine if the animation should loop\n\t\t\toutput.loop = !!data.loop;\n\t\t\t//get the framerate, default to 60\n\t\t\toutput.framerate = data.framerate > 0 ? data.framerate : 60;\n\t\t\t//determine the duration\n\t\t\toutput.duration = outTextures.length / output.framerate;\n\t\t}\n\t}\n\n\treturn art;\n};\n\nmodule.exports = AnimatedParticle;","\"use strict\";\n\nvar ParticleUtils = require(\"./ParticleUtils\"),\n\tParticle = require(\"./Particle\"),\n\tParticleContainer = PIXI.particles.ParticleContainer || PIXI.ParticleContainer,\n\tticker = PIXI.ticker.shared;\n\n/**\n * A particle emitter.\n * @memberof PIXI.particles\n * @class Emitter\n * @constructor\n * @param {PIXI.Container} particleParent The container to add the\n * particles to.\n * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use\n * for the particles. Strings will be turned\n * into textures via Texture.fromImage().\n * @param {Object} [config] A configuration object containing settings for the emitter.\n * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter\n * will start disabled.\n * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter\n * will automatically call update via the PIXI shared ticker.\n */\nvar Emitter = function(particleParent, particleImages, config)\n{\n\t/**\n\t * The constructor used to create new particles. The default is\n\t * the built in particle class.\n\t * @property {Function} _particleConstructor\n\t * @private\n\t */\n\tthis._particleConstructor = Particle;\n\t//properties for individual particles\n\t/**\n\t * An array of PIXI Texture objects.\n\t * @property {Array} particleImages\n\t */\n\tthis.particleImages = null;\n\t/**\n\t * The starting alpha of all particles.\n\t * @property {Number} startAlpha\n\t * @default 1\n\t */\n\tthis.startAlpha = 1;\n\t/**\n\t * The ending alpha of all particles.\n\t * @property {Number} endAlpha\n\t * @default 1\n\t */\n\tthis.endAlpha = 1;\n\t/**\n\t * The starting speed of all particles.\n\t * @property {Number} startSpeed\n\t * @default 0\n\t */\n\tthis.startSpeed = 0;\n\t/**\n\t * The ending speed of all particles.\n\t * @property {Number} endSpeed\n\t * @default 0\n\t */\n\tthis.endSpeed = 0;\n\t/**\n\t * A minimum multiplier for the speed of a particle at both start and\n\t * end. A value between minimumSpeedMultiplier and 1 is randomly generated\n\t * and multiplied with startSpeed and endSpeed to provide the actual\n\t * startSpeed and endSpeed for each particle.\n\t * @property {Number} minimumSpeedMultiplier\n\t * @default 1\n\t */\n\tthis.minimumSpeedMultiplier = 1;\n\t/**\n\t * Acceleration to apply to particles. Using this disables\n\t * any interpolation of particle speed. If the particles do\n\t * not have a rotation speed, then they will be rotated to\n\t * match the direction of travel.\n\t * @property {PIXI.Point} acceleration\n\t * @default null\n\t */\n\tthis.acceleration = null;\n\t/**\n\t * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n\t * will disable the maximum speed.\n\t * @property {Number} maxSpeed\n\t * @default NaN\n\t */\n\tthis.maxSpeed = NaN;\n\t/**\n\t * The starting scale of all particles.\n\t * @property {Number} startScale\n\t * @default 1\n\t */\n\tthis.startScale = 1;\n\t/**\n\t * The ending scale of all particles.\n\t * @property {Number} endScale\n\t * @default 1\n\t */\n\tthis.endScale = 1;\n\t/**\n\t * A minimum multiplier for the scale of a particle at both start and\n\t * end. A value between minimumScaleMultiplier and 1 is randomly generated\n\t * and multiplied with startScale and endScale to provide the actual\n\t * startScale and endScale for each particle.\n\t * @property {Number} minimumScaleMultiplier\n\t * @default 1\n\t */\n\tthis.minimumScaleMultiplier = 1;\n\t/**\n\t * The starting color of all particles, as red, green, and blue uints from 0-255.\n\t * @property {Array} startColor\n\t */\n\tthis.startColor = null;\n\t/**\n\t * The ending color of all particles, as red, green, and blue uints from 0-255.\n\t * @property {Array} endColor\n\t */\n\tthis.endColor = null;\n\t/**\n\t * The minimum lifetime for a particle, in seconds.\n\t * @property {Number} minLifetime\n\t */\n\tthis.minLifetime = 0;\n\t/**\n\t * The maximum lifetime for a particle, in seconds.\n\t * @property {Number} maxLifetime\n\t */\n\tthis.maxLifetime = 0;\n\t/**\n\t * The minimum start rotation for a particle, in degrees. This value\n\t * is ignored if the spawn type is \"burst\" or \"arc\".\n\t * @property {Number} minStartRotation\n\t */\n\tthis.minStartRotation = 0;\n\t/**\n\t * The maximum start rotation for a particle, in degrees. This value\n\t * is ignored if the spawn type is \"burst\" or \"arc\".\n\t * @property {Number} maxStartRotation\n\t */\n\tthis.maxStartRotation = 0;\n\t/**\n\t * If no particle rotation should occur. Starting rotation will still\n\t * affect the direction in which particles move. If the rotation speed\n\t * is set, then this will be ignored.\n\t * @property {Boolean} maxStartRotation\n\t */\n\tthis.noRotation = false;\n\t/**\n\t * The minimum rotation speed for a particle, in degrees per second.\n\t * This only visually spins the particle, it does not change direction\n\t * of movement.\n\t * @property {Number} minRotationSpeed\n\t */\n\tthis.minRotationSpeed = 0;\n\t/**\n\t * The maximum rotation speed for a particle, in degrees per second.\n\t * This only visually spins the particle, it does not change direction\n\t * of movement.\n\t * @property {Number} maxRotationSpeed\n\t */\n\tthis.maxRotationSpeed = 0;\n\t/**\n\t * The blend mode for all particles, as named by PIXI.blendModes.\n\t * @property {int} particleBlendMode\n\t */\n\tthis.particleBlendMode = 0;\n\t/**\n\t * An easing function for nonlinear interpolation of values. Accepts a single\n\t * parameter of time as a value from 0-1, inclusive. Expected outputs are values\n\t * from 0-1, inclusive.\n\t * @property {Function} customEase\n\t */\n\tthis.customEase = null;\n\t/**\n\t *\tExtra data for use in custom particles. The emitter doesn't look inside, but\n\t *\tpasses it on to the particle to use in init().\n\t *\t@property {Object} extraData\n\t */\n\tthis.extraData = null;\n\t//properties for spawning particles\n\t/**\n\t * Time between particle spawns in seconds.\n\t * @property {Number} _frequency\n\t * @private\n\t */\n\tthis._frequency = 1;\n\t/**\n\t * Maximum number of particles to keep alive at a time. If this limit\n\t * is reached, no more particles will spawn until some have died.\n\t * @property {int} maxParticles\n\t * @default 1000\n\t */\n\tthis.maxParticles = 1000;\n\t/**\n\t * The amount of time in seconds to emit for before setting emit to false.\n\t * A value of -1 is an unlimited amount of time.\n\t * @property {Number} emitterLifetime\n\t * @default -1\n\t */\n\tthis.emitterLifetime = -1;\n\t/**\n\t * Position at which to spawn particles, relative to the emitter's owner's origin.\n\t * For example, the flames of a rocket travelling right might have a spawnPos\n\t * of {x:-50, y:0}.\n\t * to spawn at the rear of the rocket.\n\t * To change this, use updateSpawnPos().\n\t * @property {PIXI.Point} spawnPos\n\t * @readOnly\n\t */\n\tthis.spawnPos = null;\n\t/**\n\t * How the particles will be spawned. Valid types are \"point\", \"rectangle\",\n\t * \"circle\", \"burst\", \"ring\".\n\t * @property {String} spawnType\n\t * @readOnly\n\t */\n\tthis.spawnType = null;\n\t/**\n\t * A reference to the emitter function specific to the spawn type.\n\t * @property {Function} _spawnFunc\n\t * @private\n\t */\n\tthis._spawnFunc = null;\n\t/**\n\t * A rectangle relative to spawnPos to spawn particles inside if the spawn type is \"rect\".\n\t * @property {PIXI.Rectangle} spawnRect\n\t */\n\tthis.spawnRect = null;\n\t/**\n\t * A circle relative to spawnPos to spawn particles inside if the spawn type is \"circle\".\n\t * @property {PIXI.Circle} spawnCircle\n\t */\n\tthis.spawnCircle = null;\n\t/**\n\t * Number of particles to spawn each wave in a burst.\n\t * @property {int} particlesPerWave\n\t * @default 1\n\t */\n\tthis.particlesPerWave = 1;\n\t/**\n\t * Spacing between particles in a burst. 0 gives a random angle for each particle.\n\t * @property {Number} particleSpacing\n\t * @default 0\n\t */\n\tthis.particleSpacing = 0;\n\t/**\n\t * Angle at which to start spawning particles in a burst.\n\t * @property {Number} angleStart\n\t * @default 0\n\t */\n\tthis.angleStart = 0;\n\t/**\n\t * Rotation of the emitter or emitter's owner in degrees. This is added to\n\t * the calculated spawn angle.\n\t * To change this, use rotate().\n\t * @property {Number} rotation\n\t * @default 0\n\t * @readOnly\n\t */\n\tthis.rotation = 0;\n\t/**\n\t * The world position of the emitter's owner, to add spawnPos to when\n\t * spawning particles. To change this, use updateOwnerPos().\n\t * @property {PIXI.Point} ownerPos\n\t * @default {x:0, y:0}\n\t * @readOnly\n\t */\n\tthis.ownerPos = null;\n\t/**\n\t * The origin + spawnPos in the previous update, so that the spawn position\n\t * can be interpolated to space out particles better.\n\t * @property {PIXI.Point} _prevEmitterPos\n\t * @private\n\t */\n\tthis._prevEmitterPos = null;\n\t/**\n\t * If _prevEmitterPos is valid, to prevent interpolation on the first update\n\t * @property {Boolean} _prevPosIsValid\n\t * @private\n\t * @default false\n\t */\n\tthis._prevPosIsValid = false;\n\t/**\n\t * If either ownerPos or spawnPos has changed since the previous update.\n\t * @property {Boolean} _posChanged\n\t * @private\n\t */\n\tthis._posChanged = false;\n\t/**\n\t * If the parent is a ParticleContainer from Pixi V3\n\t * @property {Boolean} _parentIsPC\n\t * @private\n\t */\n\tthis._parentIsPC = false;\n\t/**\n\t * The container to add particles to.\n\t * @property {PIXI.Container} _parent\n\t * @private\n\t */\n\tthis._parent = null;\n\t/**\n\t * If particles should be added at the back of the display list instead of the front.\n\t * @property {Boolean} addAtBack\n\t */\n\tthis.addAtBack = false;\n\t/**\n\t * The current number of active particles.\n\t * @property {Number} particleCount\n\t * @readOnly\n\t */\n\tthis.particleCount = 0;\n\t/**\n\t * If particles should be emitted during update() calls. Setting this to false\n\t * stops new particles from being created, but allows existing ones to die out.\n\t * @property {Boolean} _emit\n\t * @private\n\t */\n\tthis._emit = false;\n\t/**\n\t * The timer for when to spawn particles in seconds, where numbers less\n\t * than 0 mean that particles should be spawned.\n\t * @property {Number} _spawnTimer\n\t * @private\n\t */\n\tthis._spawnTimer = 0;\n\t/**\n\t * The life of the emitter in seconds.\n\t * @property {Number} _emitterLife\n\t * @private\n\t */\n\tthis._emitterLife = -1;\n\t/**\n\t * The particles that are active and on the display list. This is the first particle in a\n\t * linked list.\n\t * @property {Particle} _activeParticlesFirst\n\t * @private\n\t */\n\tthis._activeParticlesFirst = null;\n\t/**\n\t * The particles that are active and on the display list. This is the last particle in a\n\t * linked list.\n\t * @property {Particle} _activeParticlesLast\n\t * @private\n\t */\n\tthis._activeParticlesLast = null;\n\t/**\n\t * The particles that are not currently being used. This is the first particle in a\n\t * linked list.\n\t * @property {Particle} _poolFirst\n\t * @private\n\t */\n\tthis._poolFirst = null;\n\t/**\n\t * The original config object that this emitter was initialized with.\n\t * @property {Object} _origConfig\n\t * @private\n\t */\n\tthis._origConfig = null;\n\t/**\n\t * The original particle image data that this emitter was initialized with.\n\t * @property {PIXI.Texture|Array|String} _origArt\n\t * @private\n\t */\n\tthis._origArt = null;\n\t/**\n\t * If the update function is called automatically from the shared ticker.\n\t * Setting this to false requires calling the update function manually.\n\t * @property {Boolean} _autoUpdate\n\t * @private\n\t */\n\tthis._autoUpdate = false;\n\t/**\n\t * If the emitter should destroy itself when all particles have died out. This is set by\n\t * playOnceAndDestroy();\n\t * @property {Boolean} _destroyWhenComplete\n\t * @private\n\t */\n\tthis._destroyWhenComplete = false;\n\t/**\n\t * A callback for when all particles have died out. This is set by\n\t * playOnceAndDestroy() or playOnce();\n\t * @property {Function} _completeCallback\n\t * @private\n\t */\n\tthis._completeCallback = null;\n\n\t//set the initial parent\n\tthis.parent = particleParent;\n\n\tif(particleImages && config)\n\t\tthis.init(particleImages, config);\n\n\t//save often used functions on the instance instead of the prototype for better speed\n\tthis.recycle = this.recycle;\n\tthis.update = this.update;\n\tthis.rotate = this.rotate;\n\tthis.updateSpawnPos = this.updateSpawnPos;\n\tthis.updateOwnerPos = this.updateOwnerPos;\n};\n\n// Reference to the prototype\nvar p = Emitter.prototype = {};\n\nvar helperPoint = new PIXI.Point();\n\n/**\n * Time between particle spawns in seconds. If this value is not a number greater than 0,\n * it will be set to 1 (particle per second) to prevent infinite loops.\n * @member {Number} PIXI.particles.Emitter#frequency\n */\nObject.defineProperty(p, \"frequency\",\n{\n\tget: function() { return this._frequency; },\n\tset: function(value)\n\t{\n\t\t//do some error checking to prevent infinite loops\n\t\tif(typeof value == \"number\" && value > 0)\n\t\t\tthis._frequency = value;\n\t\telse\n\t\t\tthis._frequency = 1;\n\t}\n});\n\n/**\n * The constructor used to create new particles. The default is\n * the built in Particle class. Setting this will dump any active or\n * pooled particles, if the emitter has already been used.\n * @member {Function} PIXI.particles.Emitter#particleConstructor\n */\nObject.defineProperty(p, \"particleConstructor\",\n{\n\tget: function() { return this._particleConstructor; },\n\tset: function(value)\n\t{\n\t\tif(value != this._particleConstructor)\n\t\t{\n\t\t\tthis._particleConstructor = value;\n\t\t\t//clean up existing particles\n\t\t\tthis.cleanup();\n\t\t\t//scrap all the particles\n\t\t\tfor (var particle = this._poolFirst; particle; particle = particle.next)\n\t\t\t{\n\t\t\t\tparticle.destroy();\n\t\t\t}\n\t\t\tthis._poolFirst = null;\n\t\t\t//re-initialize the emitter so that the new constructor can do anything it needs to\n\t\t\tif(this._origConfig && this._origArt)\n\t\t\t\tthis.init(this._origArt, this._origConfig);\n\t\t}\n\t}\n});\n\n/**\n* The container to add particles to. Settings this will dump any active particles.\n* @member {PIXI.Container} PIXI.particles.Emitter#parent\n*/\nObject.defineProperty(p, \"parent\",\n{\n\tget: function() { return this._parent; },\n\tset: function(value)\n\t{\n\t\t//if our previous parent was a ParticleContainer, then we need to remove\n\t\t//pooled particles from it\n\t\tif (this._parentIsPC) {\n\t\t\tfor (var particle = this._poolFirst; particle; particle = particle.next)\n\t\t\t{\n\t\t\t\tif(particle.parent)\n\t\t\t\t\tparticle.parent.removeChild(particle);\n\t\t\t}\n\t\t}\n\t\tthis.cleanup();\n\t\tthis._parent = value;\n\t\tthis._parentIsPC = ParticleContainer && value && value instanceof ParticleContainer;\n\t}\n});\n\n/**\n * Sets up the emitter based on the config settings.\n * @method PIXI.particles.Emitter#init\n * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles.\n * @param {Object} config A configuration object containing settings for the emitter.\n */\np.init = function(art, config)\n{\n\tif(!art || !config)\n\t\treturn;\n\t//clean up any existing particles\n\tthis.cleanup();\n\n\t//store the original config and particle images, in case we need to re-initialize\n\t//when the particle constructor is changed\n\tthis._origConfig = config;\n\tthis._origArt = art;\n\n\t//set up the array of data, also ensuring that it is an array\n\tart = Array.isArray(art) ? art.slice() : [art];\n\t//run the art through the particle class's parsing function\n\tvar partClass = this._particleConstructor;\n\tthis.particleImages = partClass.parseArt ? partClass.parseArt(art) : art;\n\t///////////////////////////\n\t// Particle Properties //\n\t///////////////////////////\n\t//set up the alpha\n\tif (config.alpha)\n\t{\n\t\tthis.startAlpha = config.alpha.start;\n\t\tthis.endAlpha = config.alpha.end;\n\t}\n\telse\n\t\tthis.startAlpha = this.endAlpha = 1;\n\t//set up the speed\n\tif (config.speed)\n\t{\n\t\tthis.startSpeed = config.speed.start;\n\t\tthis.endSpeed = config.speed.end;\n\t\tthis.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1;\n\t}\n\telse\n\t{\n\t\tthis.minimumSpeedMultiplier = 1;\n\t\tthis.startSpeed = this.endSpeed = 0;\n\t}\n\t//set up acceleration\n\tvar acceleration = config.acceleration;\n\tif(acceleration && (acceleration.x || acceleration.y))\n\t{\n\t\tthis.endSpeed = this.startSpeed;\n\t\tthis.acceleration = new PIXI.Point(acceleration.x, acceleration.y);\n\t\tthis.maxSpeed = config.maxSpeed || NaN;\n\t}\n\telse\n\t\tthis.acceleration = new PIXI.Point();\n\t//set up the scale\n\tif (config.scale)\n\t{\n\t\tthis.startScale = config.scale.start;\n\t\tthis.endScale = config.scale.end;\n\t\tthis.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1;\n\t}\n\telse\n\t\tthis.startScale = this.endScale = this.minimumScaleMultiplier = 1;\n\t//set up the color\n\tif (config.color)\n\t{\n\t\tthis.startColor = ParticleUtils.hexToRGB(config.color.start);\n\t\t//if it's just one color, only use the start color\n\t\tif (config.color.start != config.color.end)\n\t\t{\n\t\t\tthis.endColor = ParticleUtils.hexToRGB(config.color.end);\n\t\t}\n\t\telse\n\t\t\tthis.endColor = null;\n\t}\n\t//set up the start rotation\n\tif (config.startRotation)\n\t{\n\t\tthis.minStartRotation = config.startRotation.min;\n\t\tthis.maxStartRotation = config.startRotation.max;\n\t}\n\telse\n\t\tthis.minStartRotation = this.maxStartRotation = 0;\n\tif (config.noRotation &&\n\t\t(this.minStartRotation || this.maxStartRotation))\n\t{\n\t\tthis.noRotation = !!config.noRotation;\n\t}\n\telse\n\t\tthis.noRotation = false;\n\t//set up the rotation speed\n\tif (config.rotationSpeed)\n\t{\n\t\tthis.minRotationSpeed = config.rotationSpeed.min;\n\t\tthis.maxRotationSpeed = config.rotationSpeed.max;\n\t}\n\telse\n\t\tthis.minRotationSpeed = this.maxRotationSpeed = 0;\n\t//set up the lifetime\n\tthis.minLifetime = config.lifetime.min;\n\tthis.maxLifetime = config.lifetime.max;\n\t//get the blend mode\n\tthis.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode);\n\t//use the custom ease if provided\n\tif (config.ease)\n\t{\n\t\tthis.customEase = typeof config.ease == \"function\" ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tconfig.ease :\n\t\t\t\t\t\t\t\t\t\t\t\t\tParticleUtils.generateEase(config.ease);\n\t}\n\telse\n\t\tthis.customEase = null;\n\t//set up the extra data, running it through the particle class's parseData function.\n\tif(partClass.parseData)\n\t\tthis.extraData = partClass.parseData(config.extraData);\n\telse\n\t\tthis.extraData = config.extraData || null;\n\t//////////////////////////\n\t// Emitter Properties //\n\t//////////////////////////\n\t//reset spawn type specific settings\n\tthis.spawnRect = this.spawnCircle = null;\n\tthis.particlesPerWave = 1;\n\tthis.particleSpacing = 0;\n\tthis.angleStart = 0;\n\tvar spawnCircle;\n\t//determine the spawn function to use\n\tswitch(config.spawnType)\n\t{\n\t\tcase \"rect\":\n\t\t\tthis.spawnType = \"rect\";\n\t\t\tthis._spawnFunc = this._spawnRect;\n\t\t\tvar spawnRect = config.spawnRect;\n\t\t\tthis.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);\n\t\t\tbreak;\n\t\tcase \"circle\":\n\t\t\tthis.spawnType = \"circle\";\n\t\t\tthis._spawnFunc = this._spawnCircle;\n\t\t\tspawnCircle = config.spawnCircle;\n\t\t\tthis.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\n\t\t\tbreak;\n\t\tcase \"ring\":\n\t\t\tthis.spawnType = \"ring\";\n\t\t\tthis._spawnFunc = this._spawnRing;\n\t\t\tspawnCircle = config.spawnCircle;\n\t\t\tthis.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\n\t\t\tthis.spawnCircle.minRadius = spawnCircle.minR;\n\t\t\tbreak;\n\t\tcase \"burst\":\n\t\t\tthis.spawnType = \"burst\";\n\t\t\tthis._spawnFunc = this._spawnBurst;\n\t\t\tthis.particlesPerWave = config.particlesPerWave;\n\t\t\tthis.particleSpacing = config.particleSpacing;\n\t\t\tthis.angleStart = config.angleStart ? config.angleStart : 0;\n\t\t\tbreak;\n\t\tcase \"point\":\n\t\t\tthis.spawnType = \"point\";\n\t\t\tthis._spawnFunc = this._spawnPoint;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthis.spawnType = \"point\";\n\t\t\tthis._spawnFunc = this._spawnPoint;\n\t\t\tbreak;\n\t}\n\t//set the spawning frequency\n\tthis.frequency = config.frequency;\n\t//set the emitter lifetime\n\tthis.emitterLifetime = config.emitterLifetime || -1;\n\t//set the max particles\n\tthis.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000;\n\t//determine if we should add the particle at the back of the list or not\n\tthis.addAtBack = !!config.addAtBack;\n\t//reset the emitter position and rotation variables\n\tthis.rotation = 0;\n\tthis.ownerPos = new PIXI.Point();\n\tthis.spawnPos = new PIXI.Point(config.pos.x, config.pos.y);\n\tthis._prevEmitterPos = this.spawnPos.clone();\n\t//previous emitter position is invalid and should not be used for interpolation\n\tthis._prevPosIsValid = false;\n\t//start emitting\n\tthis._spawnTimer = 0;\n\tthis.emit = config.emit === undefined ? true : !!config.emit;\n\tthis.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate;\n};\n\n/**\n * Recycles an individual particle.\n * @method PIXI.particles.Emitter#recycle\n * @param {Particle} particle The particle to recycle.\n * @private\n */\np.recycle = function(particle)\n{\n\tif(particle.next)\n\t\tparticle.next.prev = particle.prev;\n\tif(particle.prev)\n\t\tparticle.prev.next = particle.next;\n\tif(particle == this._activeParticlesLast)\n\t\tthis._activeParticlesLast = particle.prev;\n\tif(particle == this._activeParticlesFirst)\n\t\tthis._activeParticlesFirst = particle.next;\n\t//add to pool\n\tparticle.prev = null;\n\tparticle.next = this._poolFirst;\n\tthis._poolFirst = particle;\n\t//remove child from display, or make it invisible if it is in a ParticleContainer\n\tif(this._parentIsPC)\n\t{\n\t\tparticle.alpha = 0;\n\t\tparticle.visible = false;\n\t}\n\telse\n\t{\n\t\tif(particle.parent)\n\t\t\tparticle.parent.removeChild(particle);\n\t}\n\t//decrease count\n\t--this.particleCount;\n};\n\n/**\n * Sets the rotation of the emitter to a new value.\n * @method PIXI.particles.Emitter#rotate\n * @param {Number} newRot The new rotation, in degrees.\n */\np.rotate = function(newRot)\n{\n\tif (this.rotation == newRot) return;\n\t//caclulate the difference in rotation for rotating spawnPos\n\tvar diff = newRot - this.rotation;\n\tthis.rotation = newRot;\n\t//rotate spawnPos\n\tParticleUtils.rotatePoint(diff, this.spawnPos);\n\t//mark the position as having changed\n\tthis._posChanged = true;\n};\n\n/**\n * Changes the spawn position of the emitter.\n * @method PIXI.particles.Emitter#updateSpawnPos\n * @param {Number} x The new x value of the spawn position for the emitter.\n * @param {Number} y The new y value of the spawn position for the emitter.\n */\np.updateSpawnPos = function(x, y)\n{\n\tthis._posChanged = true;\n\tthis.spawnPos.x = x;\n\tthis.spawnPos.y = y;\n};\n\n/**\n * Changes the position of the emitter's owner. You should call this if you are adding\n * particles to the world container that your emitter's owner is moving around in.\n * @method PIXI.particles.Emitter#updateOwnerPos\n * @param {Number} x The new x value of the emitter's owner.\n * @param {Number} y The new y value of the emitter's owner.\n */\np.updateOwnerPos = function(x, y)\n{\n\tthis._posChanged = true;\n\tthis.ownerPos.x = x;\n\tthis.ownerPos.y = y;\n};\n\n/**\n * Prevents emitter position interpolation in the next update.\n * This should be used if you made a major position change of your emitter's owner\n * that was not normal movement.\n * @method PIXI.particles.Emitter#resetPositionTracking\n */\np.resetPositionTracking = function()\n{\n\tthis._prevPosIsValid = false;\n};\n\n/**\n * If particles should be emitted during update() calls. Setting this to false\n * stops new particles from being created, but allows existing ones to die out.\n * @member {Boolean} PIXI.particles.Emitter#emit\n */\nObject.defineProperty(p, \"emit\",\n{\n\tget: function() { return this._emit; },\n\tset: function(value)\n\t{\n\t\tthis._emit = !!value;\n\t\tthis._emitterLife = this.emitterLifetime;\n\t}\n});\n\n/**\n * If the update function is called automatically from the shared ticker.\n * Setting this to false requires calling the update function manually.\n * @member {Boolean} PIXI.particles.Emitter#autoUpdate\n */\nObject.defineProperty(p, \"autoUpdate\",\n{\n\tget: function() { return this._autoUpdate; },\n\tset: function(value)\n\t{\n\t\tif (this._autoUpdate && !value)\n\t\t{\n\t\t\tticker.remove(this.update, this);\n\t\t}\n\t\telse if (!this._autoUpdate && value)\n\t\t{\n\t\t\tticker.add(this.update, this);\n\t\t}\n\t\tthis._autoUpdate = !!value;\n\t}\n});\n\n/**\n * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself\n * when particle emission is complete.\n * @method PIXI.particles.Emitter#playOnceAndDestroy\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\n */\np.playOnceAndDestroy = function(callback)\n{\n\tthis.autoUpdate = true;\n\tthis.emit = true;\n\tthis._destroyWhenComplete = true;\n\tthis._completeCallback = callback;\n};\n\n/**\n * Starts emitting particles, sets autoUpdate to true, and optionally calls a callback\n * when particle emission is complete.\n * @method PIXI.particles.Emitter#playOnce\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\n */\np.playOnce = function(callback)\n{\n\tthis.autoUpdate = true;\n\tthis.emit = true;\n\tthis._completeCallback = callback;\n};\n\n/**\n * Updates all particles spawned by this emitter and emits new ones.\n * @method PIXI.particles.Emitter#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n */\np.update = function(delta)\n{\n\tif (this._autoUpdate)\n\t{\n\t\tdelta = delta / PIXI.settings.TARGET_FPMS / 1000;\n\t}\n\n\t//if we don't have a parent to add particles to, then don't do anything.\n\t//this also works as a isDestroyed check\n\tif (!this._parent) return;\n\t//update existing particles\n\tvar i, particle, next;\n\tfor (particle = this._activeParticlesFirst; particle; particle = next)\n\t{\n\t\tnext = particle.next;\n\t\tparticle.update(delta);\n\t}\n\tvar prevX, prevY;\n\t//if the previous position is valid, store these for later interpolation\n\tif(this._prevPosIsValid)\n\t{\n\t\tprevX = this._prevEmitterPos.x;\n\t\tprevY = this._prevEmitterPos.y;\n\t}\n\t//store current position of the emitter as local variables\n\tvar curX = this.ownerPos.x + this.spawnPos.x;\n\tvar curY = this.ownerPos.y + this.spawnPos.y;\n\t//spawn new particles\n\tif (this._emit)\n\t{\n\t\t//decrease spawn timer\n\t\tthis._spawnTimer -= delta;\n\t\t//while _spawnTimer < 0, we have particles to spawn\n\t\twhile(this._spawnTimer <= 0)\n\t\t{\n\t\t\t//determine if the emitter should stop spawning\n\t\t\tif(this._emitterLife > 0)\n\t\t\t{\n\t\t\t\tthis._emitterLife -= this._frequency;\n\t\t\t\tif(this._emitterLife <= 0)\n\t\t\t\t{\n\t\t\t\t\tthis._spawnTimer = 0;\n\t\t\t\t\tthis._emitterLife = 0;\n\t\t\t\t\tthis.emit = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//determine if we have hit the particle limit\n\t\t\tif(this.particleCount >= this.maxParticles)\n\t\t\t{\n\t\t\t\tthis._spawnTimer += this._frequency;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t//determine the particle lifetime\n\t\t\tvar lifetime;\n\t\t\tif (this.minLifetime == this.maxLifetime)\n\t\t\t\tlifetime = this.minLifetime;\n\t\t\telse\n\t\t\t\tlifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime;\n\t\t\t//only make the particle if it wouldn't immediately destroy itself\n\t\t\tif(-this._spawnTimer < lifetime)\n\t\t\t{\n\t\t\t\t//If the position has changed and this isn't the first spawn,\n\t\t\t\t//interpolate the spawn position\n\t\t\t\tvar emitPosX, emitPosY;\n\t\t\t\tif (this._prevPosIsValid && this._posChanged)\n\t\t\t\t{\n\t\t\t\t\t//1 - _spawnTimer / delta, but _spawnTimer is negative\n\t\t\t\t\tvar lerp = 1 + this._spawnTimer / delta;\n\t\t\t\t\temitPosX = (curX - prevX) * lerp + prevX;\n\t\t\t\t\temitPosY = (curY - prevY) * lerp + prevY;\n\t\t\t\t}\n\t\t\t\telse//otherwise just set to the spawn position\n\t\t\t\t{\n\t\t\t\t\temitPosX = curX;\n\t\t\t\t\temitPosY = curY;\n\t\t\t\t}\n\t\t\t\t//create enough particles to fill the wave (non-burst types have a wave of 1)\n\t\t\t\ti = 0;\n\t\t\t\tfor(var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i)\n\t\t\t\t{\n\t\t\t\t\t//create particle\n\t\t\t\t\tvar p, rand;\n\t\t\t\t\tif(this._poolFirst)\n\t\t\t\t\t{\n\t\t\t\t\t\tp = this._poolFirst;\n\t\t\t\t\t\tthis._poolFirst = this._poolFirst.next;\n\t\t\t\t\t\tp.next = null;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp = new this.particleConstructor(this);\n\t\t\t\t\t}\n\n\t\t\t\t\t//set a random texture if we have more than one\n\t\t\t\t\tif(this.particleImages.length > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tp.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//if they are actually the same texture, a standard particle\n\t\t\t\t\t\t//will quit early from the texture setting in setTexture().\n\t\t\t\t\t\tp.applyArt(this.particleImages[0]);\n\t\t\t\t\t}\n\t\t\t\t\t//set up the start and end values\n\t\t\t\t\tp.startAlpha = this.startAlpha;\n\t\t\t\t\tp.endAlpha = this.endAlpha;\n\t\t\t\t\tif(this.minimumSpeedMultiplier != 1)\n\t\t\t\t\t{\n\t\t\t\t\t\trand = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier;\n\t\t\t\t\t\tp.startSpeed = this.startSpeed * rand;\n\t\t\t\t\t\tp.endSpeed = this.endSpeed * rand;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp.startSpeed = this.startSpeed;\n\t\t\t\t\t\tp.endSpeed = this.endSpeed;\n\t\t\t\t\t}\n\t\t\t\t\tp.acceleration.x = this.acceleration.x;\n\t\t\t\t\tp.acceleration.y = this.acceleration.y;\n\t\t\t\t\tp.maxSpeed = this.maxSpeed;\n\t\t\t\t\tif(this.minimumScaleMultiplier != 1)\n\t\t\t\t\t{\n\t\t\t\t\t\trand = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier;\n\t\t\t\t\t\tp.startScale = this.startScale * rand;\n\t\t\t\t\t\tp.endScale = this.endScale * rand;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp.startScale = this.startScale;\n\t\t\t\t\t\tp.endScale = this.endScale;\n\t\t\t\t\t}\n\t\t\t\t\tp.startColor = this.startColor;\n\t\t\t\t\tp.endColor = this.endColor;\n\t\t\t\t\t//randomize the rotation speed\n\t\t\t\t\tif(this.minRotationSpeed == this.maxRotationSpeed)\n\t\t\t\t\t\tp.rotationSpeed = this.minRotationSpeed;\n\t\t\t\t\telse\n\t\t\t\t\t\tp.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed;\n\t\t\t\t\tp.noRotation = this.noRotation;\n\t\t\t\t\t//set up the lifetime\n\t\t\t\t\tp.maxLife = lifetime;\n\t\t\t\t\t//set the blend mode\n\t\t\t\t\tp.blendMode = this.particleBlendMode;\n\t\t\t\t\t//set the custom ease, if any\n\t\t\t\t\tp.ease = this.customEase;\n\t\t\t\t\t//set the extra data, if any\n\t\t\t\t\tp.extraData = this.extraData;\n\t\t\t\t\t//call the proper function to handle rotation and position of particle\n\t\t\t\t\tthis._spawnFunc(p, emitPosX, emitPosY, i);\n\t\t\t\t\t//initialize particle\n\t\t\t\t\tp.init();\n\t\t\t\t\t//update the particle by the time passed, so the particles are spread out properly\n\t\t\t\t\tp.update(-this._spawnTimer);//we want a positive delta, because a negative delta messes things up\n\t\t\t\t\t//add the particle to the display list\n\t\t\t\t\tif(!this._parentIsPC || !p.parent)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (this.addAtBack)\n\t\t\t\t\t\t\tthis._parent.addChildAt(p, 0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tthis._parent.addChild(p);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//kind of hacky, but performance friendly\n\t\t\t\t\t\t//shuffle children to correct place\n\t\t\t\t\t\tvar children = this._parent.children;\n\t\t\t\t\t\t//avoid using splice if possible\n\t\t\t\t\t\tif(children[0] == p)\n\t\t\t\t\t\t\tchildren.shift();\n\t\t\t\t\t\telse if(children[children.length-1] == p)\n\t\t\t\t\t\t\tchildren.pop();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar index = children.indexOf(p);\n\t\t\t\t\t\t\tchildren.splice(index, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(this.addAtBack)\n\t\t\t\t\t\t\tchildren.unshift(p);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tchildren.push(p);\n\t\t\t\t\t}\n\t\t\t\t\t//add particle to list of active particles\n\t\t\t\t\tif(this._activeParticlesLast)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis._activeParticlesLast.next = p;\n\t\t\t\t\t\tp.prev = this._activeParticlesLast;\n\t\t\t\t\t\tthis._activeParticlesLast = p;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthis._activeParticlesLast = this._activeParticlesFirst = p;\n\t\t\t\t\t}\n\t\t\t\t\t++this.particleCount;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//increase timer and continue on to any other particles that need to be created\n\t\t\tthis._spawnTimer += this._frequency;\n\t\t}\n\t}\n\t//if the position changed before this update, then keep track of that\n\tif(this._posChanged)\n\t{\n\t\tthis._prevEmitterPos.x = curX;\n\t\tthis._prevEmitterPos.y = curY;\n\t\tthis._prevPosIsValid = true;\n\t\tthis._posChanged = false;\n\t}\n\n\t//if we are all done and should destroy ourselves, take care of that\n\tif (!this._emit && !this._activeParticlesFirst)\n\t{\n\t\tif (this._completeCallback)\n\t\t{\n\t\t\tthis._completeCallback();\n\t\t}\n\t\tif (this._destroyWhenComplete)\n\t\t{\n\t\t\tthis.destroy();\n\t\t}\n\t}\n};\n\n/**\n * Positions a particle for a point type emitter.\n * @method PIXI.particles.Emitter#_spawnPoint\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnPoint = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on\n\t//starting particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\n\t//drop the particle at the emitter's position\n\tp.position.x = emitPosX;\n\tp.position.y = emitPosY;\n};\n\n/**\n * Positions a particle for a rectangle type emitter.\n * @method PIXI.particles.Emitter#_spawnRect\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnRect = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\n\t//place the particle at a random point in the rectangle\n\thelperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x;\n\thelperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y;\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a circle type emitter.\n * @method PIXI.particles.Emitter#_spawnCircle\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnCircle = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\n\t\t\t\t\tthis.minStartRotation + this.rotation;\n\t//place the particle at a random radius in the circle\n\thelperPoint.x = Math.random() * this.spawnCircle.radius;\n\thelperPoint.y = 0;\n\t//rotate the point to a random angle in the circle\n\tParticleUtils.rotatePoint(Math.random() * 360, helperPoint);\n\t//offset by the circle's center\n\thelperPoint.x += this.spawnCircle.x;\n\thelperPoint.y += this.spawnCircle.y;\n\t//rotate the point by the emitter's rotation\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\t//set the position, offset by the emitter's position\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a ring type emitter.\n * @method PIXI.particles.Emitter#_spawnRing\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnRing = function(p, emitPosX, emitPosY)\n{\n\tvar spawnCircle = this.spawnCircle;\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\n\t\t\t\t\tthis.minStartRotation + this.rotation;\n\t//place the particle at a random radius in the ring\n\tif(spawnCircle.minRadius == spawnCircle.radius)\n\t{\n\t\thelperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) +\n\t\t\t\t\t\tspawnCircle.minRadius;\n\t}\n\telse\n\t\thelperPoint.x = spawnCircle.radius;\n\thelperPoint.y = 0;\n\t//rotate the point to a random angle in the circle\n\tvar angle = Math.random() * 360;\n\tp.rotation += angle;\n\tParticleUtils.rotatePoint(angle, helperPoint);\n\t//offset by the circle's center\n\thelperPoint.x += this.spawnCircle.x;\n\thelperPoint.y += this.spawnCircle.y;\n\t//rotate the point by the emitter's rotation\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\t//set the position, offset by the emitter's position\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a burst type emitter.\n * @method PIXI.particles.Emitter#_spawnBurst\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave.\n */\np._spawnBurst = function(p, emitPosX, emitPosY, i)\n{\n\t//set the initial rotation/direction of the particle based on spawn\n\t//angle and rotation of emitter\n\tif(this.particleSpacing === 0)\n\t\tp.rotation = Math.random() * 360;\n\telse\n\t\tp.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation;\n\t//drop the particle at the emitter's position\n\tp.position.x = emitPosX;\n\tp.position.y = emitPosY;\n};\n\n/**\n * Kills all active particles immediately.\n * @method PIXI.particles.Emitter#cleanup\n */\np.cleanup = function()\n{\n\tvar particle, next;\n\tfor (particle = this._activeParticlesFirst; particle; particle = next)\n\t{\n\t\tnext = particle.next;\n\t\tthis.recycle(particle);\n\t\tif(particle.parent)\n\t\t\tparticle.parent.removeChild(particle);\n\t}\n\tthis._activeParticlesFirst = this._activeParticlesLast = null;\n\tthis.particleCount = 0;\n};\n\n/**\n * Destroys the emitter and all of its particles.\n * @method PIXI.particles.Emitter#destroy\n */\np.destroy = function()\n{\n\t//make sure we aren't still listening to any tickers\n\tthis.autoUpdate = false;\n\t//puts all active particles in the pool, and removes them from the particle parent\n\tthis.cleanup();\n\t//wipe the pool clean\n\tvar next;\n\tfor (var particle = this._poolFirst; particle; particle = next)\n\t{\n\t\t//store next value so we don't lose it in our destroy call\n\t\tnext = particle.next;\n\t\tparticle.destroy();\n\t}\n\tthis._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos =\n\t\tthis.startColor = this.endColor = this.customEase = this._completeCallback = null;\n};\n\nmodule.exports = Emitter;","var ParticleUtils = require(\"./ParticleUtils\");\nvar Sprite = PIXI.Sprite;\n\n/**\n * An individual particle image. You shouldn't have to deal with these.\n * @memberof PIXI.particles\n * @class Particle\n * @extends PIXI.Sprite\n * @constructor\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle.\n */\nvar Particle = function(emitter)\n{\n\t//start off the sprite with a blank texture, since we are going to replace it\n\t//later when the particle is initialized.\n\tSprite.call(this);\n\n\t/**\n\t * The emitter that controls this particle.\n\t * @property {Emitter} emitter\n\t */\n\tthis.emitter = emitter;\n\t//particles should be centered\n\tthis.anchor.x = this.anchor.y = 0.5;\n\t/**\n\t * The velocity of the particle. Speed may change, but the angle also\n\t * contained in velocity is constant.\n\t * @property {PIXI.Point} velocity\n\t */\n\tthis.velocity = new PIXI.Point();\n\t/**\n\t * The maximum lifetime of this particle, in seconds.\n\t * @property {Number} maxLife\n\t */\n\tthis.maxLife = 0;\n\t/**\n\t * The current age of the particle, in seconds.\n\t * @property {Number} age\n\t */\n\tthis.age = 0;\n\t/**\n\t * A simple easing function to be applied to all properties that\n\t * are being interpolated.\n\t * @property {Function} ease\n\t */\n\tthis.ease = null;\n\t/**\n\t * Extra data that the emitter passes along for custom particles.\n\t * @property {Object} extraData\n\t */\n\tthis.extraData = null;\n\t/**\n\t * The alpha of the particle at the start of its life.\n\t * @property {Number} startAlpha\n\t */\n\tthis.startAlpha = 0;\n\t/**\n\t * The alpha of the particle at the end of its life.\n\t * @property {Number} endAlpha\n\t */\n\tthis.endAlpha = 0;\n\t/**\n\t * The speed of the particle at the start of its life.\n\t * @property {Number} startSpeed\n\t */\n\tthis.startSpeed = 0;\n\t/**\n\t * The speed of the particle at the end of its life.\n\t * @property {Number} endSpeed\n\t */\n\tthis.endSpeed = 0;\n\t/**\n\t * Acceleration to apply to the particle.\n\t * @property {PIXI.Point} accleration\n\t */\n\tthis.acceleration = new PIXI.Point();\n\t/**\n\t * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n\t * will disable the maximum speed.\n\t * @property {Number} maxSpeed\n\t * @default NaN\n\t */\n\tthis.maxSpeed = NaN;\n\t/**\n\t * The scale of the particle at the start of its life.\n\t * @property {Number} startScale\n\t */\n\tthis.startScale = 0;\n\t/**\n\t * The scale of the particle at the start of its life.\n\t * @property {Number} endScale\n\t */\n\tthis.endScale = 0;\n\t/**\n\t * The tint of the particle at the start of its life.\n\t * @property {Array} startColor\n\t */\n\tthis.startColor = null;\n\t/**\n\t * The red tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sR\n\t * @private\n\t */\n\tthis._sR = 0;\n\t/**\n\t * The green tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sG\n\t * @private\n\t */\n\tthis._sG = 0;\n\t/**\n\t * The blue tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sB\n\t * @private\n\t */\n\tthis._sB = 0;\n\t/**\n\t * The tint of the particle at the start of its life.\n\t * @property {Array} endColor\n\t */\n\tthis.endColor = null;\n\t/**\n\t * The red tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _eR\n\t * @private\n\t */\n\tthis._eR = 0;\n\t/**\n\t * The green tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _sG\n\t * @private\n\t */\n\tthis._eG = 0;\n\t/**\n\t * The blue tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _sB\n\t * @private\n\t */\n\tthis._eB = 0;\n\t/**\n\t * If alpha should be interpolated at all.\n\t * @property {Boolean} _doAlpha\n\t * @private\n\t */\n\tthis._doAlpha = false;\n\t/**\n\t * If scale should be interpolated at all.\n\t * @property {Boolean} _doScale\n\t * @private\n\t */\n\tthis._doScale = false;\n\t/**\n\t * If speed should be interpolated at all.\n\t * @property {Boolean} _doSpeed\n\t * @private\n\t */\n\tthis._doSpeed = false;\n\t/**\n\t * If acceleration should be handled at all. _doSpeed is mutually exclusive with this,\n\t * and _doSpeed gets priority.\n\t * @property {Boolean} _doAcceleration\n\t * @private\n\t */\n\tthis._doAcceleration = false;\n\t/**\n\t * If color should be interpolated at all.\n\t * @property {Boolean} _doColor\n\t * @private\n\t */\n\tthis._doColor = false;\n\t/**\n\t * If normal movement should be handled. Subclasses wishing to override movement\n\t * can set this to false in init().\n\t * @property {Boolean} _doNormalMovement\n\t * @private\n\t */\n\tthis._doNormalMovement = false;\n\t/**\n\t * One divided by the max life of the particle, saved for slightly faster math.\n\t * @property {Number} _oneOverLife\n\t * @private\n\t */\n\tthis._oneOverLife = 0;\n\n\t/**\n\t * Reference to the next particle in the list.\n\t * @property {Particle} next\n\t * @private\n\t */\n\tthis.next = null;\n\n\t/**\n\t * Reference to the previous particle in the list.\n\t * @property {Particle} prev\n\t * @private\n\t */\n\tthis.prev = null;\n\n\t//save often used functions on the instance instead of the prototype for better speed\n\tthis.init = this.init;\n\tthis.Particle_init = this.Particle_init;\n\tthis.update = this.update;\n\tthis.Particle_update = this.Particle_update;\n\tthis.applyArt = this.applyArt;\n\tthis.kill = this.kill;\n};\n\n// Reference to the prototype\nvar p = Particle.prototype = Object.create(Sprite.prototype);\n\n/**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n * @method PIXI.particles.Particle#init\n */\n/**\n * A reference to init, so that subclasses can access it without the penalty of Function.call()\n * @method PIXI.particles.Particle#Particle_init\n * @protected\n */\np.init = p.Particle_init = function()\n{\n\t//reset the age\n\tthis.age = 0;\n\t//set up the velocity based on the start speed and rotation\n\tthis.velocity.x = this.startSpeed;\n\tthis.velocity.y = 0;\n\tParticleUtils.rotatePoint(this.rotation, this.velocity);\n\tif (this.noRotation)\n\t{\n\t\tthis.rotation = 0;\n\t}\n\telse\n\t{\n\t\t//convert rotation to Radians from Degrees\n\t\tthis.rotation *= ParticleUtils.DEG_TO_RADS;\n\t}\n\t//convert rotation speed to Radians from Degrees\n\tthis.rotationSpeed *= ParticleUtils.DEG_TO_RADS;\n\t//set alpha to inital alpha\n\tthis.alpha = this.startAlpha;\n\t//set scale to initial scale\n\tthis.scale.x = this.scale.y = this.startScale;\n\t//determine start and end color values\n\tif (this.startColor)\n\t{\n\t\tthis._sR = this.startColor[0];\n\t\tthis._sG = this.startColor[1];\n\t\tthis._sB = this.startColor[2];\n\t\tif(this.endColor)\n\t\t{\n\t\t\tthis._eR = this.endColor[0];\n\t\t\tthis._eG = this.endColor[1];\n\t\t\tthis._eB = this.endColor[2];\n\t\t}\n\t}\n\t//figure out what we need to interpolate\n\tthis._doAlpha = this.startAlpha != this.endAlpha;\n\tthis._doSpeed = this.startSpeed != this.endSpeed;\n\tthis._doScale = this.startScale != this.endScale;\n\tthis._doColor = !!this.endColor;\n\tthis._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0;\n\t//_doNormalMovement can be cancelled by subclasses\n\tthis._doNormalMovement = this._doSpeed || this.startSpeed !== 0 || this._doAcceleration;\n\t//save our lerp helper\n\tthis._oneOverLife = 1 / this.maxLife;\n\t//set the inital color\n\tthis.tint = ParticleUtils.combineRGBComponents(this._sR, this._sG, this._sB);\n\t//ensure visibility\n\tthis.visible = true;\n};\n\n/**\n * Sets the texture for the particle. This can be overridden to allow\n * for an animated particle.\n * @method PIXI.particles.Particle#applyArt\n * @param {PIXI.Texture} art The texture to set.\n */\np.applyArt = function(art)\n{\n\tthis.texture = art || ParticleUtils.EMPTY_TEXTURE;\n};\n\n/**\n * Updates the particle.\n * @method PIXI.particles.Particle#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\n * properties. A value of -1 means the particle died of old age instead.\n */\n/**\n * A reference to update so that subclasses can access the original without the overhead\n * of Function.call().\n * @method PIXI.particles.Particle#Particle_update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\n * properties. A value of -1 means the particle died of old age instead.\n * @protected\n */\np.update = p.Particle_update = function(delta)\n{\n\t//increase age\n\tthis.age += delta;\n\t//recycle particle if it is too old\n\tif(this.age >= this.maxLife)\n\t{\n\t\tthis.kill();\n\t\treturn -1;\n\t}\n\n\t//determine our interpolation value\n\tvar lerp = this.age * this._oneOverLife;//lifetime / maxLife;\n\tif (this.ease)\n\t{\n\t\tif(this.ease.length == 4)\n\t\t{\n\t\t\t//the t, b, c, d parameters that some tween libraries use\n\t\t\t//(time, initial value, end value, duration)\n\t\t\tlerp = this.ease(lerp, 0, 1, 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//the simplified version that we like that takes\n\t\t\t//one parameter, time from 0-1. TweenJS eases provide this usage.\n\t\t\tlerp = this.ease(lerp);\n\t\t}\n\t}\n\n\t//interpolate alpha\n\tif (this._doAlpha)\n\t\tthis.alpha = (this.endAlpha - this.startAlpha) * lerp + this.startAlpha;\n\t//interpolate scale\n\tif (this._doScale)\n\t{\n\t\tvar scale = (this.endScale - this.startScale) * lerp + this.startScale;\n\t\tthis.scale.x = this.scale.y = scale;\n\t}\n\t//handle movement\n\tif(this._doNormalMovement)\n\t{\n\t\t//interpolate speed\n\t\tif (this._doSpeed)\n\t\t{\n\t\t\tvar speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed;\n\t\t\tParticleUtils.normalize(this.velocity);\n\t\t\tParticleUtils.scaleBy(this.velocity, speed);\n\t\t}\n\t\telse if(this._doAcceleration)\n\t\t{\n\t\t\tthis.velocity.x += this.acceleration.x * delta;\n\t\t\tthis.velocity.y += this.acceleration.y * delta;\n\t\t\tif (this.maxSpeed)\n\t\t\t{\n\t\t\t\tvar currentSpeed = ParticleUtils.length(this.velocity);\n\t\t\t\t//if we are going faster than we should, clamp at the max speed\n\t\t\t\t//DO NOT recalculate vector length\n\t\t\t\tif (currentSpeed > this.maxSpeed)\n\t\t\t\t{\n\t\t\t\t\tParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//adjust position based on velocity\n\t\tthis.position.x += this.velocity.x * delta;\n\t\tthis.position.y += this.velocity.y * delta;\n\t}\n\t//interpolate color\n\tif (this._doColor)\n\t{\n\t\tvar r = (this._eR - this._sR) * lerp + this._sR;\n\t\tvar g = (this._eG - this._sG) * lerp + this._sG;\n\t\tvar b = (this._eB - this._sB) * lerp + this._sB;\n\t\tthis.tint = ParticleUtils.combineRGBComponents(r, g, b);\n\t}\n\t//update rotation\n\tif(this.rotationSpeed !== 0)\n\t{\n\t\tthis.rotation += this.rotationSpeed * delta;\n\t}\n\telse if(this.acceleration && !this.noRotation)\n\t{\n\t\tthis.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2;\n\t}\n\treturn lerp;\n};\n\n/**\n * Kills the particle, removing it from the display list\n * and telling the emitter to recycle it.\n * @method PIXI.particles.Particle#kill\n */\np.kill = function()\n{\n\tthis.emitter.recycle(this);\n};\n\np.Sprite_Destroy = Sprite.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.Particle#destroy\n */\np.destroy = function()\n{\n\tif (this.parent)\n\t\tthis.parent.removeChild(this);\n\tif (this.Sprite_Destroy)\n\t\tthis.Sprite_Destroy();\n\tthis.emitter = this.velocity = this.startColor = this.endColor = this.ease =\n\t\tthis.next = this.prev = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @method PIXI.particles.Particle.parseArt\n * @static\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\n * Any strings in the array will be converted to Textures via\n * Texture.fromImage().\n * @return {Array} The art, after any needed modifications.\n */\nParticle.parseArt = function(art)\n{\n\t//convert any strings to Textures.\n\tvar i;\n\tfor(i = art.length; i >= 0; --i)\n\t{\n\t\tif(typeof art[i] == \"string\")\n\t\t\tart[i] = PIXI.Texture.fromImage(art[i]);\n\t}\n\t//particles from different base textures will be slower in WebGL than if they\n\t//were from one spritesheet\n\tif(ParticleUtils.verbose)\n\t{\n\t\tfor(i = art.length - 1; i > 0; --i)\n\t\t{\n\t\t\tif(art[i].baseTexture != art[i - 1].baseTexture)\n\t\t\t{\n\t\t\t\tif (window.console)\n\t\t\t\t\tconsole.warn(\"PixiParticles: using particle textures from different images may hinder performance in WebGL\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn art;\n};\n\n/**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * Particle does nothing to the extra data.\n * @method PIXI.particles.Particle.parseData\n * @static\n * @param {Object} extraData The extra data from the particle config.\n * @return {Object} The parsed extra data.\n */\nParticle.parseData = function(extraData)\n{\n\treturn extraData;\n};\n\nmodule.exports = Particle;","\"use strict\";\n\nvar BLEND_MODES = PIXI.BLEND_MODES || PIXI.blendModes;\nvar Texture = PIXI.Texture;\n\n/**\n * Contains helper functions for particles and emitters to use.\n * @memberof PIXI.particles\n * @class ParticleUtils\n * @static\n */\nvar ParticleUtils = {};\n\n/**\n * If errors and warnings should be logged within the library.\n * @name PIXI.particles.ParticleUtils.verbose\n * @default false\n * @static\n */\nParticleUtils.verbose = false;\n\nvar DEG_TO_RADS = ParticleUtils.DEG_TO_RADS = Math.PI / 180;\n\nvar empty = ParticleUtils.EMPTY_TEXTURE = Texture.EMPTY;\n//prevent any events from being used on the empty texture, as well as destruction of it\n//v4 of Pixi does this, but doing it again won't hurt\nempty.on = empty.destroy = empty.once = empty.emit = function() {};\n\n/**\n * Rotates a point by a given angle.\n * @method PIXI.particles.ParticleUtils.rotatePoint\n * @param {Number} angle The angle to rotate by in degrees\n * @param {PIXI.Point} p The point to rotate around 0,0.\n * @static\n */\nParticleUtils.rotatePoint = function(angle, p)\n{\n\tif(!angle) return;\n\tangle *= DEG_TO_RADS;\n\tvar s = Math.sin(angle);\n\tvar c = Math.cos(angle);\n\tvar xnew = p.x * c - p.y * s;\n\tvar ynew = p.x * s + p.y * c;\n\tp.x = xnew;\n\tp.y = ynew;\n};\n\n/**\n * Combines separate color components (0-255) into a single uint color.\n * @method PIXI.particles.ParticleUtils.combineRGBComponents\n * @param {uint} r The red value of the color\n * @param {uint} g The green value of the color\n * @param {uint} b The blue value of the color\n * @return {uint} The color in the form of 0xRRGGBB\n * @static\n */\nParticleUtils.combineRGBComponents = function(r, g, b/*, a*/)\n{\n\treturn /*a << 24 |*/ r << 16 | g << 8 | b;\n};\n\n/**\n * Reduces the point to a length of 1.\n * @method PIXI.particles.ParticleUtils.normalize\n * @static\n * @param {PIXI.Point} point The point to normalize\n */\nParticleUtils.normalize = function(point)\n{\n\tvar oneOverLen = 1 / ParticleUtils.length(point);\n\tpoint.x *= oneOverLen;\n\tpoint.y *= oneOverLen;\n};\n\n/**\n * Multiplies the x and y values of this point by a value.\n * @method PIXI.particles.ParticleUtils.scaleBy\n * @static\n * @param {PIXI.Point} point The point to scaleBy\n * @param value {Number} The value to scale by.\n */\nParticleUtils.scaleBy = function(point, value)\n{\n\tpoint.x *= value;\n\tpoint.y *= value;\n};\n\n/**\n * Returns the length (or magnitude) of this point.\n * @method PIXI.particles.ParticleUtils.length\n * @static\n * @param {PIXI.Point} point The point to measure length\n * @return The length of this point.\n */\nParticleUtils.length = function(point)\n{\n\treturn Math.sqrt(point.x * point.x + point.y * point.y);\n};\n\n/**\n * Converts a hex string from \"#AARRGGBB\", \"#RRGGBB\", \"0xAARRGGBB\", \"0xRRGGBB\",\n * \"AARRGGBB\", or \"RRGGBB\" to an array of ints of 0-255 or Numbers from 0-1, as\n * [r, g, b, (a)].\n * @method PIXI.particles.ParticleUtils.hexToRGB\n * @param {String} color The input color string.\n * @param {Array} output An array to put the output in. If omitted, a new array is created.\n * @return The array of numeric color values.\n * @static\n */\nParticleUtils.hexToRGB = function(color, output)\n{\n\tif (output)\n\t\toutput.length = 0;\n\telse\n\t\toutput = [];\n\tif (color.charAt(0) == \"#\")\n\t\tcolor = color.substr(1);\n\telse if (color.indexOf(\"0x\") === 0)\n\t\tcolor = color.substr(2);\n\tvar alpha;\n\tif (color.length == 8)\n\t{\n\t\talpha = color.substr(0, 2);\n\t\tcolor = color.substr(2);\n\t}\n\toutput.push(parseInt(color.substr(0, 2), 16));//Red\n\toutput.push(parseInt(color.substr(2, 2), 16));//Green\n\toutput.push(parseInt(color.substr(4, 2), 16));//Blue\n\tif (alpha)\n\t\toutput.push(parseInt(alpha, 16));\n\treturn output;\n};\n\n/**\n * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated\n * by the related tool at http://www.greensock.com/customease/.\n * @method PIXI.particles.ParticleUtils.generateEase\n * @param {Array} segments An array of segments, as created by\n * http://www.greensock.com/customease/.\n * @return {Function} A function that calculates the percentage of change at\n * a given point in time (0-1 inclusive).\n * @static\n */\nParticleUtils.generateEase = function(segments)\n{\n\tvar qty = segments.length;\n\tvar oneOverQty = 1 / qty;\n\t/*\n\t * Calculates the percentage of change at a given point in time (0-1 inclusive).\n\t * @param {Number} time The time of the ease, 0-1 inclusive.\n\t * @return {Number} The percentage of the change, 0-1 inclusive (unless your\n\t * ease goes outside those bounds).\n\t */\n\tvar simpleEase = function(time)\n\t{\n\t\tvar t, s;\n\t\tvar i = (qty * time) | 0;//do a quick floor operation\n\t\tt = (time - (i * oneOverQty)) * qty;\n\t\ts = segments[i] || segments[qty - 1];\n\t\treturn (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s)));\n\t};\n\treturn simpleEase;\n};\n\n/**\n * Gets a blend mode, ensuring that it is valid.\n * @method PIXI.particles.ParticleUtils.getBlendMode\n * @param {String} name The name of the blend mode to get.\n * @return {int} The blend mode as specified in the PIXI.blendModes enumeration.\n * @static\n */\nParticleUtils.getBlendMode = function(name)\n{\n\tif (!name) return BLEND_MODES.NORMAL;\n\tname = name.toUpperCase();\n\twhile (name.indexOf(\" \") >= 0)\n\t\tname = name.replace(\" \", \"_\");\n\treturn BLEND_MODES[name] || BLEND_MODES.NORMAL;\n};\n\nmodule.exports = ParticleUtils;","\"use strict\";\n\nvar ParticleUtils = require(\"./ParticleUtils\"),\n\tParticle = require(\"./Particle\");\n\n/**\n * An particle that follows a path defined by an algebraic expression, e.g. \"sin(x)\" or\n * \"5x + 3\".\n * To use this class, the particle config must have a \"path\" string in the\n * \"extraData\" parameter. This string should have \"x\" in it to represent movement (from the\n * speed settings of the particle). It may have numbers, parentheses, the four basic\n * operations, and the following Math functions or properties (without the preceding \"Math.\"):\n * \"pow\", \"sqrt\", \"abs\", \"floor\", \"round\", \"ceil\", \"E\", \"PI\", \"sin\", \"cos\", \"tan\", \"asin\",\n * \"acos\", \"atan\", \"atan2\", \"log\".\n * The overall movement of the particle and the expression value become x and y positions for\n * the particle, respectively. The final position is rotated by the spawn rotation/angle of\n * the particle.\n *\n * Some example paths:\n *\n * \t\"sin(x/10) * 20\" // A sine wave path.\n * \t\"cos(x/100) * 30\" // Particles curve counterclockwise (for medium speed/low lifetime particles)\n * \t\"pow(x/10, 2) / 2\" // Particles curve clockwise (remember, +y is down).\n *\n * @memberof PIXI.particles\n * @class PathParticle\n * @extends PIXI.particles.Particle\n * @constructor\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle.\n */\nvar PathParticle = function(emitter)\n{\n\tParticle.call(this, emitter);\n\t/**\n\t * The function representing the path the particle should take.\n\t * @property {Function} path\n\t */\n\tthis.path = null;\n\t/**\n\t * The initial rotation in degrees of the particle, because the direction of the path\n\t * is based on that.\n\t * @property {Number} initialRotation\n\t */\n\tthis.initialRotation = 0;\n\t/**\n\t * The initial position of the particle, as all path movement is added to that.\n\t * @property {PIXI.Point} initialPosition\n\t */\n\tthis.initialPosition = new PIXI.Point();\n\t/**\n\t * Total single directional movement, due to speed.\n\t * @property {Number} movement\n\t */\n\tthis.movement = 0;\n};\n\n// Reference to the super class\nvar s = Particle.prototype;\n// Reference to the prototype\nvar p = PathParticle.prototype = Object.create(s);\n\n/**\n * A helper point for math things.\n * @property {Function} helperPoint\n * @private\n * @static\n */\nvar helperPoint = new PIXI.Point();\n\n/**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n * @method PIXI.particles.PathParticle#init\n */\np.init = function()\n{\n\t//get initial rotation before it is converted to radians\n\tthis.initialRotation = this.rotation;\n\t//standard init\n\tthis.Particle_init();\n\n\t//set the path for the particle\n\tthis.path = this.extraData.path;\n\t//cancel the normal movement behavior\n\tthis._doNormalMovement = !this.path;\n\t//reset movement\n\tthis.movement = 0;\n\t//grab position\n\tthis.initialPosition.x = this.position.x;\n\tthis.initialPosition.y = this.position.y;\n};\n\n//a hand picked list of Math functions (and a couple properties) that are allowable.\n//they should be used without the preceding \"Math.\"\nvar MATH_FUNCS =\n[\n\t\"pow\",\n\t\"sqrt\",\n\t\"abs\",\n\t\"floor\",\n\t\"round\",\n\t\"ceil\",\n\t\"E\",\n\t\"PI\",\n\t\"sin\",\n\t\"cos\",\n\t\"tan\",\n\t\"asin\",\n\t\"acos\",\n\t\"atan\",\n\t\"atan2\",\n\t\"log\"\n];\n//Allow the 4 basic operations, parentheses and all numbers/decimals, as well\n//as 'x', for the variable usage.\nvar WHITELISTER = \"[01234567890\\\\.\\\\*\\\\-\\\\+\\\\/\\\\(\\\\)x ,]\";\n//add the math functions to the regex string.\nfor(var index = MATH_FUNCS.length - 1; index >= 0; --index)\n{\n\tWHITELISTER += \"|\" + MATH_FUNCS[index];\n}\n//create an actual regular expression object from the string\nWHITELISTER = new RegExp(WHITELISTER, \"g\");\n\n/**\n * Parses a string into a function for path following.\n * This involves whitelisting the string for safety, inserting \"Math.\" to math function\n * names, and using `new Function()` to generate a function.\n * @method PIXI.particles.PathParticle~parsePath\n * @private\n * @static\n * @param {String} pathString The string to parse.\n * @return {Function} The path function - takes x, outputs y.\n */\nvar parsePath = function(pathString)\n{\n\tvar matches = pathString.match(WHITELISTER);\n\tfor(var i = matches.length - 1; i >= 0; --i)\n\t{\n\t\tif(MATH_FUNCS.indexOf(matches[i]) >= 0)\n\t\t\tmatches[i] = \"Math.\" + matches[i];\n\t}\n\tpathString = matches.join(\"\");\n\treturn new Function(\"x\", \"return \"+ pathString + \";\");\n};\n\n/**\n * Updates the particle.\n * @method PIXI.particles.PathParticle#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n */\np.update = function(delta)\n{\n\tvar lerp = this.Particle_update(delta);\n\t//if the particle died during the update, then don't bother\n\tif(lerp >= 0 && this.path)\n\t{\n\t\t//increase linear movement based on speed\n\t\tvar speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed;\n\t\tthis.movement += speed * delta;\n\t\t//set up the helper point for rotation\n\t\thelperPoint.x = this.movement;\n\t\thelperPoint.y = this.path(this.movement);\n\t\tParticleUtils.rotatePoint(this.initialRotation, helperPoint);\n\t\tthis.position.x = this.initialPosition.x + helperPoint.x;\n\t\tthis.position.y = this.initialPosition.y + helperPoint.y;\n\t}\n};\n\np.Particle_destroy = Particle.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.PathParticle#destroy\n */\np.destroy = function()\n{\n\tthis.Particle_destroy();\n\tthis.path = this.initialPosition = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time. This just runs Particle.parseArt().\n * @method PIXI.particles.PathParticle.parseArt\n * @static\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\n * Any strings in the array will be converted to Textures via\n * Texture.fromImage().\n * @return {Array} The art, after any needed modifications.\n */\nPathParticle.parseArt = function(art)\n{\n\treturn Particle.parseArt(art);\n};\n\n/**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * PathParticle checks for the existence of path data, and parses the path data for use\n * by particle instances.\n * @method PIXI.particles.PathParticle.parseData\n * @static\n * @param {Object} extraData The extra data from the particle config.\n * @return {Object} The parsed extra data.\n */\nPathParticle.parseData = function(extraData)\n{\n\tvar output = {};\n\tif(extraData && extraData.path)\n\t{\n\t\ttry\n\t\t{\n\t\t\toutput.path = parsePath(extraData.path);\n\t\t}\n\t\tcatch(e)\n\t\t{\n\t\t\tif(ParticleUtils.verbose)\n\t\t\t\tconsole.error(\"PathParticle: error in parsing path expression\");\n\t\t\toutput.path = null;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(ParticleUtils.verbose)\n\t\t\tconsole.error(\"PathParticle requires a path string in extraData!\");\n\t\toutput.path = null;\n\t}\n\treturn output;\n};\n\nmodule.exports = PathParticle;","//Nothing to deprecate right now!","exports.ParticleUtils = require(\"./ParticleUtils.js\");\nexports.Particle = require(\"./Particle.js\");\nexports.Emitter = require(\"./Emitter.js\");\nexports.PathParticle = require(\"./PathParticle.js\");\nexports.AnimatedParticle = require(\"./AnimatedParticle.js\");\nrequire(\"./deprecation.js\");","\"use strict\";\n\n// Check for window, fallback to global\nvar global = typeof window !== 'undefined' ? window : GLOBAL;\n\n//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not\nif (!global.PIXI.particles) {\n\tglobal.PIXI.particles = {};\n}\n\n// Export for Node-compatible environments like Electron\nif (typeof module !== 'undefined' && module.exports)\n{\n\t// Attempt to require the pixi module\n\tif (typeof PIXI === 'undefined')\n\t{\n\t\t// Include the Pixi.js module\n\t\trequire('pixi.js');\n\t}\n\n\t// Export the module\n\tmodule.exports = global.PIXI.particles || particles;\n}\n// If we're in the browser make sure PIXI is available\nelse if (typeof PIXI === 'undefined')\n{\n\tthrow \"pixi-particles requires pixi.js to be loaded first\";\n}\n\n// get the library itself\nvar particles = require('./particles');\n\n// insert the lirbary into the particles namespace on PIXI\nfor (var prop in particles) {\n\tglobal.PIXI.particles[prop] = particles[prop];\n}"],"sourceRoot":"."} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","ts-dist/AnimatedParticle.js","ts-dist/Emitter.js","ts-dist/Particle.js","ts-dist/ParticleUtils.js","ts-dist/PathParticle.js","ts-dist/PropertyList.js","ts-dist/PropertyNode.js","ts-dist/particles.js","ts-dist"],"names":[],"mappings":";;;;;;;AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACryBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"pixi-particles.js","sourcesContent":["(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0) {\r\n this.elapsed += delta;\r\n if (this.elapsed > this.duration) {\r\n //loop elapsed back around\r\n if (this.loop)\r\n this.elapsed = this.elapsed % this.duration;\r\n else\r\n this.elapsed = this.duration - 0.000001;\r\n }\r\n var frame = (this.elapsed * this.framerate + 0.0000001) | 0;\r\n this.texture = this.textures[frame] || PIXI.Texture.EMPTY;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.AnimatedParticle#destroy\r\n */\r\n AnimatedParticle.prototype.destroy = function () {\r\n this.Particle_destroy();\r\n this.textures = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time.\r\n * @method PIXI.particles.AnimatedParticle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data, properly formatted for AnimatedParticle.\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n AnimatedParticle.parseArt = function (art) {\r\n var data, output, textures, tex, outTextures;\r\n var outArr = [];\r\n for (var i = 0; i < art.length; ++i) {\r\n data = art[i];\r\n outArr[i] = output = {};\r\n output.textures = outTextures = [];\r\n textures = data.textures;\r\n for (var j = 0; j < textures.length; ++j) {\r\n tex = textures[j];\r\n if (typeof tex == \"string\")\r\n outTextures.push(Texture.fromImage(tex));\r\n else if (tex instanceof Texture)\r\n outTextures.push(tex);\r\n else {\r\n var dupe = tex.count || 1;\r\n if (typeof tex.texture == \"string\")\r\n tex = Texture.fromImage(tex.texture);\r\n else\r\n tex = tex.texture;\r\n for (; dupe > 0; --dupe) {\r\n outTextures.push(tex);\r\n }\r\n }\r\n }\r\n //use these values to signify that the animation should match the particle life time.\r\n if (data.framerate == \"matchLife\") {\r\n //-1 means that it should be calculated\r\n output.framerate = -1;\r\n output.duration = 0;\r\n output.loop = false;\r\n }\r\n else {\r\n //determine if the animation should loop\r\n output.loop = !!data.loop;\r\n //get the framerate, default to 60\r\n output.framerate = data.framerate > 0 ? data.framerate : 60;\r\n //determine the duration\r\n output.duration = outTextures.length / output.framerate;\r\n }\r\n }\r\n return outArr;\r\n };\r\n return AnimatedParticle;\r\n}(Particle_1.default));\r\nexports.default = AnimatedParticle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar Particle_1 = require(\"./Particle\");\r\nvar PropertyNode_1 = require(\"./PropertyNode\");\r\nvar ticker = PIXI.ticker.shared;\r\nvar helperPoint = new PIXI.Point();\r\n/**\r\n * A particle emitter.\r\n * @memberof PIXI.particles\r\n * @class Emitter\r\n * @constructor\r\n * @param {PIXI.Container} particleParent The container to add the\r\n * particles to.\r\n * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use\r\n * for the particles. Strings will be turned\r\n * into textures via Texture.fromImage().\r\n * @param {Object} [config] A configuration object containing settings for the emitter.\r\n * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter\r\n * will start disabled.\r\n * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter\r\n * will automatically call update via the PIXI shared ticker.\r\n */\r\nvar Emitter = /** @class */ (function () {\r\n function Emitter(particleParent, particleImages, config) {\r\n this._particleConstructor = Particle_1.default;\r\n //properties for individual particles\r\n this.particleImages = null;\r\n this.startAlpha = null;\r\n this.startSpeed = null;\r\n this.minimumSpeedMultiplier = 1;\r\n this.acceleration = null;\r\n this.maxSpeed = NaN;\r\n this.startScale = null;\r\n this.minimumScaleMultiplier = 1;\r\n this.startColor = null;\r\n this.minLifetime = 0;\r\n this.maxLifetime = 0;\r\n this.minStartRotation = 0;\r\n this.maxStartRotation = 0;\r\n this.noRotation = false;\r\n this.minRotationSpeed = 0;\r\n this.maxRotationSpeed = 0;\r\n this.particleBlendMode = 0;\r\n this.customEase = null;\r\n this.extraData = null;\r\n //properties for spawning particles\r\n this._frequency = 1;\r\n this.spawnChance = 1;\r\n this.maxParticles = 1000;\r\n this.emitterLifetime = -1;\r\n this.spawnPos = null;\r\n this.spawnType = null;\r\n this._spawnFunc = null;\r\n this.spawnRect = null;\r\n this.spawnCircle = null;\r\n this.particlesPerWave = 1;\r\n this.particleSpacing = 0;\r\n this.angleStart = 0;\r\n //emitter properties\r\n this.rotation = 0;\r\n this.ownerPos = null;\r\n this._prevEmitterPos = null;\r\n this._prevPosIsValid = false;\r\n this._posChanged = false;\r\n this._parent = null;\r\n this.addAtBack = false;\r\n this.particleCount = 0;\r\n this._emit = false;\r\n this._spawnTimer = 0;\r\n this._emitterLife = -1;\r\n this._activeParticlesFirst = null;\r\n this._activeParticlesLast = null;\r\n this._poolFirst = null;\r\n this._origConfig = null;\r\n this._origArt = null;\r\n this._autoUpdate = false;\r\n this._destroyWhenComplete = false;\r\n this._completeCallback = null;\r\n //set the initial parent\r\n this.parent = particleParent;\r\n if (particleImages && config)\r\n this.init(particleImages, config);\r\n //save often used functions on the instance instead of the prototype for better speed\r\n this.recycle = this.recycle;\r\n this.update = this.update;\r\n this.rotate = this.rotate;\r\n this.updateSpawnPos = this.updateSpawnPos;\r\n this.updateOwnerPos = this.updateOwnerPos;\r\n }\r\n Object.defineProperty(Emitter.prototype, \"frequency\", {\r\n /**\r\n * Time between particle spawns in seconds. If this value is not a number greater than 0,\r\n * it will be set to 1 (particle per second) to prevent infinite loops.\r\n * @member {Number} PIXI.particles.Emitter#frequency\r\n */\r\n get: function () { return this._frequency; },\r\n set: function (value) {\r\n //do some error checking to prevent infinite loops\r\n if (typeof value == \"number\" && value > 0)\r\n this._frequency = value;\r\n else\r\n this._frequency = 1;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n Object.defineProperty(Emitter.prototype, \"particleConstructor\", {\r\n /**\r\n * The constructor used to create new particles. The default is\r\n * the built in Particle class. Setting this will dump any active or\r\n * pooled particles, if the emitter has already been used.\r\n * @member {Function} PIXI.particles.Emitter#particleConstructor\r\n */\r\n get: function () { return this._particleConstructor; },\r\n set: function (value) {\r\n if (value != this._particleConstructor) {\r\n this._particleConstructor = value;\r\n //clean up existing particles\r\n this.cleanup();\r\n //scrap all the particles\r\n for (var particle = this._poolFirst; particle; particle = particle.next) {\r\n particle.destroy();\r\n }\r\n this._poolFirst = null;\r\n //re-initialize the emitter so that the new constructor can do anything it needs to\r\n if (this._origConfig && this._origArt)\r\n this.init(this._origArt, this._origConfig);\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n Object.defineProperty(Emitter.prototype, \"parent\", {\r\n /**\r\n * The container to add particles to. Settings this will dump any active particles.\r\n * @member {PIXI.Container} PIXI.particles.Emitter#parent\r\n */\r\n get: function () { return this._parent; },\r\n set: function (value) {\r\n this.cleanup();\r\n this._parent = value;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * Sets up the emitter based on the config settings.\r\n * @method PIXI.particles.Emitter#init\r\n * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles.\r\n * @param {Object} config A configuration object containing settings for the emitter.\r\n */\r\n Emitter.prototype.init = function (art, config) {\r\n if (!art || !config)\r\n return;\r\n //clean up any existing particles\r\n this.cleanup();\r\n //store the original config and particle images, in case we need to re-initialize\r\n //when the particle constructor is changed\r\n this._origConfig = config;\r\n this._origArt = art;\r\n //set up the array of data, also ensuring that it is an array\r\n art = Array.isArray(art) ? art.slice() : [art];\r\n //run the art through the particle class's parsing function\r\n var partClass = this._particleConstructor;\r\n this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art;\r\n ///////////////////////////\r\n // Particle Properties //\r\n ///////////////////////////\r\n //set up the alpha\r\n if (config.alpha) {\r\n this.startAlpha = PropertyNode_1.default.createList(config.alpha);\r\n }\r\n else\r\n this.startAlpha = new PropertyNode_1.default(1, 0);\r\n //set up the speed\r\n if (config.speed) {\r\n this.startSpeed = PropertyNode_1.default.createList(config.speed);\r\n this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1;\r\n }\r\n else {\r\n this.minimumSpeedMultiplier = 1;\r\n this.startSpeed = new PropertyNode_1.default(0, 0);\r\n }\r\n //set up acceleration\r\n var acceleration = config.acceleration;\r\n if (acceleration && (acceleration.x || acceleration.y)) {\r\n //make sure we disable speed interpolation\r\n this.startSpeed.next = null;\r\n this.acceleration = new PIXI.Point(acceleration.x, acceleration.y);\r\n this.maxSpeed = config.maxSpeed || NaN;\r\n }\r\n else\r\n this.acceleration = new PIXI.Point();\r\n //set up the scale\r\n if (config.scale) {\r\n this.startScale = PropertyNode_1.default.createList(config.scale);\r\n this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1;\r\n }\r\n else {\r\n this.startScale = new PropertyNode_1.default(1, 0);\r\n this.minimumScaleMultiplier = 1;\r\n }\r\n //set up the color\r\n if (config.color) {\r\n this.startColor = PropertyNode_1.default.createList(config.color);\r\n }\r\n else {\r\n this.startColor = new PropertyNode_1.default({ r: 0xFF, g: 0xFF, b: 0xFF }, 0);\r\n }\r\n //set up the start rotation\r\n if (config.startRotation) {\r\n this.minStartRotation = config.startRotation.min;\r\n this.maxStartRotation = config.startRotation.max;\r\n }\r\n else\r\n this.minStartRotation = this.maxStartRotation = 0;\r\n if (config.noRotation &&\r\n (this.minStartRotation || this.maxStartRotation)) {\r\n this.noRotation = !!config.noRotation;\r\n }\r\n else\r\n this.noRotation = false;\r\n //set up the rotation speed\r\n if (config.rotationSpeed) {\r\n this.minRotationSpeed = config.rotationSpeed.min;\r\n this.maxRotationSpeed = config.rotationSpeed.max;\r\n }\r\n else\r\n this.minRotationSpeed = this.maxRotationSpeed = 0;\r\n //set up the lifetime\r\n this.minLifetime = config.lifetime.min;\r\n this.maxLifetime = config.lifetime.max;\r\n //get the blend mode\r\n this.particleBlendMode = ParticleUtils_1.default.getBlendMode(config.blendMode);\r\n //use the custom ease if provided\r\n if (config.ease) {\r\n this.customEase = typeof config.ease == \"function\" ?\r\n config.ease :\r\n ParticleUtils_1.default.generateEase(config.ease);\r\n }\r\n else\r\n this.customEase = null;\r\n //set up the extra data, running it through the particle class's parseData function.\r\n if (partClass.parseData)\r\n this.extraData = partClass.parseData(config.extraData);\r\n else\r\n this.extraData = config.extraData || null;\r\n //////////////////////////\r\n // Emitter Properties //\r\n //////////////////////////\r\n //reset spawn type specific settings\r\n this.spawnRect = this.spawnCircle = null;\r\n this.particlesPerWave = 1;\r\n if (config.particlesPerWave && config.particlesPerWave > 1)\r\n this.particlesPerWave = config.particlesPerWave;\r\n this.particleSpacing = 0;\r\n this.angleStart = 0;\r\n var spawnCircle;\r\n //determine the spawn function to use\r\n switch (config.spawnType) {\r\n case \"rect\":\r\n this.spawnType = \"rect\";\r\n this._spawnFunc = this._spawnRect;\r\n var spawnRect = config.spawnRect;\r\n this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);\r\n break;\r\n case \"circle\":\r\n this.spawnType = \"circle\";\r\n this._spawnFunc = this._spawnCircle;\r\n spawnCircle = config.spawnCircle;\r\n this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\r\n break;\r\n case \"ring\":\r\n this.spawnType = \"ring\";\r\n this._spawnFunc = this._spawnRing;\r\n spawnCircle = config.spawnCircle;\r\n this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\r\n this.spawnCircle.minRadius = spawnCircle.minR;\r\n break;\r\n case \"burst\":\r\n this.spawnType = \"burst\";\r\n this._spawnFunc = this._spawnBurst;\r\n this.particleSpacing = config.particleSpacing;\r\n this.angleStart = config.angleStart ? config.angleStart : 0;\r\n break;\r\n case \"point\":\r\n this.spawnType = \"point\";\r\n this._spawnFunc = this._spawnPoint;\r\n break;\r\n default:\r\n this.spawnType = \"point\";\r\n this._spawnFunc = this._spawnPoint;\r\n break;\r\n }\r\n //set the spawning frequency\r\n this.frequency = config.frequency;\r\n this.spawnChance = (typeof config.spawnChance === 'number' && config.spawnChance > 0) ? config.spawnChance : 1;\r\n //set the emitter lifetime\r\n this.emitterLifetime = config.emitterLifetime || -1;\r\n //set the max particles\r\n this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000;\r\n //determine if we should add the particle at the back of the list or not\r\n this.addAtBack = !!config.addAtBack;\r\n //reset the emitter position and rotation variables\r\n this.rotation = 0;\r\n this.ownerPos = new PIXI.Point();\r\n this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y);\r\n this._prevEmitterPos = this.spawnPos.clone();\r\n //previous emitter position is invalid and should not be used for interpolation\r\n this._prevPosIsValid = false;\r\n //start emitting\r\n this._spawnTimer = 0;\r\n this.emit = config.emit === undefined ? true : !!config.emit;\r\n this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate;\r\n };\r\n /**\r\n * Recycles an individual particle.\r\n * @method PIXI.particles.Emitter#recycle\r\n * @param {Particle} particle The particle to recycle.\r\n * @private\r\n */\r\n Emitter.prototype.recycle = function (particle) {\r\n if (particle.next)\r\n particle.next.prev = particle.prev;\r\n if (particle.prev)\r\n particle.prev.next = particle.next;\r\n if (particle == this._activeParticlesLast)\r\n this._activeParticlesLast = particle.prev;\r\n if (particle == this._activeParticlesFirst)\r\n this._activeParticlesFirst = particle.next;\r\n //add to pool\r\n particle.prev = null;\r\n particle.next = this._poolFirst;\r\n this._poolFirst = particle;\r\n //remove child from display, or make it invisible if it is in a ParticleContainer\r\n if (particle.parent)\r\n particle.parent.removeChild(particle);\r\n //decrease count\r\n --this.particleCount;\r\n };\r\n /**\r\n * Sets the rotation of the emitter to a new value.\r\n * @method PIXI.particles.Emitter#rotate\r\n * @param {Number} newRot The new rotation, in degrees.\r\n */\r\n Emitter.prototype.rotate = function (newRot) {\r\n if (this.rotation == newRot)\r\n return;\r\n //caclulate the difference in rotation for rotating spawnPos\r\n var diff = newRot - this.rotation;\r\n this.rotation = newRot;\r\n //rotate spawnPos\r\n ParticleUtils_1.default.rotatePoint(diff, this.spawnPos);\r\n //mark the position as having changed\r\n this._posChanged = true;\r\n };\r\n /**\r\n * Changes the spawn position of the emitter.\r\n * @method PIXI.particles.Emitter#updateSpawnPos\r\n * @param {Number} x The new x value of the spawn position for the emitter.\r\n * @param {Number} y The new y value of the spawn position for the emitter.\r\n */\r\n Emitter.prototype.updateSpawnPos = function (x, y) {\r\n this._posChanged = true;\r\n this.spawnPos.x = x;\r\n this.spawnPos.y = y;\r\n };\r\n /**\r\n * Changes the position of the emitter's owner. You should call this if you are adding\r\n * particles to the world container that your emitter's owner is moving around in.\r\n * @method PIXI.particles.Emitter#updateOwnerPos\r\n * @param {Number} x The new x value of the emitter's owner.\r\n * @param {Number} y The new y value of the emitter's owner.\r\n */\r\n Emitter.prototype.updateOwnerPos = function (x, y) {\r\n this._posChanged = true;\r\n this.ownerPos.x = x;\r\n this.ownerPos.y = y;\r\n };\r\n /**\r\n * Prevents emitter position interpolation in the next update.\r\n * This should be used if you made a major position change of your emitter's owner\r\n * that was not normal movement.\r\n * @method PIXI.particles.Emitter#resetPositionTracking\r\n */\r\n Emitter.prototype.resetPositionTracking = function () {\r\n this._prevPosIsValid = false;\r\n };\r\n Object.defineProperty(Emitter.prototype, \"emit\", {\r\n /**\r\n * If particles should be emitted during update() calls. Setting this to false\r\n * stops new particles from being created, but allows existing ones to die out.\r\n * @member {Boolean} PIXI.particles.Emitter#emit\r\n */\r\n get: function () { return this._emit; },\r\n set: function (value) {\r\n this._emit = !!value;\r\n this._emitterLife = this.emitterLifetime;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n ;\r\n Object.defineProperty(Emitter.prototype, \"autoUpdate\", {\r\n /**\r\n * If the update function is called automatically from the shared ticker.\r\n * Setting this to false requires calling the update function manually.\r\n * @member {Boolean} PIXI.particles.Emitter#autoUpdate\r\n */\r\n get: function () { return this._autoUpdate; },\r\n set: function (value) {\r\n if (this._autoUpdate && !value) {\r\n ticker.remove(this.update, this);\r\n }\r\n else if (!this._autoUpdate && value) {\r\n ticker.add(this.update, this);\r\n }\r\n this._autoUpdate = !!value;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself\r\n * when particle emission is complete.\r\n * @method PIXI.particles.Emitter#playOnceAndDestroy\r\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\r\n */\r\n Emitter.prototype.playOnceAndDestroy = function (callback) {\r\n this.autoUpdate = true;\r\n this.emit = true;\r\n this._destroyWhenComplete = true;\r\n this._completeCallback = callback;\r\n };\r\n /**\r\n * Starts emitting particles and optionally calls a callback when particle emission is complete.\r\n * @method PIXI.particles.Emitter#playOnce\r\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\r\n */\r\n Emitter.prototype.playOnce = function (callback) {\r\n this.emit = true;\r\n this._completeCallback = callback;\r\n };\r\n /**\r\n * Updates all particles spawned by this emitter and emits new ones.\r\n * @method PIXI.particles.Emitter#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n */\r\n Emitter.prototype.update = function (delta) {\r\n if (this._autoUpdate) {\r\n delta = delta / PIXI.settings.TARGET_FPMS / 1000;\r\n }\r\n //if we don't have a parent to add particles to, then don't do anything.\r\n //this also works as a isDestroyed check\r\n if (!this._parent)\r\n return;\r\n //update existing particles\r\n var i, particle, next;\r\n for (particle = this._activeParticlesFirst; particle; particle = next) {\r\n next = particle.next;\r\n particle.update(delta);\r\n }\r\n var prevX, prevY;\r\n //if the previous position is valid, store these for later interpolation\r\n if (this._prevPosIsValid) {\r\n prevX = this._prevEmitterPos.x;\r\n prevY = this._prevEmitterPos.y;\r\n }\r\n //store current position of the emitter as local variables\r\n var curX = this.ownerPos.x + this.spawnPos.x;\r\n var curY = this.ownerPos.y + this.spawnPos.y;\r\n //spawn new particles\r\n if (this._emit) {\r\n //decrease spawn timer\r\n this._spawnTimer -= delta;\r\n //while _spawnTimer < 0, we have particles to spawn\r\n while (this._spawnTimer <= 0) {\r\n //determine if the emitter should stop spawning\r\n if (this._emitterLife > 0) {\r\n this._emitterLife -= this._frequency;\r\n if (this._emitterLife <= 0) {\r\n this._spawnTimer = 0;\r\n this._emitterLife = 0;\r\n this.emit = false;\r\n break;\r\n }\r\n }\r\n //determine if we have hit the particle limit\r\n if (this.particleCount >= this.maxParticles) {\r\n this._spawnTimer += this._frequency;\r\n continue;\r\n }\r\n //determine the particle lifetime\r\n var lifetime = void 0;\r\n if (this.minLifetime == this.maxLifetime)\r\n lifetime = this.minLifetime;\r\n else\r\n lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime;\r\n //only make the particle if it wouldn't immediately destroy itself\r\n if (-this._spawnTimer < lifetime) {\r\n //If the position has changed and this isn't the first spawn,\r\n //interpolate the spawn position\r\n var emitPosX = void 0, emitPosY = void 0;\r\n if (this._prevPosIsValid && this._posChanged) {\r\n //1 - _spawnTimer / delta, but _spawnTimer is negative\r\n var lerp = 1 + this._spawnTimer / delta;\r\n emitPosX = (curX - prevX) * lerp + prevX;\r\n emitPosY = (curY - prevY) * lerp + prevY;\r\n }\r\n else {\r\n emitPosX = curX;\r\n emitPosY = curY;\r\n }\r\n //create enough particles to fill the wave (non-burst types have a wave of 1)\r\n i = 0;\r\n for (var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) {\r\n //see if we actually spawn one\r\n if (this.spawnChance < 1 && Math.random() >= this.spawnChance)\r\n continue;\r\n //create particle\r\n var p = void 0;\r\n if (this._poolFirst) {\r\n p = this._poolFirst;\r\n this._poolFirst = this._poolFirst.next;\r\n p.next = null;\r\n }\r\n else {\r\n p = new this.particleConstructor(this);\r\n }\r\n //set a random texture if we have more than one\r\n if (this.particleImages.length > 1) {\r\n p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]);\r\n }\r\n else {\r\n //if they are actually the same texture, a standard particle\r\n //will quit early from the texture setting in setTexture().\r\n p.applyArt(this.particleImages[0]);\r\n }\r\n //set up the start and end values\r\n p.alphaList.reset(this.startAlpha);\r\n if (this.minimumSpeedMultiplier != 1) {\r\n p.speedMultiplier = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier;\r\n }\r\n p.speedList.reset(this.startSpeed);\r\n p.acceleration.x = this.acceleration.x;\r\n p.acceleration.y = this.acceleration.y;\r\n p.maxSpeed = this.maxSpeed;\r\n if (this.minimumScaleMultiplier != 1) {\r\n p.scaleMultiplier = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier;\r\n }\r\n p.scaleList.reset(this.startScale);\r\n p.colorList.reset(this.startColor);\r\n //randomize the rotation speed\r\n if (this.minRotationSpeed == this.maxRotationSpeed)\r\n p.rotationSpeed = this.minRotationSpeed;\r\n else\r\n p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed;\r\n p.noRotation = this.noRotation;\r\n //set up the lifetime\r\n p.maxLife = lifetime;\r\n //set the blend mode\r\n p.blendMode = this.particleBlendMode;\r\n //set the custom ease, if any\r\n p.ease = this.customEase;\r\n //set the extra data, if any\r\n p.extraData = this.extraData;\r\n //call the proper function to handle rotation and position of particle\r\n this._spawnFunc(p, emitPosX, emitPosY, i);\r\n //initialize particle\r\n p.init();\r\n //update the particle by the time passed, so the particles are spread out properly\r\n p.update(-this._spawnTimer); //we want a positive delta, because a negative delta messes things up\r\n //add the particle to the display list\r\n if (!p.parent) {\r\n if (this.addAtBack)\r\n this._parent.addChildAt(p, 0);\r\n else\r\n this._parent.addChild(p);\r\n }\r\n else {\r\n //kind of hacky, but performance friendly\r\n //shuffle children to correct place\r\n var children = this._parent.children;\r\n //avoid using splice if possible\r\n if (children[0] == p)\r\n children.shift();\r\n else if (children[children.length - 1] == p)\r\n children.pop();\r\n else {\r\n var index = children.indexOf(p);\r\n children.splice(index, 1);\r\n }\r\n if (this.addAtBack)\r\n children.unshift(p);\r\n else\r\n children.push(p);\r\n }\r\n //add particle to list of active particles\r\n if (this._activeParticlesLast) {\r\n this._activeParticlesLast.next = p;\r\n p.prev = this._activeParticlesLast;\r\n this._activeParticlesLast = p;\r\n }\r\n else {\r\n this._activeParticlesLast = this._activeParticlesFirst = p;\r\n }\r\n ++this.particleCount;\r\n }\r\n }\r\n //increase timer and continue on to any other particles that need to be created\r\n this._spawnTimer += this._frequency;\r\n }\r\n }\r\n //if the position changed before this update, then keep track of that\r\n if (this._posChanged) {\r\n this._prevEmitterPos.x = curX;\r\n this._prevEmitterPos.y = curY;\r\n this._prevPosIsValid = true;\r\n this._posChanged = false;\r\n }\r\n //if we are all done and should destroy ourselves, take care of that\r\n if (!this._emit && !this._activeParticlesFirst) {\r\n if (this._completeCallback) {\r\n this._completeCallback();\r\n }\r\n if (this._destroyWhenComplete) {\r\n this.destroy();\r\n }\r\n }\r\n };\r\n /**\r\n * Positions a particle for a point type emitter.\r\n * @method PIXI.particles.Emitter#_spawnPoint\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnPoint = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on\r\n //starting particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\r\n //drop the particle at the emitter's position\r\n p.position.x = emitPosX;\r\n p.position.y = emitPosY;\r\n };\r\n /**\r\n * Positions a particle for a rectangle type emitter.\r\n * @method PIXI.particles.Emitter#_spawnRect\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnRect = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\r\n //place the particle at a random point in the rectangle\r\n helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x;\r\n helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y;\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a circle type emitter.\r\n * @method PIXI.particles.Emitter#_spawnCircle\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnCircle = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\r\n this.minStartRotation + this.rotation;\r\n //place the particle at a random radius in the circle\r\n helperPoint.x = Math.random() * this.spawnCircle.radius;\r\n helperPoint.y = 0;\r\n //rotate the point to a random angle in the circle\r\n ParticleUtils_1.default.rotatePoint(Math.random() * 360, helperPoint);\r\n //offset by the circle's center\r\n helperPoint.x += this.spawnCircle.x;\r\n helperPoint.y += this.spawnCircle.y;\r\n //rotate the point by the emitter's rotation\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n //set the position, offset by the emitter's position\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a ring type emitter.\r\n * @method PIXI.particles.Emitter#_spawnRing\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnRing = function (p, emitPosX, emitPosY) {\r\n var spawnCircle = this.spawnCircle;\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\r\n this.minStartRotation + this.rotation;\r\n //place the particle at a random radius in the ring\r\n if (spawnCircle.minRadius == spawnCircle.radius) {\r\n helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) +\r\n spawnCircle.minRadius;\r\n }\r\n else\r\n helperPoint.x = spawnCircle.radius;\r\n helperPoint.y = 0;\r\n //rotate the point to a random angle in the circle\r\n var angle = Math.random() * 360;\r\n p.rotation += angle;\r\n ParticleUtils_1.default.rotatePoint(angle, helperPoint);\r\n //offset by the circle's center\r\n helperPoint.x += this.spawnCircle.x;\r\n helperPoint.y += this.spawnCircle.y;\r\n //rotate the point by the emitter's rotation\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n //set the position, offset by the emitter's position\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a burst type emitter.\r\n * @method PIXI.particles.Emitter#_spawnBurst\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave.\r\n */\r\n Emitter.prototype._spawnBurst = function (p, emitPosX, emitPosY, i) {\r\n //set the initial rotation/direction of the particle based on spawn\r\n //angle and rotation of emitter\r\n if (this.particleSpacing === 0)\r\n p.rotation = Math.random() * 360;\r\n else\r\n p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation;\r\n //drop the particle at the emitter's position\r\n p.position.x = emitPosX;\r\n p.position.y = emitPosY;\r\n };\r\n /**\r\n * Kills all active particles immediately.\r\n * @method PIXI.particles.Emitter#cleanup\r\n */\r\n Emitter.prototype.cleanup = function () {\r\n var particle, next;\r\n for (particle = this._activeParticlesFirst; particle; particle = next) {\r\n next = particle.next;\r\n this.recycle(particle);\r\n if (particle.parent)\r\n particle.parent.removeChild(particle);\r\n }\r\n this._activeParticlesFirst = this._activeParticlesLast = null;\r\n this.particleCount = 0;\r\n };\r\n /**\r\n * Destroys the emitter and all of its particles.\r\n * @method PIXI.particles.Emitter#destroy\r\n */\r\n Emitter.prototype.destroy = function () {\r\n //make sure we aren't still listening to any tickers\r\n this.autoUpdate = false;\r\n //puts all active particles in the pool, and removes them from the particle parent\r\n this.cleanup();\r\n //wipe the pool clean\r\n var next;\r\n for (var particle = this._poolFirst; particle; particle = next) {\r\n //store next value so we don't lose it in our destroy call\r\n next = particle.next;\r\n particle.destroy();\r\n }\r\n this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos =\r\n this.startColor = this.startScale = this.startAlpha = this.startSpeed =\r\n this.customEase = this._completeCallback = null;\r\n };\r\n return Emitter;\r\n}());\r\nexports.default = Emitter;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar PropertyList_1 = require(\"./PropertyList\");\r\nvar Sprite = PIXI.Sprite;\r\n/**\r\n * An individual particle image. You shouldn't have to deal with these.\r\n * @memberof PIXI.particles\r\n * @class Particle\r\n * @extends PIXI.Sprite\r\n * @constructor\r\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle.\r\n */\r\nvar Particle = /** @class */ (function (_super) {\r\n __extends(Particle, _super);\r\n function Particle(emitter) {\r\n var _this = \r\n //start off the sprite with a blank texture, since we are going to replace it\r\n //later when the particle is initialized.\r\n _super.call(this) || this;\r\n _this.emitter = emitter;\r\n //particles should be centered\r\n _this.anchor.x = _this.anchor.y = 0.5;\r\n _this.velocity = new PIXI.Point();\r\n _this.maxLife = 0;\r\n _this.age = 0;\r\n _this.ease = null;\r\n _this.extraData = null;\r\n _this.alphaList = new PropertyList_1.default();\r\n _this.speedList = new PropertyList_1.default();\r\n _this.speedMultiplier = 1;\r\n /**\r\n * Acceleration to apply to the particle.\r\n * @property {PIXI.Point} accleration\r\n */\r\n _this.acceleration = new PIXI.Point();\r\n /**\r\n * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\r\n * will disable the maximum speed.\r\n * @property {Number} maxSpeed\r\n * @default NaN\r\n */\r\n _this.maxSpeed = NaN;\r\n /**\r\n * The scale of the particle throughout its life.\r\n * @property {PIXI.particles.PropertyList} scaleList\r\n */\r\n _this.scaleList = new PropertyList_1.default();\r\n /**\r\n * A multiplier from 0-1 applied to the scale of the particle at all times.\r\n * @property {number} scaleMultiplier\r\n */\r\n _this.scaleMultiplier = 1;\r\n /**\r\n * The tint of the particle throughout its life.\r\n * @property {PIXI.particles.PropertyList} colorList\r\n */\r\n _this.colorList = new PropertyList_1.default(true);\r\n /**\r\n * If alpha should be interpolated at all.\r\n * @property {Boolean} _doAlpha\r\n * @private\r\n */\r\n _this._doAlpha = false;\r\n /**\r\n * If scale should be interpolated at all.\r\n * @property {Boolean} _doScale\r\n * @private\r\n */\r\n _this._doScale = false;\r\n /**\r\n * If speed should be interpolated at all.\r\n * @property {Boolean} _doSpeed\r\n * @private\r\n */\r\n _this._doSpeed = false;\r\n /**\r\n * If acceleration should be handled at all. _doSpeed is mutually exclusive with this,\r\n * and _doSpeed gets priority.\r\n * @property {Boolean} _doAcceleration\r\n * @private\r\n */\r\n _this._doAcceleration = false;\r\n /**\r\n * If color should be interpolated at all.\r\n * @property {Boolean} _doColor\r\n * @private\r\n */\r\n _this._doColor = false;\r\n /**\r\n * If normal movement should be handled. Subclasses wishing to override movement\r\n * can set this to false in init().\r\n * @property {Boolean} _doNormalMovement\r\n * @private\r\n */\r\n _this._doNormalMovement = false;\r\n /**\r\n * One divided by the max life of the particle, saved for slightly faster math.\r\n * @property {Number} _oneOverLife\r\n * @private\r\n */\r\n _this._oneOverLife = 0;\r\n /**\r\n * Reference to the next particle in the list.\r\n * @property {Particle} next\r\n * @private\r\n */\r\n _this.next = null;\r\n /**\r\n * Reference to the previous particle in the list.\r\n * @property {Particle} prev\r\n * @private\r\n */\r\n _this.prev = null;\r\n //save often used functions on the instance instead of the prototype for better speed\r\n _this.init = _this.init;\r\n _this.Particle_init = Particle.prototype.init;\r\n _this.update = _this.update;\r\n _this.Particle_update = Particle.prototype.update;\r\n _this.Sprite_destroy = _super.prototype.destroy;\r\n _this.Particle_destroy = Particle.prototype.destroy;\r\n _this.applyArt = _this.applyArt;\r\n _this.kill = _this.kill;\r\n return _this;\r\n }\r\n /**\r\n * Initializes the particle for use, based on the properties that have to\r\n * have been set already on the particle.\r\n * @method PIXI.particles.Particle#init\r\n */\r\n Particle.prototype.init = function () {\r\n //reset the age\r\n this.age = 0;\r\n //set up the velocity based on the start speed and rotation\r\n this.velocity.x = this.speedList.current.value * this.speedMultiplier;\r\n this.velocity.y = 0;\r\n ParticleUtils_1.default.rotatePoint(this.rotation, this.velocity);\r\n if (this.noRotation) {\r\n this.rotation = 0;\r\n }\r\n else {\r\n //convert rotation to Radians from Degrees\r\n this.rotation *= ParticleUtils_1.default.DEG_TO_RADS;\r\n }\r\n //convert rotation speed to Radians from Degrees\r\n this.rotationSpeed *= ParticleUtils_1.default.DEG_TO_RADS;\r\n //set alpha to inital alpha\r\n this.alpha = this.alphaList.current.value;\r\n //set scale to initial scale\r\n this.scale.x = this.scale.y = this.scaleList.current.value;\r\n //figure out what we need to interpolate\r\n this._doAlpha = !!this.alphaList.current.next;\r\n this._doSpeed = !!this.speedList.current.next;\r\n this._doScale = !!this.scaleList.current.next;\r\n this._doColor = !!this.colorList.current.next;\r\n this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0;\r\n //_doNormalMovement can be cancelled by subclasses\r\n this._doNormalMovement = this._doSpeed || this.speedList.current.value !== 0 || this._doAcceleration;\r\n //save our lerp helper\r\n this._oneOverLife = 1 / this.maxLife;\r\n //set the inital color\r\n var color = this.colorList.current.value;\r\n this.tint = ParticleUtils_1.default.combineRGBComponents(color.r, color.g, color.b);\r\n //ensure visibility\r\n this.visible = true;\r\n };\r\n /**\r\n * Sets the texture for the particle. This can be overridden to allow\r\n * for an animated particle.\r\n * @method PIXI.particles.Particle#applyArt\r\n * @param {PIXI.Texture} art The texture to set.\r\n */\r\n Particle.prototype.applyArt = function (art) {\r\n this.texture = art || PIXI.Texture.EMPTY;\r\n };\r\n /**\r\n * Updates the particle.\r\n * @method PIXI.particles.Particle#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\r\n * properties. A value of -1 means the particle died of old age instead.\r\n */\r\n Particle.prototype.update = function (delta) {\r\n //increase age\r\n this.age += delta;\r\n //recycle particle if it is too old\r\n if (this.age >= this.maxLife) {\r\n this.kill();\r\n return -1;\r\n }\r\n //determine our interpolation value\r\n var lerp = this.age * this._oneOverLife; //lifetime / maxLife;\r\n if (this.ease) {\r\n if (this.ease.length == 4) {\r\n //the t, b, c, d parameters that some tween libraries use\r\n //(time, initial value, end value, duration)\r\n lerp = this.ease(lerp, 0, 1, 1);\r\n }\r\n else {\r\n //the simplified version that we like that takes\r\n //one parameter, time from 0-1. TweenJS eases provide this usage.\r\n lerp = this.ease(lerp);\r\n }\r\n }\r\n //interpolate alpha\r\n if (this._doAlpha)\r\n this.alpha = this.alphaList.interpolate(lerp);\r\n //interpolate scale\r\n if (this._doScale) {\r\n var scale = this.scaleList.interpolate(lerp) * this.scaleMultiplier;\r\n this.scale.x = this.scale.y = scale;\r\n }\r\n //handle movement\r\n if (this._doNormalMovement) {\r\n //interpolate speed\r\n if (this._doSpeed) {\r\n var speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\r\n ParticleUtils_1.default.normalize(this.velocity);\r\n ParticleUtils_1.default.scaleBy(this.velocity, speed);\r\n }\r\n else if (this._doAcceleration) {\r\n this.velocity.x += this.acceleration.x * delta;\r\n this.velocity.y += this.acceleration.y * delta;\r\n if (this.maxSpeed) {\r\n var currentSpeed = ParticleUtils_1.default.length(this.velocity);\r\n //if we are going faster than we should, clamp at the max speed\r\n //DO NOT recalculate vector length\r\n if (currentSpeed > this.maxSpeed) {\r\n ParticleUtils_1.default.scaleBy(this.velocity, this.maxSpeed / currentSpeed);\r\n }\r\n }\r\n }\r\n //adjust position based on velocity\r\n this.position.x += this.velocity.x * delta;\r\n this.position.y += this.velocity.y * delta;\r\n }\r\n //interpolate color\r\n if (this._doColor) {\r\n this.tint = this.colorList.interpolate(lerp);\r\n }\r\n //update rotation\r\n if (this.rotationSpeed !== 0) {\r\n this.rotation += this.rotationSpeed * delta;\r\n }\r\n else if (this.acceleration && !this.noRotation) {\r\n this.rotation = Math.atan2(this.velocity.y, this.velocity.x); // + Math.PI / 2;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Kills the particle, removing it from the display list\r\n * and telling the emitter to recycle it.\r\n * @method PIXI.particles.Particle#kill\r\n */\r\n Particle.prototype.kill = function () {\r\n this.emitter.recycle(this);\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.Particle#destroy\r\n */\r\n Particle.prototype.destroy = function () {\r\n if (this.parent)\r\n this.parent.removeChild(this);\r\n this.Sprite_destroy();\r\n this.emitter = this.velocity = this.colorList = this.scaleList = this.alphaList =\r\n this.speedList = this.ease = this.next = this.prev = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time.\r\n * @method PIXI.particles.Particle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\r\n * Any strings in the array will be converted to Textures via\r\n * Texture.fromImage().\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n Particle.parseArt = function (art) {\r\n //convert any strings to Textures.\r\n var i;\r\n for (i = art.length; i >= 0; --i) {\r\n if (typeof art[i] == \"string\")\r\n art[i] = PIXI.Texture.fromImage(art[i]);\r\n }\r\n //particles from different base textures will be slower in WebGL than if they\r\n //were from one spritesheet\r\n if (ParticleUtils_1.default.verbose) {\r\n for (i = art.length - 1; i > 0; --i) {\r\n if (art[i].baseTexture != art[i - 1].baseTexture) {\r\n if (window.console)\r\n console.warn(\"PixiParticles: using particle textures from different images may hinder performance in WebGL\");\r\n break;\r\n }\r\n }\r\n }\r\n return art;\r\n };\r\n /**\r\n * Parses extra emitter data to ensure it is set up for this particle class.\r\n * Particle does nothing to the extra data.\r\n * @method PIXI.particles.Particle.parseData\r\n * @static\r\n * @param {Object} extraData The extra data from the particle config.\r\n * @return {Object} The parsed extra data.\r\n */\r\n Particle.parseData = function (extraData) {\r\n return extraData;\r\n };\r\n return Particle;\r\n}(Sprite));\r\nexports.default = Particle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar BLEND_MODES = PIXI.BLEND_MODES;\r\nvar PropertyNode_1 = require(\"./PropertyNode\");\r\n/**\r\n * Contains helper functions for particles and emitters to use.\r\n * @memberof PIXI.particles\r\n * @class ParticleUtils\r\n * @static\r\n */\r\nvar ParticleUtils = {\r\n /**\r\n * If errors and warnings should be logged within the library.\r\n * @name PIXI.particles.ParticleUtils.verbose\r\n * @default false\r\n * @static\r\n */\r\n verbose: false,\r\n DEG_TO_RADS: Math.PI / 180,\r\n /**\r\n * Rotates a point by a given angle.\r\n * @method PIXI.particles.ParticleUtils.rotatePoint\r\n * @param {Number} angle The angle to rotate by in degrees\r\n * @param {PIXI.Point} p The point to rotate around 0,0.\r\n * @static\r\n */\r\n rotatePoint: function (angle, p) {\r\n if (!angle)\r\n return;\r\n angle *= ParticleUtils.DEG_TO_RADS;\r\n var s = Math.sin(angle);\r\n var c = Math.cos(angle);\r\n var xnew = p.x * c - p.y * s;\r\n var ynew = p.x * s + p.y * c;\r\n p.x = xnew;\r\n p.y = ynew;\r\n },\r\n /**\r\n * Combines separate color components (0-255) into a single uint color.\r\n * @method PIXI.particles.ParticleUtils.combineRGBComponents\r\n * @param {uint} r The red value of the color\r\n * @param {uint} g The green value of the color\r\n * @param {uint} b The blue value of the color\r\n * @return {uint} The color in the form of 0xRRGGBB\r\n * @static\r\n */\r\n combineRGBComponents: function (r, g, b /*, a*/) {\r\n return /*a << 24 |*/ r << 16 | g << 8 | b;\r\n },\r\n /**\r\n * Reduces the point to a length of 1.\r\n * @method PIXI.particles.ParticleUtils.normalize\r\n * @static\r\n * @param {PIXI.Point} point The point to normalize\r\n */\r\n normalize: function (point) {\r\n var oneOverLen = 1 / ParticleUtils.length(point);\r\n point.x *= oneOverLen;\r\n point.y *= oneOverLen;\r\n },\r\n /**\r\n * Multiplies the x and y values of this point by a value.\r\n * @method PIXI.particles.ParticleUtils.scaleBy\r\n * @static\r\n * @param {PIXI.Point} point The point to scaleBy\r\n * @param {number} value The value to scale by.\r\n */\r\n scaleBy: function (point, value) {\r\n point.x *= value;\r\n point.y *= value;\r\n },\r\n /**\r\n * Returns the length (or magnitude) of this point.\r\n * @method PIXI.particles.ParticleUtils.length\r\n * @static\r\n * @param {PIXI.Point} point The point to measure length\r\n * @return The length of this point.\r\n */\r\n length: function (point) {\r\n return Math.sqrt(point.x * point.x + point.y * point.y);\r\n },\r\n /**\r\n * Converts a hex string from \"#AARRGGBB\", \"#RRGGBB\", \"0xAARRGGBB\", \"0xRRGGBB\",\r\n * \"AARRGGBB\", or \"RRGGBB\" to an object of ints of 0-255, as\r\n * {r, g, b, (a)}.\r\n * @method PIXI.particles.ParticleUtils.hexToRGB\r\n * @param {string} color The input color string.\r\n * @param {Object} [output] An object to put the output in. If omitted, a new object is created.\r\n * @return The object with r, g, and b properties, possibly with an a property.\r\n * @static\r\n */\r\n hexToRGB: function (color, output) {\r\n if (!output)\r\n output = {};\r\n if (color.charAt(0) == \"#\")\r\n color = color.substr(1);\r\n else if (color.indexOf(\"0x\") === 0)\r\n color = color.substr(2);\r\n var alpha;\r\n if (color.length == 8) {\r\n alpha = color.substr(0, 2);\r\n color = color.substr(2);\r\n }\r\n output.r = parseInt(color.substr(0, 2), 16); //Red\r\n output.g = parseInt(color.substr(2, 2), 16); //Green\r\n output.b = parseInt(color.substr(4, 2), 16); //Blue\r\n if (alpha)\r\n output.a = parseInt(alpha, 16);\r\n return output;\r\n },\r\n /**\r\n * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated\r\n * by the related tool at http://www.greensock.com/customease/.\r\n * @method PIXI.particles.ParticleUtils.generateEase\r\n * @param {Array} segments An array of segments, as created by\r\n * http://www.greensock.com/customease/.\r\n * @return {Function} A function that calculates the percentage of change at\r\n * a given point in time (0-1 inclusive).\r\n * @static\r\n */\r\n generateEase: function (segments) {\r\n var qty = segments.length;\r\n var oneOverQty = 1 / qty;\r\n /*\r\n * Calculates the percentage of change at a given point in time (0-1 inclusive).\r\n * @param {Number} time The time of the ease, 0-1 inclusive.\r\n * @return {Number} The percentage of the change, 0-1 inclusive (unless your\r\n * ease goes outside those bounds).\r\n */\r\n return function (time) {\r\n var t, s;\r\n var i = (qty * time) | 0; //do a quick floor operation\r\n t = (time - (i * oneOverQty)) * qty;\r\n s = segments[i] || segments[qty - 1];\r\n return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s)));\r\n };\r\n },\r\n /**\r\n * Gets a blend mode, ensuring that it is valid.\r\n * @method PIXI.particles.ParticleUtils.getBlendMode\r\n * @param {string} name The name of the blend mode to get.\r\n * @return {int} The blend mode as specified in the PIXI.BLEND_MODES enumeration.\r\n * @static\r\n */\r\n getBlendMode: function (name) {\r\n if (!name)\r\n return BLEND_MODES.NORMAL;\r\n name = name.toUpperCase();\r\n while (name.indexOf(\" \") >= 0)\r\n name = name.replace(\" \", \"_\");\r\n return BLEND_MODES[name] || BLEND_MODES.NORMAL;\r\n },\r\n /**\r\n * Converts a list of {value, time} objects starting at time 0 and ending at time 1 into an evenly\r\n * spaced stepped list of PropertyNodes for color values. This is primarily to handle conversion of\r\n * linear gradients to fewer colors, allowing for some optimization for Canvas2d fallbacks.\r\n * @method PIXI.particles.ParticleUtils.createSteppedGradient\r\n * @param {Array} list The list of data to convert.\r\n * @param {number} [numSteps=10] The number of steps to use.\r\n * @return {PIXI.particles.PropertyNode} The blend mode as specified in the PIXI.blendModes enumeration.\r\n * @static\r\n */\r\n createSteppedGradient: function (list, numSteps) {\r\n if (numSteps === void 0) { numSteps = 10; }\r\n if (typeof numSteps !== 'number' || numSteps <= 0)\r\n numSteps = 10;\r\n var first = new PropertyNode_1.default(list[0].value, list[0].time);\r\n first.isStepped = true;\r\n var currentNode = first;\r\n var current = list[0];\r\n var nextIndex = 1;\r\n var next = list[nextIndex];\r\n for (var i = 1; i < numSteps; ++i) {\r\n var lerp = i / numSteps;\r\n //ensure we are on the right segment, if multiple\r\n while (lerp > next.time) {\r\n current = next;\r\n next = list[++nextIndex];\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - current.time) / (next.time - current.time);\r\n var curVal = ParticleUtils.hexToRGB(current.value);\r\n var nextVal = ParticleUtils.hexToRGB(next.value);\r\n var output = {};\r\n output.r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n output.g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n output.b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n currentNode.next = new PropertyNode_1.default(output, i / numSteps);\r\n currentNode = currentNode.next;\r\n }\r\n //we don't need to have a PropertyNode for time of 1, because in a stepped version at that point\r\n //the particle has died of old age\r\n return first;\r\n }\r\n};\r\nexports.default = ParticleUtils;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar Particle_1 = require(\"./Particle\");\r\n/**\r\n * A helper point for math things.\r\n * @private\r\n */\r\nvar helperPoint = new PIXI.Point();\r\n//a hand picked list of Math functions (and a couple properties) that are allowable.\r\n//they should be used without the preceding \"Math.\"\r\nvar MATH_FUNCS = [\r\n \"pow\",\r\n \"sqrt\",\r\n \"abs\",\r\n \"floor\",\r\n \"round\",\r\n \"ceil\",\r\n \"E\",\r\n \"PI\",\r\n \"sin\",\r\n \"cos\",\r\n \"tan\",\r\n \"asin\",\r\n \"acos\",\r\n \"atan\",\r\n \"atan2\",\r\n \"log\"\r\n];\r\n//create an actual regular expression object from the string\r\nvar WHITELISTER = new RegExp([\r\n //Allow the 4 basic operations, parentheses and all numbers/decimals, as well\r\n //as 'x', for the variable usage.\r\n \"[01234567890\\\\.\\\\*\\\\-\\\\+\\\\/\\\\(\\\\)x ,]\",\r\n].concat(MATH_FUNCS).join(\"|\"), \"g\");\r\n/**\r\n * Parses a string into a function for path following.\r\n * This involves whitelisting the string for safety, inserting \"Math.\" to math function\r\n * names, and using `new Function()` to generate a function.\r\n * @method PIXI.particles.PathParticle~parsePath\r\n * @private\r\n * @static\r\n * @param {String} pathString The string to parse.\r\n * @return {Function} The path function - takes x, outputs y.\r\n */\r\nvar parsePath = function (pathString) {\r\n var matches = pathString.match(WHITELISTER);\r\n for (var i = matches.length - 1; i >= 0; --i) {\r\n if (MATH_FUNCS.indexOf(matches[i]) >= 0)\r\n matches[i] = \"Math.\" + matches[i];\r\n }\r\n pathString = matches.join(\"\");\r\n return new Function(\"x\", \"return \" + pathString + \";\");\r\n};\r\n/**\r\n * An particle that follows a path defined by an algebraic expression, e.g. \"sin(x)\" or\r\n * \"5x + 3\".\r\n * To use this class, the particle config must have a \"path\" string in the\r\n * \"extraData\" parameter. This string should have \"x\" in it to represent movement (from the\r\n * speed settings of the particle). It may have numbers, parentheses, the four basic\r\n * operations, and the following Math functions or properties (without the preceding \"Math.\"):\r\n * \"pow\", \"sqrt\", \"abs\", \"floor\", \"round\", \"ceil\", \"E\", \"PI\", \"sin\", \"cos\", \"tan\", \"asin\",\r\n * \"acos\", \"atan\", \"atan2\", \"log\".\r\n * The overall movement of the particle and the expression value become x and y positions for\r\n * the particle, respectively. The final position is rotated by the spawn rotation/angle of\r\n * the particle.\r\n *\r\n * Some example paths:\r\n *\r\n * \t\"sin(x/10) * 20\" // A sine wave path.\r\n * \t\"cos(x/100) * 30\" // Particles curve counterclockwise (for medium speed/low lifetime particles)\r\n * \t\"pow(x/10, 2) / 2\" // Particles curve clockwise (remember, +y is down).\r\n *\r\n * @memberof PIXI.particles\r\n * @class PathParticle\r\n * @extends PIXI.particles.Particle\r\n * @constructor\r\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle.\r\n */\r\nvar PathParticle = /** @class */ (function (_super) {\r\n __extends(PathParticle, _super);\r\n function PathParticle(emitter) {\r\n var _this = _super.call(this, emitter) || this;\r\n _this.path = null;\r\n _this.initialRotation = 0;\r\n _this.initialPosition = new PIXI.Point();\r\n _this.movement = 0;\r\n return _this;\r\n }\r\n /**\r\n * Initializes the particle for use, based on the properties that have to\r\n * have been set already on the particle.\r\n * @method PIXI.particles.PathParticle#init\r\n */\r\n PathParticle.prototype.init = function () {\r\n //get initial rotation before it is converted to radians\r\n this.initialRotation = this.rotation;\r\n //standard init\r\n this.Particle_init();\r\n //set the path for the particle\r\n this.path = this.extraData.path;\r\n //cancel the normal movement behavior\r\n this._doNormalMovement = !this.path;\r\n //reset movement\r\n this.movement = 0;\r\n //grab position\r\n this.initialPosition.x = this.position.x;\r\n this.initialPosition.y = this.position.y;\r\n };\r\n /**\r\n * Updates the particle.\r\n * @method PIXI.particles.PathParticle#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n */\r\n PathParticle.prototype.update = function (delta) {\r\n var lerp = this.Particle_update(delta);\r\n //if the particle died during the update, then don't bother\r\n if (lerp >= 0 && this.path) {\r\n //increase linear movement based on speed\r\n var speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\r\n this.movement += speed * delta;\r\n //set up the helper point for rotation\r\n helperPoint.x = this.movement;\r\n helperPoint.y = this.path(this.movement);\r\n ParticleUtils_1.default.rotatePoint(this.initialRotation, helperPoint);\r\n this.position.x = this.initialPosition.x + helperPoint.x;\r\n this.position.y = this.initialPosition.y + helperPoint.y;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.PathParticle#destroy\r\n */\r\n PathParticle.prototype.destroy = function () {\r\n this.Particle_destroy();\r\n this.path = this.initialPosition = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time. This just runs Particle.parseArt().\r\n * @method PIXI.particles.PathParticle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\r\n * Any strings in the array will be converted to Textures via\r\n * Texture.fromImage().\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n PathParticle.parseArt = function (art) {\r\n return Particle_1.default.parseArt(art);\r\n };\r\n /**\r\n * Parses extra emitter data to ensure it is set up for this particle class.\r\n * PathParticle checks for the existence of path data, and parses the path data for use\r\n * by particle instances.\r\n * @method PIXI.particles.PathParticle.parseData\r\n * @static\r\n * @param {Object} extraData The extra data from the particle config.\r\n * @return {Object} The parsed extra data.\r\n */\r\n PathParticle.parseData = function (extraData) {\r\n var output = {};\r\n if (extraData && extraData.path) {\r\n try {\r\n output.path = parsePath(extraData.path);\r\n }\r\n catch (e) {\r\n if (ParticleUtils_1.default.verbose)\r\n console.error(\"PathParticle: error in parsing path expression\");\r\n output.path = null;\r\n }\r\n }\r\n else {\r\n if (ParticleUtils_1.default.verbose)\r\n console.error(\"PathParticle requires a path string in extraData!\");\r\n output.path = null;\r\n }\r\n return output;\r\n };\r\n return PathParticle;\r\n}(Particle_1.default));\r\nexports.default = PathParticle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\n/**\r\n * Singly linked list container for keeping track of interpolated properties for particles.\r\n * Each Particle will have one of these for each interpolated property.\r\n * @memberof PIXI.particles\r\n * @class PropertyList\r\n * @constructor\r\n * @param {boolean} isColor If this list handles color values\r\n */\r\nvar PropertyList = /** @class */ (function () {\r\n function PropertyList(isColor) {\r\n if (isColor === void 0) { isColor = false; }\r\n this.current = null;\r\n this.next = null;\r\n this.isColor = !!isColor;\r\n this.interpolate = null;\r\n this.ease = null;\r\n }\r\n /**\r\n * Resets the list for use.\r\n * @method interpolate\r\n * @param {PIXI.particles.PropertyNode} first The first node in the list.\r\n * @param {boolean} [isStepped=false] If the values should be stepped instead of interpolated linearly.\r\n */\r\n PropertyList.prototype.reset = function (first) {\r\n this.current = first;\r\n this.next = first.next;\r\n var isSimple = this.next && this.next.time >= 1;\r\n if (isSimple) {\r\n this.interpolate = this.isColor ? intColorSimple : intValueSimple;\r\n }\r\n else if (first.isStepped) {\r\n this.interpolate = this.isColor ? intColorStepped : intValueStepped;\r\n }\r\n else {\r\n this.interpolate = this.isColor ? intColorComplex : intValueComplex;\r\n }\r\n this.ease = this.current.ease;\r\n };\r\n return PropertyList;\r\n}());\r\nexports.default = PropertyList;\r\nfunction intValueSimple(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n return (this.next.value - this.current.value) * lerp + this.current.value;\r\n}\r\nfunction intColorSimple(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n var curVal = this.current.value, nextVal = this.next.value;\r\n var r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n var g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n var b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n return ParticleUtils_1.default.combineRGBComponents(r, g, b);\r\n}\r\nfunction intValueComplex(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\r\n return (this.next.value - this.current.value) * lerp + this.current.value;\r\n}\r\nfunction intColorComplex(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\r\n var curVal = this.current.value, nextVal = this.next.value;\r\n var r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n var g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n var b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n return ParticleUtils_1.default.combineRGBComponents(r, g, b);\r\n}\r\nfunction intValueStepped(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (this.next && lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n return this.current.value;\r\n}\r\nfunction intColorStepped(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (this.next && lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n var curVal = this.current.value;\r\n return ParticleUtils_1.default.combineRGBComponents(curVal.r, curVal.g, curVal.b);\r\n}\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\n/**\r\n * A single node in a PropertyList.\r\n * @memberof PIXI.particles\r\n * @class PropertyNode\r\n * @constructor\r\n * @param {number|string} value The value for this node\r\n * @param {number} time The time for this node, between 0-1\r\n * @param {Function|Array} [ease] Custom ease for this list. Only relevant for the first node.\r\n */\r\nvar PropertyNode = /** @class */ (function () {\r\n function PropertyNode(value, time, ease) {\r\n this.value = typeof value == \"string\" ? ParticleUtils_1.default.hexToRGB(value) : value;\r\n this.time = time;\r\n this.next = null;\r\n this.isStepped = false;\r\n if (ease) {\r\n this.ease = typeof ease == \"function\" ? ease : ParticleUtils_1.default.generateEase(ease);\r\n }\r\n else {\r\n this.ease = null;\r\n }\r\n }\r\n /**\r\n * Creates a list of property values from a data object {list, isStepped} with a list of objects in\r\n * the form {value, time}. Alternatively, the data object can be in the deprecated form of\r\n * {start, end}.\r\n * @method PIXI.particles.PropertyNode.createListFromArray\r\n * @static\r\n * @param {Object} data The data for the list.\r\n * @param {Array} data.list The array of value and time objects.\r\n * @param {boolean} [data.isStepped] If the list is stepped rather than interpolated.\r\n * @param {Function|Array} [data.ease] Custom ease for this list.\r\n * @return {PIXI.particles.PropertyNode} The first node in the list\r\n */\r\n PropertyNode.createList = function (data) {\r\n if (Array.isArray(data.list)) {\r\n var array = data.list;\r\n var node = void 0, first = void 0;\r\n first = node = new PropertyNode(array[0].value, array[0].time, data.ease);\r\n //only set up subsequent nodes if there are a bunch or the 2nd one is different from the first\r\n if (array.length > 2 || (array.length === 2 && array[1].value !== array[0].value)) {\r\n for (var i = 1; i < array.length; ++i) {\r\n node.next = new PropertyNode(array[i].value, array[i].time);\r\n node = node.next;\r\n }\r\n }\r\n first.isStepped = !!data.isStepped;\r\n return first;\r\n }\r\n else {\r\n //Handle deprecated version here\r\n var start = new PropertyNode(data.start, 0);\r\n //only set up a next value if it is different from the starting value\r\n if (data.end !== data.start)\r\n start.next = new PropertyNode(data.end, 1);\r\n return start;\r\n }\r\n };\r\n return PropertyNode;\r\n}());\r\nexports.default = PropertyNode;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_js_1 = require(\"./ParticleUtils.js\");\r\nexports.ParticleUtils = ParticleUtils_js_1.default;\r\nvar Particle_js_1 = require(\"./Particle.js\");\r\nexports.Particle = Particle_js_1.default;\r\nvar Emitter_js_1 = require(\"./Emitter.js\");\r\nexports.Emitter = Emitter_js_1.default;\r\nvar PathParticle_js_1 = require(\"./PathParticle.js\");\r\nexports.PathParticle = PathParticle_js_1.default;\r\nvar AnimatedParticle_js_1 = require(\"./AnimatedParticle.js\");\r\nexports.AnimatedParticle = AnimatedParticle_js_1.default;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n// If we're in the browser make sure PIXI is available\r\nif (typeof PIXI === 'undefined') {\r\n throw \"pixi-particles requires pixi.js to be loaded first\";\r\n}\r\n//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not\r\nif (!PIXI.particles) {\r\n PIXI.particles = {};\r\n}\r\n// get the library itself\r\nvar particles = require(\"./particles\");\r\n// insert the library into the particles namespace on PIXI\r\nfor (var prop in particles) {\r\n PIXI.particles[prop] = particles[prop];\r\n}\r\n"],"sourceRoot":"."} \ No newline at end of file diff --git a/dist/pixi-particles.min.js b/dist/pixi-particles.min.js index 9a281248..07892192 100644 --- a/dist/pixi-particles.min.js +++ b/dist/pixi-particles.min.js @@ -1,9 +1,9 @@ /*! * pixi-particles - v2.1.9 - * Compiled Thu, 16 Nov 2017 01:52:39 UTC + * Compiled Mon, 12 Feb 2018 03:27:46 UTC * * pixi-particles is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i;i="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,i.pixiParticles=t()}}(function(){return function t(i,e,s){function a(n,o){if(!e[n]){if(!i[n]){var h="function"==typeof require&&require;if(!o&&h)return h(n,!0);if(r)return r(n,!0);var l=new Error("Cannot find module '"+n+"'");throw l.code="MODULE_NOT_FOUND",l}var p=e[n]={exports:{}};i[n][0].call(p.exports,function(t){var e=i[n][1][t];return a(e?e:t)},p,p.exports,t,i,e,s)}return e[n].exports}for(var r="function"==typeof require&&require,n=0;n=0){this.elapsed+=t,this.elapsed>this.duration&&(this.loop?this.elapsed=this.elapsed%this.duration:this.elapsed=this.duration-1e-6);var i=this.elapsed*this.framerate+1e-7|0;this.texture=this.textures[i]||s.EMPTY_TEXTURE}},h.Particle_destroy=a.prototype.destroy,h.destroy=function(){this.Particle_destroy(),this.textures=null},n.parseArt=function(t){var i,e,s,a,n,o,h=[];for(i=0;i0;--l)o.push(n)}"matchLife"==e.framerate?(h.framerate=-1,h.duration=0,h.loop=!1):(h.loop=!!e.loop,h.framerate=e.framerate>0?e.framerate:60,h.duration=o.length/h.framerate)}return t},i.exports=n},{"./Particle":3,"./ParticleUtils":4}],2:[function(t,i,e){"use strict";var s=t("./ParticleUtils"),a=t("./Particle"),r=PIXI.particles.ParticleContainer||PIXI.ParticleContainer,n=PIXI.ticker.shared,o=function(t,i,e){this._particleConstructor=a,this.particleImages=null,this.startAlpha=1,this.endAlpha=1,this.startSpeed=0,this.endSpeed=0,this.minimumSpeedMultiplier=1,this.acceleration=null,this.maxSpeed=NaN,this.startScale=1,this.endScale=1,this.minimumScaleMultiplier=1,this.startColor=null,this.endColor=null,this.minLifetime=0,this.maxLifetime=0,this.minStartRotation=0,this.maxStartRotation=0,this.noRotation=!1,this.minRotationSpeed=0,this.maxRotationSpeed=0,this.particleBlendMode=0,this.customEase=null,this.extraData=null,this._frequency=1,this.maxParticles=1e3,this.emitterLifetime=-1,this.spawnPos=null,this.spawnType=null,this._spawnFunc=null,this.spawnRect=null,this.spawnCircle=null,this.particlesPerWave=1,this.particleSpacing=0,this.angleStart=0,this.rotation=0,this.ownerPos=null,this._prevEmitterPos=null,this._prevPosIsValid=!1,this._posChanged=!1,this._parentIsPC=!1,this._parent=null,this.addAtBack=!1,this.particleCount=0,this._emit=!1,this._spawnTimer=0,this._emitterLife=-1,this._activeParticlesFirst=null,this._activeParticlesLast=null,this._poolFirst=null,this._origConfig=null,this._origArt=null,this._autoUpdate=!1,this._destroyWhenComplete=!1,this._completeCallback=null,this.parent=t,i&&e&&this.init(i,e),this.recycle=this.recycle,this.update=this.update,this.rotate=this.rotate,this.updateSpawnPos=this.updateSpawnPos,this.updateOwnerPos=this.updateOwnerPos},h=o.prototype={},l=new PIXI.Point;Object.defineProperty(h,"frequency",{get:function(){return this._frequency},set:function(t){"number"==typeof t&&t>0?this._frequency=t:this._frequency=1}}),Object.defineProperty(h,"particleConstructor",{get:function(){return this._particleConstructor},set:function(t){if(t!=this._particleConstructor){this._particleConstructor=t,this.cleanup();for(var i=this._poolFirst;i;i=i.next)i.destroy();this._poolFirst=null,this._origConfig&&this._origArt&&this.init(this._origArt,this._origConfig)}}}),Object.defineProperty(h,"parent",{get:function(){return this._parent},set:function(t){if(this._parentIsPC)for(var i=this._poolFirst;i;i=i.next)i.parent&&i.parent.removeChild(i);this.cleanup(),this._parent=t,this._parentIsPC=r&&t&&t instanceof r}}),h.init=function(t,i){if(t&&i){this.cleanup(),this._origConfig=i,this._origArt=t,t=Array.isArray(t)?t.slice():[t];var e=this._particleConstructor;this.particleImages=e.parseArt?e.parseArt(t):t,i.alpha?(this.startAlpha=i.alpha.start,this.endAlpha=i.alpha.end):this.startAlpha=this.endAlpha=1,i.speed?(this.startSpeed=i.speed.start,this.endSpeed=i.speed.end,this.minimumSpeedMultiplier=i.speed.minimumSpeedMultiplier||1):(this.minimumSpeedMultiplier=1,this.startSpeed=this.endSpeed=0);var a=i.acceleration;a&&(a.x||a.y)?(this.endSpeed=this.startSpeed,this.acceleration=new PIXI.Point(a.x,a.y),this.maxSpeed=i.maxSpeed||NaN):this.acceleration=new PIXI.Point,i.scale?(this.startScale=i.scale.start,this.endScale=i.scale.end,this.minimumScaleMultiplier=i.scale.minimumScaleMultiplier||1):this.startScale=this.endScale=this.minimumScaleMultiplier=1,i.color&&(this.startColor=s.hexToRGB(i.color.start),i.color.start!=i.color.end?this.endColor=s.hexToRGB(i.color.end):this.endColor=null),i.startRotation?(this.minStartRotation=i.startRotation.min,this.maxStartRotation=i.startRotation.max):this.minStartRotation=this.maxStartRotation=0,i.noRotation&&(this.minStartRotation||this.maxStartRotation)?this.noRotation=!!i.noRotation:this.noRotation=!1,i.rotationSpeed?(this.minRotationSpeed=i.rotationSpeed.min,this.maxRotationSpeed=i.rotationSpeed.max):this.minRotationSpeed=this.maxRotationSpeed=0,this.minLifetime=i.lifetime.min,this.maxLifetime=i.lifetime.max,this.particleBlendMode=s.getBlendMode(i.blendMode),i.ease?this.customEase="function"==typeof i.ease?i.ease:s.generateEase(i.ease):this.customEase=null,e.parseData?this.extraData=e.parseData(i.extraData):this.extraData=i.extraData||null,this.spawnRect=this.spawnCircle=null,this.particlesPerWave=1,this.particleSpacing=0,this.angleStart=0;var r;switch(i.spawnType){case"rect":this.spawnType="rect",this._spawnFunc=this._spawnRect;var n=i.spawnRect;this.spawnRect=new PIXI.Rectangle(n.x,n.y,n.w,n.h);break;case"circle":this.spawnType="circle",this._spawnFunc=this._spawnCircle,r=i.spawnCircle,this.spawnCircle=new PIXI.Circle(r.x,r.y,r.r);break;case"ring":this.spawnType="ring",this._spawnFunc=this._spawnRing,r=i.spawnCircle,this.spawnCircle=new PIXI.Circle(r.x,r.y,r.r),this.spawnCircle.minRadius=r.minR;break;case"burst":this.spawnType="burst",this._spawnFunc=this._spawnBurst,this.particlesPerWave=i.particlesPerWave,this.particleSpacing=i.particleSpacing,this.angleStart=i.angleStart?i.angleStart:0;break;case"point":this.spawnType="point",this._spawnFunc=this._spawnPoint;break;default:this.spawnType="point",this._spawnFunc=this._spawnPoint}this.frequency=i.frequency,this.emitterLifetime=i.emitterLifetime||-1,this.maxParticles=i.maxParticles>0?i.maxParticles:1e3,this.addAtBack=!!i.addAtBack,this.rotation=0,this.ownerPos=new PIXI.Point,this.spawnPos=new PIXI.Point(i.pos.x,i.pos.y),this._prevEmitterPos=this.spawnPos.clone(),this._prevPosIsValid=!1,this._spawnTimer=0,this.emit=void 0===i.emit||!!i.emit,this.autoUpdate=void 0!==i.autoUpdate&&!!i.autoUpdate}},h.recycle=function(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t==this._activeParticlesLast&&(this._activeParticlesLast=t.prev),t==this._activeParticlesFirst&&(this._activeParticlesFirst=t.next),t.prev=null,t.next=this._poolFirst,this._poolFirst=t,this._parentIsPC?(t.alpha=0,t.visible=!1):t.parent&&t.parent.removeChild(t),--this.particleCount},h.rotate=function(t){if(this.rotation!=t){var i=t-this.rotation;this.rotation=t,s.rotatePoint(i,this.spawnPos),this._posChanged=!0}},h.updateSpawnPos=function(t,i){this._posChanged=!0,this.spawnPos.x=t,this.spawnPos.y=i},h.updateOwnerPos=function(t,i){this._posChanged=!0,this.ownerPos.x=t,this.ownerPos.y=i},h.resetPositionTracking=function(){this._prevPosIsValid=!1},Object.defineProperty(h,"emit",{get:function(){return this._emit},set:function(t){this._emit=!!t,this._emitterLife=this.emitterLifetime}}),Object.defineProperty(h,"autoUpdate",{get:function(){return this._autoUpdate},set:function(t){this._autoUpdate&&!t?n.remove(this.update,this):!this._autoUpdate&&t&&n.add(this.update,this),this._autoUpdate=!!t}}),h.playOnceAndDestroy=function(t){this.autoUpdate=!0,this.emit=!0,this._destroyWhenComplete=!0,this._completeCallback=t},h.playOnce=function(t){this.autoUpdate=!0,this.emit=!0,this._completeCallback=t},h.update=function(t){if(this._autoUpdate&&(t=t/PIXI.settings.TARGET_FPMS/1e3),this._parent){var i,e,s;for(e=this._activeParticlesFirst;e;e=s)s=e.next,e.update(t);var a,r;this._prevPosIsValid&&(a=this._prevEmitterPos.x,r=this._prevEmitterPos.y);var n=this.ownerPos.x+this.spawnPos.x,o=this.ownerPos.y+this.spawnPos.y;if(this._emit)for(this._spawnTimer-=t;this._spawnTimer<=0;){if(this._emitterLife>0&&(this._emitterLife-=this._frequency,this._emitterLife<=0)){this._spawnTimer=0,this._emitterLife=0,this.emit=!1;break}if(this.particleCount>=this.maxParticles)this._spawnTimer+=this._frequency;else{var h;if(h=this.minLifetime==this.maxLifetime?this.minLifetime:Math.random()*(this.maxLifetime-this.minLifetime)+this.minLifetime,-this._spawnTimer1?u.applyArt(this.particleImages[Math.floor(Math.random()*this.particleImages.length)]):u.applyArt(this.particleImages[0]),u.startAlpha=this.startAlpha,u.endAlpha=this.endAlpha,1!=this.minimumSpeedMultiplier?(m=Math.random()*(1-this.minimumSpeedMultiplier)+this.minimumSpeedMultiplier,u.startSpeed=this.startSpeed*m,u.endSpeed=this.endSpeed*m):(u.startSpeed=this.startSpeed,u.endSpeed=this.endSpeed),u.acceleration.x=this.acceleration.x,u.acceleration.y=this.acceleration.y,u.maxSpeed=this.maxSpeed,1!=this.minimumScaleMultiplier?(m=Math.random()*(1-this.minimumScaleMultiplier)+this.minimumScaleMultiplier,u.startScale=this.startScale*m,u.endScale=this.endScale*m):(u.startScale=this.startScale,u.endScale=this.endScale),u.startColor=this.startColor,u.endColor=this.endColor,this.minRotationSpeed==this.maxRotationSpeed?u.rotationSpeed=this.minRotationSpeed:u.rotationSpeed=Math.random()*(this.maxRotationSpeed-this.minRotationSpeed)+this.minRotationSpeed,u.noRotation=this.noRotation,u.maxLife=h,u.blendMode=this.particleBlendMode,u.ease=this.customEase,u.extraData=this.extraData,this._spawnFunc(u,l,p,i),u.init(),u.update(-this._spawnTimer),this._parentIsPC&&u.parent){var f=this._parent.children;if(f[0]==u)f.shift();else if(f[f.length-1]==u)f.pop();else{var _=f.indexOf(u);f.splice(_,1)}this.addAtBack?f.unshift(u):f.push(u)}else this.addAtBack?this._parent.addChildAt(u,0):this._parent.addChild(u);this._activeParticlesLast?(this._activeParticlesLast.next=u,u.prev=this._activeParticlesLast,this._activeParticlesLast=u):this._activeParticlesLast=this._activeParticlesFirst=u,++this.particleCount}}this._spawnTimer+=this._frequency}}this._posChanged&&(this._prevEmitterPos.x=n,this._prevEmitterPos.y=o,this._prevPosIsValid=!0,this._posChanged=!1),this._emit||this._activeParticlesFirst||(this._completeCallback&&this._completeCallback(),this._destroyWhenComplete&&this.destroy())}},h._spawnPoint=function(t,i,e){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,t.position.x=i,t.position.y=e},h._spawnRect=function(t,i,e){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,l.x=Math.random()*this.spawnRect.width+this.spawnRect.x,l.y=Math.random()*this.spawnRect.height+this.spawnRect.y,0!==this.rotation&&s.rotatePoint(this.rotation,l),t.position.x=i+l.x,t.position.y=e+l.y},h._spawnCircle=function(t,i,e){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,l.x=Math.random()*this.spawnCircle.radius,l.y=0,s.rotatePoint(360*Math.random(),l),l.x+=this.spawnCircle.x,l.y+=this.spawnCircle.y,0!==this.rotation&&s.rotatePoint(this.rotation,l),t.position.x=i+l.x,t.position.y=e+l.y},h._spawnRing=function(t,i,e){var a=this.spawnCircle;this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,a.minRadius==a.radius?l.x=Math.random()*(a.radius-a.minRadius)+a.minRadius:l.x=a.radius,l.y=0;var r=360*Math.random();t.rotation+=r,s.rotatePoint(r,l),l.x+=this.spawnCircle.x,l.y+=this.spawnCircle.y,0!==this.rotation&&s.rotatePoint(this.rotation,l),t.position.x=i+l.x,t.position.y=e+l.y},h._spawnBurst=function(t,i,e,s){0===this.particleSpacing?t.rotation=360*Math.random():t.rotation=this.angleStart+this.particleSpacing*s+this.rotation,t.position.x=i,t.position.y=e},h.cleanup=function(){var t,i;for(t=this._activeParticlesFirst;t;t=i)i=t.next,this.recycle(t),t.parent&&t.parent.removeChild(t);this._activeParticlesFirst=this._activeParticlesLast=null,this.particleCount=0},h.destroy=function(){this.autoUpdate=!1,this.cleanup();for(var t,i=this._poolFirst;i;i=t)t=i.next,i.destroy();this._poolFirst=this._parent=this.particleImages=this.spawnPos=this.ownerPos=this.startColor=this.endColor=this.customEase=this._completeCallback=null},i.exports=o},{"./Particle":3,"./ParticleUtils":4}],3:[function(t,i,e){var s=t("./ParticleUtils"),a=PIXI.Sprite,r=function(t){a.call(this),this.emitter=t,this.anchor.x=this.anchor.y=.5,this.velocity=new PIXI.Point,this.maxLife=0,this.age=0,this.ease=null,this.extraData=null,this.startAlpha=0,this.endAlpha=0,this.startSpeed=0,this.endSpeed=0,this.acceleration=new PIXI.Point,this.maxSpeed=NaN,this.startScale=0,this.endScale=0,this.startColor=null,this._sR=0,this._sG=0,this._sB=0,this.endColor=null,this._eR=0,this._eG=0,this._eB=0,this._doAlpha=!1,this._doScale=!1,this._doSpeed=!1,this._doAcceleration=!1,this._doColor=!1,this._doNormalMovement=!1,this._oneOverLife=0,this.next=null,this.prev=null,this.init=this.init,this.Particle_init=this.Particle_init,this.update=this.update,this.Particle_update=this.Particle_update,this.applyArt=this.applyArt,this.kill=this.kill},n=r.prototype=Object.create(a.prototype);n.init=n.Particle_init=function(){this.age=0,this.velocity.x=this.startSpeed,this.velocity.y=0,s.rotatePoint(this.rotation,this.velocity),this.noRotation?this.rotation=0:this.rotation*=s.DEG_TO_RADS,this.rotationSpeed*=s.DEG_TO_RADS,this.alpha=this.startAlpha,this.scale.x=this.scale.y=this.startScale,this.startColor&&(this._sR=this.startColor[0],this._sG=this.startColor[1],this._sB=this.startColor[2],this.endColor&&(this._eR=this.endColor[0],this._eG=this.endColor[1],this._eB=this.endColor[2])),this._doAlpha=this.startAlpha!=this.endAlpha,this._doSpeed=this.startSpeed!=this.endSpeed,this._doScale=this.startScale!=this.endScale,this._doColor=!!this.endColor,this._doAcceleration=0!==this.acceleration.x||0!==this.acceleration.y,this._doNormalMovement=this._doSpeed||0!==this.startSpeed||this._doAcceleration,this._oneOverLife=1/this.maxLife,this.tint=s.combineRGBComponents(this._sR,this._sG,this._sB),this.visible=!0},n.applyArt=function(t){this.texture=t||s.EMPTY_TEXTURE},n.update=n.Particle_update=function(t){if(this.age+=t,this.age>=this.maxLife)return this.kill(),-1;var i=this.age*this._oneOverLife;if(this.ease&&(i=4==this.ease.length?this.ease(i,0,1,1):this.ease(i)),this._doAlpha&&(this.alpha=(this.endAlpha-this.startAlpha)*i+this.startAlpha),this._doScale){var e=(this.endScale-this.startScale)*i+this.startScale;this.scale.x=this.scale.y=e}if(this._doNormalMovement){if(this._doSpeed){var a=(this.endSpeed-this.startSpeed)*i+this.startSpeed;s.normalize(this.velocity),s.scaleBy(this.velocity,a)}else if(this._doAcceleration&&(this.velocity.x+=this.acceleration.x*t,this.velocity.y+=this.acceleration.y*t,this.maxSpeed)){var r=s.length(this.velocity);r>this.maxSpeed&&s.scaleBy(this.velocity,this.maxSpeed/r)}this.position.x+=this.velocity.x*t,this.position.y+=this.velocity.y*t}if(this._doColor){var n=(this._eR-this._sR)*i+this._sR,o=(this._eG-this._sG)*i+this._sG,h=(this._eB-this._sB)*i+this._sB;this.tint=s.combineRGBComponents(n,o,h)}return 0!==this.rotationSpeed?this.rotation+=this.rotationSpeed*t:this.acceleration&&!this.noRotation&&(this.rotation=Math.atan2(this.velocity.y,this.velocity.x)),i},n.kill=function(){this.emitter.recycle(this)},n.Sprite_Destroy=a.prototype.destroy,n.destroy=function(){this.parent&&this.parent.removeChild(this),this.Sprite_Destroy&&this.Sprite_Destroy(),this.emitter=this.velocity=this.startColor=this.endColor=this.ease=this.next=this.prev=null},r.parseArt=function(t){var i;for(i=t.length;i>=0;--i)"string"==typeof t[i]&&(t[i]=PIXI.Texture.fromImage(t[i]));if(s.verbose)for(i=t.length-1;i>0;--i)if(t[i].baseTexture!=t[i-1].baseTexture){window.console&&console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL");break}return t},r.parseData=function(t){return t},i.exports=r},{"./ParticleUtils":4}],4:[function(t,i,e){"use strict";var s=PIXI.BLEND_MODES||PIXI.blendModes,a=PIXI.Texture,r={};r.verbose=!1;var n=r.DEG_TO_RADS=Math.PI/180,o=r.EMPTY_TEXTURE=a.EMPTY;o.on=o.destroy=o.once=o.emit=function(){},r.rotatePoint=function(t,i){if(t){t*=n;var e=Math.sin(t),s=Math.cos(t),a=i.x*s-i.y*e,r=i.x*e+i.y*s;i.x=a,i.y=r}},r.combineRGBComponents=function(t,i,e){return t<<16|i<<8|e},r.normalize=function(t){var i=1/r.length(t);t.x*=i,t.y*=i},r.scaleBy=function(t,i){t.x*=i,t.y*=i},r.length=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},r.hexToRGB=function(t,i){i?i.length=0:i=[],"#"==t.charAt(0)?t=t.substr(1):0===t.indexOf("0x")&&(t=t.substr(2));var e;return 8==t.length&&(e=t.substr(0,2),t=t.substr(2)),i.push(parseInt(t.substr(0,2),16)),i.push(parseInt(t.substr(2,2),16)),i.push(parseInt(t.substr(4,2),16)),e&&i.push(parseInt(e,16)),i},r.generateEase=function(t){var i=t.length,e=1/i,s=function(s){var a,r,n=i*s|0;return a=(s-n*e)*i,r=t[n]||t[i-1],r.s+a*(2*(1-a)*(r.cp-r.s)+a*(r.e-r.s))};return s},r.getBlendMode=function(t){if(!t)return s.NORMAL;for(t=t.toUpperCase();t.indexOf(" ")>=0;)t=t.replace(" ","_");return s[t]||s.NORMAL},i.exports=r},{}],5:[function(t,i,e){"use strict";var s=t("./ParticleUtils"),a=t("./Particle"),r=function(t){a.call(this,t),this.path=null,this.initialRotation=0,this.initialPosition=new PIXI.Point,this.movement=0},n=a.prototype,o=r.prototype=Object.create(n),h=new PIXI.Point;o.init=function(){this.initialRotation=this.rotation,this.Particle_init(),this.path=this.extraData.path,this._doNormalMovement=!this.path,this.movement=0,this.initialPosition.x=this.position.x,this.initialPosition.y=this.position.y};for(var l=["pow","sqrt","abs","floor","round","ceil","E","PI","sin","cos","tan","asin","acos","atan","atan2","log"],p="[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]",c=l.length-1;c>=0;--c)p+="|"+l[c];p=new RegExp(p,"g");var d=function(t){for(var i=t.match(p),e=i.length-1;e>=0;--e)l.indexOf(i[e])>=0&&(i[e]="Math."+i[e]);return t=i.join(""),new Function("x","return "+t+";")};o.update=function(t){var i=this.Particle_update(t);if(i>=0&&this.path){var e=(this.endSpeed-this.startSpeed)*i+this.startSpeed;this.movement+=e*t,h.x=this.movement,h.y=this.path(this.movement),s.rotatePoint(this.initialRotation,h),this.position.x=this.initialPosition.x+h.x,this.position.y=this.initialPosition.y+h.y}},o.Particle_destroy=a.prototype.destroy,o.destroy=function(){this.Particle_destroy(),this.path=this.initialPosition=null},r.parseArt=function(t){return a.parseArt(t)},r.parseData=function(t){var i={};if(t&&t.path)try{i.path=d(t.path)}catch(t){s.verbose&&console.error("PathParticle: error in parsing path expression"),i.path=null}else s.verbose&&console.error("PathParticle requires a path string in extraData!"),i.path=null;return i},i.exports=r},{"./Particle":3,"./ParticleUtils":4}],6:[function(t,i,e){},{}],7:[function(t,i,e){e.ParticleUtils=t("./ParticleUtils.js"),e.Particle=t("./Particle.js"),e.Emitter=t("./Emitter.js"),e.PathParticle=t("./PathParticle.js"),e.AnimatedParticle=t("./AnimatedParticle.js"),t("./deprecation.js")},{"./AnimatedParticle.js":1,"./Emitter.js":2,"./Particle.js":3,"./ParticleUtils.js":4,"./PathParticle.js":5,"./deprecation.js":6}],8:[function(t,i,e){"use strict";var s="undefined"!=typeof window?window:GLOBAL;if(s.PIXI.particles||(s.PIXI.particles={}),"undefined"!=typeof i&&i.exports)"undefined"==typeof PIXI&&t("pixi.js"),i.exports=s.PIXI.particles||a;else if("undefined"==typeof PIXI)throw"pixi-particles requires pixi.js to be loaded first";var a=t("./particles");for(var r in a)s.PIXI.particles[r]=a[r]},{"./particles":7,"pixi.js":void 0}]},{},[8])(8)}); +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.pixiParticles=t()}}(function(){return function(){function t(e,i,s){function a(n,o){if(!i[n]){if(!e[n]){var h="function"==typeof require&&require;if(!o&&h)return h(n,!0);if(r)return r(n,!0);var l=new Error("Cannot find module '"+n+"'");throw l.code="MODULE_NOT_FOUND",l}var p=i[n]={exports:{}};e[n][0].call(p.exports,function(t){var i=e[n][1][t];return a(i||t)},p,p.exports,t,e,i,s)}return i[n].exports}for(var r="function"==typeof require&&require,n=0;n=0){this.elapsed+=t,this.elapsed>this.duration&&(this.loop?this.elapsed=this.elapsed%this.duration:this.elapsed=this.duration-1e-6);var i=this.elapsed*this.framerate+1e-7|0;this.texture=this.textures[i]||PIXI.Texture.EMPTY}return e},e.prototype.destroy=function(){this.Particle_destroy(),this.textures=null},e.parseArt=function(t){for(var e,i,s,a,n,o=[],h=0;h0;--p)n.push(a)}"matchLife"==e.framerate?(i.framerate=-1,i.duration=0,i.loop=!1):(i.loop=!!e.loop,i.framerate=e.framerate>0?e.framerate:60,i.duration=n.length/i.framerate)}return o},e}(a.default);i.default=n},{"./Particle":3}],2:[function(t,e,i){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var s=t("./ParticleUtils"),a=t("./Particle"),r=t("./PropertyNode"),n=PIXI.ticker.shared,o=new PIXI.Point,h=function(){function t(t,e,i){this._particleConstructor=a.default,this.particleImages=null,this.startAlpha=null,this.startSpeed=null,this.minimumSpeedMultiplier=1,this.acceleration=null,this.maxSpeed=NaN,this.startScale=null,this.minimumScaleMultiplier=1,this.startColor=null,this.minLifetime=0,this.maxLifetime=0,this.minStartRotation=0,this.maxStartRotation=0,this.noRotation=!1,this.minRotationSpeed=0,this.maxRotationSpeed=0,this.particleBlendMode=0,this.customEase=null,this.extraData=null,this._frequency=1,this.spawnChance=1,this.maxParticles=1e3,this.emitterLifetime=-1,this.spawnPos=null,this.spawnType=null,this._spawnFunc=null,this.spawnRect=null,this.spawnCircle=null,this.particlesPerWave=1,this.particleSpacing=0,this.angleStart=0,this.rotation=0,this.ownerPos=null,this._prevEmitterPos=null,this._prevPosIsValid=!1,this._posChanged=!1,this._parent=null,this.addAtBack=!1,this.particleCount=0,this._emit=!1,this._spawnTimer=0,this._emitterLife=-1,this._activeParticlesFirst=null,this._activeParticlesLast=null,this._poolFirst=null,this._origConfig=null,this._origArt=null,this._autoUpdate=!1,this._destroyWhenComplete=!1,this._completeCallback=null,this.parent=t,e&&i&&this.init(e,i),this.recycle=this.recycle,this.update=this.update,this.rotate=this.rotate,this.updateSpawnPos=this.updateSpawnPos,this.updateOwnerPos=this.updateOwnerPos}return Object.defineProperty(t.prototype,"frequency",{get:function(){return this._frequency},set:function(t){this._frequency="number"==typeof t&&t>0?t:1},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"particleConstructor",{get:function(){return this._particleConstructor},set:function(t){if(t!=this._particleConstructor){this._particleConstructor=t,this.cleanup();for(var e=this._poolFirst;e;e=e.next)e.destroy();this._poolFirst=null,this._origConfig&&this._origArt&&this.init(this._origArt,this._origConfig)}},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"parent",{get:function(){return this._parent},set:function(t){this.cleanup(),this._parent=t},enumerable:!0,configurable:!0}),t.prototype.init=function(t,e){if(t&&e){this.cleanup(),this._origConfig=e,this._origArt=t,t=Array.isArray(t)?t.slice():[t];var i=this._particleConstructor;this.particleImages=i.parseArt?i.parseArt(t):t,e.alpha?this.startAlpha=r.default.createList(e.alpha):this.startAlpha=new r.default(1,0),e.speed?(this.startSpeed=r.default.createList(e.speed),this.minimumSpeedMultiplier=e.speed.minimumSpeedMultiplier||1):(this.minimumSpeedMultiplier=1,this.startSpeed=new r.default(0,0));var a=e.acceleration;a&&(a.x||a.y)?(this.startSpeed.next=null,this.acceleration=new PIXI.Point(a.x,a.y),this.maxSpeed=e.maxSpeed||NaN):this.acceleration=new PIXI.Point,e.scale?(this.startScale=r.default.createList(e.scale),this.minimumScaleMultiplier=e.scale.minimumScaleMultiplier||1):(this.startScale=new r.default(1,0),this.minimumScaleMultiplier=1),e.color?this.startColor=r.default.createList(e.color):this.startColor=new r.default({r:255,g:255,b:255},0),e.startRotation?(this.minStartRotation=e.startRotation.min,this.maxStartRotation=e.startRotation.max):this.minStartRotation=this.maxStartRotation=0,e.noRotation&&(this.minStartRotation||this.maxStartRotation)?this.noRotation=!!e.noRotation:this.noRotation=!1,e.rotationSpeed?(this.minRotationSpeed=e.rotationSpeed.min,this.maxRotationSpeed=e.rotationSpeed.max):this.minRotationSpeed=this.maxRotationSpeed=0,this.minLifetime=e.lifetime.min,this.maxLifetime=e.lifetime.max,this.particleBlendMode=s.default.getBlendMode(e.blendMode),e.ease?this.customEase="function"==typeof e.ease?e.ease:s.default.generateEase(e.ease):this.customEase=null,i.parseData?this.extraData=i.parseData(e.extraData):this.extraData=e.extraData||null,this.spawnRect=this.spawnCircle=null,this.particlesPerWave=1,e.particlesPerWave&&e.particlesPerWave>1&&(this.particlesPerWave=e.particlesPerWave),this.particleSpacing=0,this.angleStart=0;var n;switch(e.spawnType){case"rect":this.spawnType="rect",this._spawnFunc=this._spawnRect;var o=e.spawnRect;this.spawnRect=new PIXI.Rectangle(o.x,o.y,o.w,o.h);break;case"circle":this.spawnType="circle",this._spawnFunc=this._spawnCircle,n=e.spawnCircle,this.spawnCircle=new PIXI.Circle(n.x,n.y,n.r);break;case"ring":this.spawnType="ring",this._spawnFunc=this._spawnRing,n=e.spawnCircle,this.spawnCircle=new PIXI.Circle(n.x,n.y,n.r),this.spawnCircle.minRadius=n.minR;break;case"burst":this.spawnType="burst",this._spawnFunc=this._spawnBurst,this.particleSpacing=e.particleSpacing,this.angleStart=e.angleStart?e.angleStart:0;break;case"point":default:this.spawnType="point",this._spawnFunc=this._spawnPoint}this.frequency=e.frequency,this.spawnChance="number"==typeof e.spawnChance&&e.spawnChance>0?e.spawnChance:1,this.emitterLifetime=e.emitterLifetime||-1,this.maxParticles=e.maxParticles>0?e.maxParticles:1e3,this.addAtBack=!!e.addAtBack,this.rotation=0,this.ownerPos=new PIXI.Point,this.spawnPos=new PIXI.Point(e.pos.x,e.pos.y),this._prevEmitterPos=this.spawnPos.clone(),this._prevPosIsValid=!1,this._spawnTimer=0,this.emit=void 0===e.emit||!!e.emit,this.autoUpdate=void 0!==e.autoUpdate&&!!e.autoUpdate}},t.prototype.recycle=function(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t==this._activeParticlesLast&&(this._activeParticlesLast=t.prev),t==this._activeParticlesFirst&&(this._activeParticlesFirst=t.next),t.prev=null,t.next=this._poolFirst,this._poolFirst=t,t.parent&&t.parent.removeChild(t),--this.particleCount},t.prototype.rotate=function(t){if(this.rotation!=t){var e=t-this.rotation;this.rotation=t,s.default.rotatePoint(e,this.spawnPos),this._posChanged=!0}},t.prototype.updateSpawnPos=function(t,e){this._posChanged=!0,this.spawnPos.x=t,this.spawnPos.y=e},t.prototype.updateOwnerPos=function(t,e){this._posChanged=!0,this.ownerPos.x=t,this.ownerPos.y=e},t.prototype.resetPositionTracking=function(){this._prevPosIsValid=!1},Object.defineProperty(t.prototype,"emit",{get:function(){return this._emit},set:function(t){this._emit=!!t,this._emitterLife=this.emitterLifetime},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"autoUpdate",{get:function(){return this._autoUpdate},set:function(t){this._autoUpdate&&!t?n.remove(this.update,this):!this._autoUpdate&&t&&n.add(this.update,this),this._autoUpdate=!!t},enumerable:!0,configurable:!0}),t.prototype.playOnceAndDestroy=function(t){this.autoUpdate=!0,this.emit=!0,this._destroyWhenComplete=!0,this._completeCallback=t},t.prototype.playOnce=function(t){this.emit=!0,this._completeCallback=t},t.prototype.update=function(t){if(this._autoUpdate&&(t=t/PIXI.settings.TARGET_FPMS/1e3),this._parent){var e,i,s;for(i=this._activeParticlesFirst;i;i=s)s=i.next,i.update(t);var a,r;this._prevPosIsValid&&(a=this._prevEmitterPos.x,r=this._prevEmitterPos.y);var n=this.ownerPos.x+this.spawnPos.x,o=this.ownerPos.y+this.spawnPos.y;if(this._emit)for(this._spawnTimer-=t;this._spawnTimer<=0;){if(this._emitterLife>0&&(this._emitterLife-=this._frequency,this._emitterLife<=0)){this._spawnTimer=0,this._emitterLife=0,this.emit=!1;break}if(this.particleCount>=this.maxParticles)this._spawnTimer+=this._frequency;else{var h=void 0;if(h=this.minLifetime==this.maxLifetime?this.minLifetime:Math.random()*(this.maxLifetime-this.minLifetime)+this.minLifetime,-this._spawnTimer=this.spawnChance)){var d=void 0;if(this._poolFirst?(d=this._poolFirst,this._poolFirst=this._poolFirst.next,d.next=null):d=new this.particleConstructor(this),this.particleImages.length>1?d.applyArt(this.particleImages[Math.floor(Math.random()*this.particleImages.length)]):d.applyArt(this.particleImages[0]),d.alphaList.reset(this.startAlpha),1!=this.minimumSpeedMultiplier&&(d.speedMultiplier=Math.random()*(1-this.minimumSpeedMultiplier)+this.minimumSpeedMultiplier),d.speedList.reset(this.startSpeed),d.acceleration.x=this.acceleration.x,d.acceleration.y=this.acceleration.y,d.maxSpeed=this.maxSpeed,1!=this.minimumScaleMultiplier&&(d.scaleMultiplier=Math.random()*(1-this.minimumScaleMultiplier)+this.minimumScaleMultiplier),d.scaleList.reset(this.startScale),d.colorList.reset(this.startColor),this.minRotationSpeed==this.maxRotationSpeed?d.rotationSpeed=this.minRotationSpeed:d.rotationSpeed=Math.random()*(this.maxRotationSpeed-this.minRotationSpeed)+this.minRotationSpeed,d.noRotation=this.noRotation,d.maxLife=h,d.blendMode=this.particleBlendMode,d.ease=this.customEase,d.extraData=this.extraData,this._spawnFunc(d,l,p,e),d.init(),d.update(-this._spawnTimer),d.parent){var f=this._parent.children;if(f[0]==d)f.shift();else if(f[f.length-1]==d)f.pop();else{var m=f.indexOf(d);f.splice(m,1)}this.addAtBack?f.unshift(d):f.push(d)}else this.addAtBack?this._parent.addChildAt(d,0):this._parent.addChild(d);this._activeParticlesLast?(this._activeParticlesLast.next=d,d.prev=this._activeParticlesLast,this._activeParticlesLast=d):this._activeParticlesLast=this._activeParticlesFirst=d,++this.particleCount}}this._spawnTimer+=this._frequency}}this._posChanged&&(this._prevEmitterPos.x=n,this._prevEmitterPos.y=o,this._prevPosIsValid=!0,this._posChanged=!1),this._emit||this._activeParticlesFirst||(this._completeCallback&&this._completeCallback(),this._destroyWhenComplete&&this.destroy())}},t.prototype._spawnPoint=function(t,e,i){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,t.position.x=e,t.position.y=i},t.prototype._spawnRect=function(t,e,i){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,o.x=Math.random()*this.spawnRect.width+this.spawnRect.x,o.y=Math.random()*this.spawnRect.height+this.spawnRect.y,0!==this.rotation&&s.default.rotatePoint(this.rotation,o),t.position.x=e+o.x,t.position.y=i+o.y},t.prototype._spawnCircle=function(t,e,i){this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,o.x=Math.random()*this.spawnCircle.radius,o.y=0,s.default.rotatePoint(360*Math.random(),o),o.x+=this.spawnCircle.x,o.y+=this.spawnCircle.y,0!==this.rotation&&s.default.rotatePoint(this.rotation,o),t.position.x=e+o.x,t.position.y=i+o.y},t.prototype._spawnRing=function(t,e,i){var a=this.spawnCircle;this.minStartRotation==this.maxStartRotation?t.rotation=this.minStartRotation+this.rotation:t.rotation=Math.random()*(this.maxStartRotation-this.minStartRotation)+this.minStartRotation+this.rotation,a.minRadius==a.radius?o.x=Math.random()*(a.radius-a.minRadius)+a.minRadius:o.x=a.radius,o.y=0;var r=360*Math.random();t.rotation+=r,s.default.rotatePoint(r,o),o.x+=this.spawnCircle.x,o.y+=this.spawnCircle.y,0!==this.rotation&&s.default.rotatePoint(this.rotation,o),t.position.x=e+o.x,t.position.y=i+o.y},t.prototype._spawnBurst=function(t,e,i,s){0===this.particleSpacing?t.rotation=360*Math.random():t.rotation=this.angleStart+this.particleSpacing*s+this.rotation,t.position.x=e,t.position.y=i},t.prototype.cleanup=function(){var t,e;for(t=this._activeParticlesFirst;t;t=e)e=t.next,this.recycle(t),t.parent&&t.parent.removeChild(t);this._activeParticlesFirst=this._activeParticlesLast=null,this.particleCount=0},t.prototype.destroy=function(){this.autoUpdate=!1,this.cleanup();for(var t,e=this._poolFirst;e;e=t)t=e.next,e.destroy();this._poolFirst=this._parent=this.particleImages=this.spawnPos=this.ownerPos=this.startColor=this.startScale=this.startAlpha=this.startSpeed=this.customEase=this._completeCallback=null},t}();i.default=h},{"./Particle":3,"./ParticleUtils":4,"./PropertyNode":7}],3:[function(t,e,i){"use strict";var s=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i])};return function(e,i){function s(){this.constructor=e}t(e,i),e.prototype=null===i?Object.create(i):(s.prototype=i.prototype,new s)}}();Object.defineProperty(i,"__esModule",{value:!0});var a=t("./ParticleUtils"),r=t("./PropertyList"),n=PIXI.Sprite,o=function(t){function e(i){var s=t.call(this)||this;return s.emitter=i,s.anchor.x=s.anchor.y=.5,s.velocity=new PIXI.Point,s.maxLife=0,s.age=0,s.ease=null,s.extraData=null,s.alphaList=new r.default,s.speedList=new r.default,s.speedMultiplier=1,s.acceleration=new PIXI.Point,s.maxSpeed=NaN,s.scaleList=new r.default,s.scaleMultiplier=1,s.colorList=new r.default(!0),s._doAlpha=!1,s._doScale=!1,s._doSpeed=!1,s._doAcceleration=!1,s._doColor=!1,s._doNormalMovement=!1,s._oneOverLife=0,s.next=null,s.prev=null,s.init=s.init,s.Particle_init=e.prototype.init,s.update=s.update,s.Particle_update=e.prototype.update,s.Sprite_destroy=t.prototype.destroy,s.Particle_destroy=e.prototype.destroy,s.applyArt=s.applyArt,s.kill=s.kill,s}return s(e,t),e.prototype.init=function(){this.age=0,this.velocity.x=this.speedList.current.value*this.speedMultiplier,this.velocity.y=0,a.default.rotatePoint(this.rotation,this.velocity),this.noRotation?this.rotation=0:this.rotation*=a.default.DEG_TO_RADS,this.rotationSpeed*=a.default.DEG_TO_RADS,this.alpha=this.alphaList.current.value,this.scale.x=this.scale.y=this.scaleList.current.value,this._doAlpha=!!this.alphaList.current.next,this._doSpeed=!!this.speedList.current.next,this._doScale=!!this.scaleList.current.next,this._doColor=!!this.colorList.current.next,this._doAcceleration=0!==this.acceleration.x||0!==this.acceleration.y,this._doNormalMovement=this._doSpeed||0!==this.speedList.current.value||this._doAcceleration,this._oneOverLife=1/this.maxLife;var t=this.colorList.current.value;this.tint=a.default.combineRGBComponents(t.r,t.g,t.b),this.visible=!0},e.prototype.applyArt=function(t){this.texture=t||PIXI.Texture.EMPTY},e.prototype.update=function(t){if(this.age+=t,this.age>=this.maxLife)return this.kill(),-1;var e=this.age*this._oneOverLife;if(this.ease&&(e=4==this.ease.length?this.ease(e,0,1,1):this.ease(e)),this._doAlpha&&(this.alpha=this.alphaList.interpolate(e)),this._doScale){var i=this.scaleList.interpolate(e)*this.scaleMultiplier;this.scale.x=this.scale.y=i}if(this._doNormalMovement){if(this._doSpeed){var s=this.speedList.interpolate(e)*this.speedMultiplier;a.default.normalize(this.velocity),a.default.scaleBy(this.velocity,s)}else if(this._doAcceleration&&(this.velocity.x+=this.acceleration.x*t,this.velocity.y+=this.acceleration.y*t,this.maxSpeed)){var r=a.default.length(this.velocity);r>this.maxSpeed&&a.default.scaleBy(this.velocity,this.maxSpeed/r)}this.position.x+=this.velocity.x*t,this.position.y+=this.velocity.y*t}return this._doColor&&(this.tint=this.colorList.interpolate(e)),0!==this.rotationSpeed?this.rotation+=this.rotationSpeed*t:this.acceleration&&!this.noRotation&&(this.rotation=Math.atan2(this.velocity.y,this.velocity.x)),e},e.prototype.kill=function(){this.emitter.recycle(this)},e.prototype.destroy=function(){this.parent&&this.parent.removeChild(this),this.Sprite_destroy(),this.emitter=this.velocity=this.colorList=this.scaleList=this.alphaList=this.speedList=this.ease=this.next=this.prev=null},e.parseArt=function(t){var e;for(e=t.length;e>=0;--e)"string"==typeof t[e]&&(t[e]=PIXI.Texture.fromImage(t[e]));if(a.default.verbose)for(e=t.length-1;e>0;--e)if(t[e].baseTexture!=t[e-1].baseTexture){window.console&&console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL");break}return t},e.parseData=function(t){return t},e}(n);i.default=o},{"./ParticleUtils":4,"./PropertyList":6}],4:[function(t,e,i){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var s=PIXI.BLEND_MODES,a=t("./PropertyNode"),r={verbose:!1,DEG_TO_RADS:Math.PI/180,rotatePoint:function(t,e){if(t){t*=r.DEG_TO_RADS;var i=Math.sin(t),s=Math.cos(t),a=e.x*s-e.y*i,n=e.x*i+e.y*s;e.x=a,e.y=n}},combineRGBComponents:function(t,e,i){return t<<16|e<<8|i},normalize:function(t){var e=1/r.length(t);t.x*=e,t.y*=e},scaleBy:function(t,e){t.x*=e,t.y*=e},length:function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},hexToRGB:function(t,e){e||(e={}),"#"==t.charAt(0)?t=t.substr(1):0===t.indexOf("0x")&&(t=t.substr(2));var i;return 8==t.length&&(i=t.substr(0,2),t=t.substr(2)),e.r=parseInt(t.substr(0,2),16),e.g=parseInt(t.substr(2,2),16),e.b=parseInt(t.substr(4,2),16),i&&(e.a=parseInt(i,16)),e},generateEase:function(t){var e=t.length,i=1/e;return function(s){var a,r,n=e*s|0;return a=(s-n*i)*e,r=t[n]||t[e-1],r.s+a*(2*(1-a)*(r.cp-r.s)+a*(r.e-r.s))}},getBlendMode:function(t){if(!t)return s.NORMAL;for(t=t.toUpperCase();t.indexOf(" ")>=0;)t=t.replace(" ","_");return s[t]||s.NORMAL},createSteppedGradient:function(t,e){void 0===e&&(e=10),("number"!=typeof e||e<=0)&&(e=10);var i=new a.default(t[0].value,t[0].time);i.isStepped=!0;for(var s=i,n=t[0],o=1,h=t[o],l=1;lh.time;)n=h,h=t[++o];p=(p-n.time)/(h.time-n.time);var c=r.hexToRGB(n.value),u=r.hexToRGB(h.value),d={};d.r=(u.r-c.r)*p+c.r,d.g=(u.g-c.g)*p+c.g,d.b=(u.b-c.b)*p+c.b,s.next=new a.default(d,l/e),s=s.next}return i}};i.default=r},{"./PropertyNode":7}],5:[function(t,e,i){"use strict";var s=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i])};return function(e,i){function s(){this.constructor=e}t(e,i),e.prototype=null===i?Object.create(i):(s.prototype=i.prototype,new s)}}();Object.defineProperty(i,"__esModule",{value:!0});var a=t("./ParticleUtils"),r=t("./Particle"),n=new PIXI.Point,o=["pow","sqrt","abs","floor","round","ceil","E","PI","sin","cos","tan","asin","acos","atan","atan2","log"],h=new RegExp(["[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]"].concat(o).join("|"),"g"),l=function(t){for(var e=t.match(h),i=e.length-1;i>=0;--i)o.indexOf(e[i])>=0&&(e[i]="Math."+e[i]);return t=e.join(""),new Function("x","return "+t+";")},p=function(t){function e(e){var i=t.call(this,e)||this;return i.path=null,i.initialRotation=0,i.initialPosition=new PIXI.Point,i.movement=0,i}return s(e,t),e.prototype.init=function(){this.initialRotation=this.rotation,this.Particle_init(),this.path=this.extraData.path,this._doNormalMovement=!this.path,this.movement=0,this.initialPosition.x=this.position.x,this.initialPosition.y=this.position.y},e.prototype.update=function(t){var e=this.Particle_update(t);if(e>=0&&this.path){var i=this.speedList.interpolate(e)*this.speedMultiplier;this.movement+=i*t,n.x=this.movement,n.y=this.path(this.movement),a.default.rotatePoint(this.initialRotation,n),this.position.x=this.initialPosition.x+n.x,this.position.y=this.initialPosition.y+n.y}return e},e.prototype.destroy=function(){this.Particle_destroy(),this.path=this.initialPosition=null},e.parseArt=function(t){return r.default.parseArt(t)},e.parseData=function(t){var e={};if(t&&t.path)try{e.path=l(t.path)}catch(t){a.default.verbose&&console.error("PathParticle: error in parsing path expression"),e.path=null}else a.default.verbose&&console.error("PathParticle requires a path string in extraData!"),e.path=null;return e},e}(r.default);i.default=p},{"./Particle":3,"./ParticleUtils":4}],6:[function(t,e,i){"use strict";function s(t){return this.ease&&(t=this.ease(t)),(this.next.value-this.current.value)*t+this.current.value}function a(t){this.ease&&(t=this.ease(t));var e=this.current.value,i=this.next.value,s=(i.r-e.r)*t+e.r,a=(i.g-e.g)*t+e.g,r=(i.b-e.b)*t+e.b;return l.default.combineRGBComponents(s,a,r)}function r(t){for(this.ease&&(t=this.ease(t));t>this.next.time;)this.current=this.next,this.next=this.next.next;return t=(t-this.current.time)/(this.next.time-this.current.time),(this.next.value-this.current.value)*t+this.current.value}function n(t){for(this.ease&&(t=this.ease(t));t>this.next.time;)this.current=this.next,this.next=this.next.next;t=(t-this.current.time)/(this.next.time-this.current.time);var e=this.current.value,i=this.next.value,s=(i.r-e.r)*t+e.r,a=(i.g-e.g)*t+e.g,r=(i.b-e.b)*t+e.b;return l.default.combineRGBComponents(s,a,r)}function o(t){for(this.ease&&(t=this.ease(t));this.next&&t>this.next.time;)this.current=this.next,this.next=this.next.next;return this.current.value}function h(t){for(this.ease&&(t=this.ease(t));this.next&&t>this.next.time;)this.current=this.next,this.next=this.next.next;var e=this.current.value;return l.default.combineRGBComponents(e.r,e.g,e.b)}Object.defineProperty(i,"__esModule",{value:!0});var l=t("./ParticleUtils"),p=function(){function t(t){void 0===t&&(t=!1),this.current=null,this.next=null,this.isColor=!!t,this.interpolate=null,this.ease=null}return t.prototype.reset=function(t){this.current=t,this.next=t.next,this.next&&this.next.time>=1?this.interpolate=this.isColor?a:s:t.isStepped?this.interpolate=this.isColor?h:o:this.interpolate=this.isColor?n:r,this.ease=this.current.ease},t}();i.default=p},{"./ParticleUtils":4}],7:[function(t,e,i){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var s=t("./ParticleUtils"),a=function(){function t(t,e,i){this.value="string"==typeof t?s.default.hexToRGB(t):t,this.time=e,this.next=null,this.isStepped=!1,this.ease=i?"function"==typeof i?i:s.default.generateEase(i):null}return t.createList=function(e){if(Array.isArray(e.list)){var i=e.list,s=void 0,a=void 0;if(a=s=new t(i[0].value,i[0].time,e.ease),i.length>2||2===i.length&&i[1].value!==i[0].value)for(var r=1;r= 0)\n\t{\n\t\tthis.elapsed += delta;\n\t\tif(this.elapsed > this.duration)\n\t\t{\n\t\t\t//loop elapsed back around\n\t\t\tif(this.loop)\n\t\t\t\tthis.elapsed = this.elapsed % this.duration;\n\t\t\t//subtract a small amount to prevent attempting to go past the end of the animation\n\t\t\telse\n\t\t\t\tthis.elapsed = this.duration - 0.000001;\n\t\t}\n\t\tvar frame = (this.elapsed * this.framerate + 0.0000001) | 0;\n\t\tthis.texture = this.textures[frame] || ParticleUtils.EMPTY_TEXTURE;\n\t}\n};\n\np.Particle_destroy = Particle.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.AnimatedParticle#destroy\n */\np.destroy = function()\n{\n\tthis.Particle_destroy();\n\tthis.textures = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @method PIXI.particles.AnimatedParticle.parseArt\n * @static\n * @param {Array} art The array of art data, properly formatted for AnimatedParticle.\n * @return {Array} The art, after any needed modifications.\n */\nAnimatedParticle.parseArt = function(art)\n{\n\tvar i, data, output = [], j, textures, tex, outTextures;\n\tfor(i = 0; i < art.length; ++i)\n\t{\n\t\tdata = art[i];\n\t\tart[i] = output = {};\n\t\toutput.textures = outTextures = [];\n\t\ttextures = data.textures;\n\t\tfor(j = 0; j < textures.length; ++j)\n\t\t{\n\t\t\ttex = textures[j];\n\t\t\tif(typeof tex == \"string\")\n\t\t\t\toutTextures.push(Texture.fromImage(tex));\n\t\t\telse if(tex instanceof Texture)\n\t\t\t\toutTextures.push(tex);\n\t\t\t//assume an object with extra data determining duplicate frame data\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar dupe = tex.count || 1;\n\t\t\t\tif(typeof tex.texture == \"string\")\n\t\t\t\t\ttex = Texture.fromImage(tex.texture);\n\t\t\t\telse// if(tex.texture instanceof Texture)\n\t\t\t\t\ttex = tex.texture;\n\t\t\t\tfor(; dupe > 0; --dupe)\n\t\t\t\t{\n\t\t\t\t\toutTextures.push(tex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//use these values to signify that the animation should match the particle life time.\n\t\tif(data.framerate == \"matchLife\")\n\t\t{\n\t\t\t//-1 means that it should be calculated\n\t\t\toutput.framerate = -1;\n\t\t\toutput.duration = 0;\n\t\t\toutput.loop = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//determine if the animation should loop\n\t\t\toutput.loop = !!data.loop;\n\t\t\t//get the framerate, default to 60\n\t\t\toutput.framerate = data.framerate > 0 ? data.framerate : 60;\n\t\t\t//determine the duration\n\t\t\toutput.duration = outTextures.length / output.framerate;\n\t\t}\n\t}\n\n\treturn art;\n};\n\nmodule.exports = AnimatedParticle;","\"use strict\";\n\nvar ParticleUtils = require(\"./ParticleUtils\"),\n\tParticle = require(\"./Particle\"),\n\tParticleContainer = PIXI.particles.ParticleContainer || PIXI.ParticleContainer,\n\tticker = PIXI.ticker.shared;\n\n/**\n * A particle emitter.\n * @memberof PIXI.particles\n * @class Emitter\n * @constructor\n * @param {PIXI.Container} particleParent The container to add the\n * particles to.\n * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use\n * for the particles. Strings will be turned\n * into textures via Texture.fromImage().\n * @param {Object} [config] A configuration object containing settings for the emitter.\n * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter\n * will start disabled.\n * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter\n * will automatically call update via the PIXI shared ticker.\n */\nvar Emitter = function(particleParent, particleImages, config)\n{\n\t/**\n\t * The constructor used to create new particles. The default is\n\t * the built in particle class.\n\t * @property {Function} _particleConstructor\n\t * @private\n\t */\n\tthis._particleConstructor = Particle;\n\t//properties for individual particles\n\t/**\n\t * An array of PIXI Texture objects.\n\t * @property {Array} particleImages\n\t */\n\tthis.particleImages = null;\n\t/**\n\t * The starting alpha of all particles.\n\t * @property {Number} startAlpha\n\t * @default 1\n\t */\n\tthis.startAlpha = 1;\n\t/**\n\t * The ending alpha of all particles.\n\t * @property {Number} endAlpha\n\t * @default 1\n\t */\n\tthis.endAlpha = 1;\n\t/**\n\t * The starting speed of all particles.\n\t * @property {Number} startSpeed\n\t * @default 0\n\t */\n\tthis.startSpeed = 0;\n\t/**\n\t * The ending speed of all particles.\n\t * @property {Number} endSpeed\n\t * @default 0\n\t */\n\tthis.endSpeed = 0;\n\t/**\n\t * A minimum multiplier for the speed of a particle at both start and\n\t * end. A value between minimumSpeedMultiplier and 1 is randomly generated\n\t * and multiplied with startSpeed and endSpeed to provide the actual\n\t * startSpeed and endSpeed for each particle.\n\t * @property {Number} minimumSpeedMultiplier\n\t * @default 1\n\t */\n\tthis.minimumSpeedMultiplier = 1;\n\t/**\n\t * Acceleration to apply to particles. Using this disables\n\t * any interpolation of particle speed. If the particles do\n\t * not have a rotation speed, then they will be rotated to\n\t * match the direction of travel.\n\t * @property {PIXI.Point} acceleration\n\t * @default null\n\t */\n\tthis.acceleration = null;\n\t/**\n\t * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n\t * will disable the maximum speed.\n\t * @property {Number} maxSpeed\n\t * @default NaN\n\t */\n\tthis.maxSpeed = NaN;\n\t/**\n\t * The starting scale of all particles.\n\t * @property {Number} startScale\n\t * @default 1\n\t */\n\tthis.startScale = 1;\n\t/**\n\t * The ending scale of all particles.\n\t * @property {Number} endScale\n\t * @default 1\n\t */\n\tthis.endScale = 1;\n\t/**\n\t * A minimum multiplier for the scale of a particle at both start and\n\t * end. A value between minimumScaleMultiplier and 1 is randomly generated\n\t * and multiplied with startScale and endScale to provide the actual\n\t * startScale and endScale for each particle.\n\t * @property {Number} minimumScaleMultiplier\n\t * @default 1\n\t */\n\tthis.minimumScaleMultiplier = 1;\n\t/**\n\t * The starting color of all particles, as red, green, and blue uints from 0-255.\n\t * @property {Array} startColor\n\t */\n\tthis.startColor = null;\n\t/**\n\t * The ending color of all particles, as red, green, and blue uints from 0-255.\n\t * @property {Array} endColor\n\t */\n\tthis.endColor = null;\n\t/**\n\t * The minimum lifetime for a particle, in seconds.\n\t * @property {Number} minLifetime\n\t */\n\tthis.minLifetime = 0;\n\t/**\n\t * The maximum lifetime for a particle, in seconds.\n\t * @property {Number} maxLifetime\n\t */\n\tthis.maxLifetime = 0;\n\t/**\n\t * The minimum start rotation for a particle, in degrees. This value\n\t * is ignored if the spawn type is \"burst\" or \"arc\".\n\t * @property {Number} minStartRotation\n\t */\n\tthis.minStartRotation = 0;\n\t/**\n\t * The maximum start rotation for a particle, in degrees. This value\n\t * is ignored if the spawn type is \"burst\" or \"arc\".\n\t * @property {Number} maxStartRotation\n\t */\n\tthis.maxStartRotation = 0;\n\t/**\n\t * If no particle rotation should occur. Starting rotation will still\n\t * affect the direction in which particles move. If the rotation speed\n\t * is set, then this will be ignored.\n\t * @property {Boolean} maxStartRotation\n\t */\n\tthis.noRotation = false;\n\t/**\n\t * The minimum rotation speed for a particle, in degrees per second.\n\t * This only visually spins the particle, it does not change direction\n\t * of movement.\n\t * @property {Number} minRotationSpeed\n\t */\n\tthis.minRotationSpeed = 0;\n\t/**\n\t * The maximum rotation speed for a particle, in degrees per second.\n\t * This only visually spins the particle, it does not change direction\n\t * of movement.\n\t * @property {Number} maxRotationSpeed\n\t */\n\tthis.maxRotationSpeed = 0;\n\t/**\n\t * The blend mode for all particles, as named by PIXI.blendModes.\n\t * @property {int} particleBlendMode\n\t */\n\tthis.particleBlendMode = 0;\n\t/**\n\t * An easing function for nonlinear interpolation of values. Accepts a single\n\t * parameter of time as a value from 0-1, inclusive. Expected outputs are values\n\t * from 0-1, inclusive.\n\t * @property {Function} customEase\n\t */\n\tthis.customEase = null;\n\t/**\n\t *\tExtra data for use in custom particles. The emitter doesn't look inside, but\n\t *\tpasses it on to the particle to use in init().\n\t *\t@property {Object} extraData\n\t */\n\tthis.extraData = null;\n\t//properties for spawning particles\n\t/**\n\t * Time between particle spawns in seconds.\n\t * @property {Number} _frequency\n\t * @private\n\t */\n\tthis._frequency = 1;\n\t/**\n\t * Maximum number of particles to keep alive at a time. If this limit\n\t * is reached, no more particles will spawn until some have died.\n\t * @property {int} maxParticles\n\t * @default 1000\n\t */\n\tthis.maxParticles = 1000;\n\t/**\n\t * The amount of time in seconds to emit for before setting emit to false.\n\t * A value of -1 is an unlimited amount of time.\n\t * @property {Number} emitterLifetime\n\t * @default -1\n\t */\n\tthis.emitterLifetime = -1;\n\t/**\n\t * Position at which to spawn particles, relative to the emitter's owner's origin.\n\t * For example, the flames of a rocket travelling right might have a spawnPos\n\t * of {x:-50, y:0}.\n\t * to spawn at the rear of the rocket.\n\t * To change this, use updateSpawnPos().\n\t * @property {PIXI.Point} spawnPos\n\t * @readOnly\n\t */\n\tthis.spawnPos = null;\n\t/**\n\t * How the particles will be spawned. Valid types are \"point\", \"rectangle\",\n\t * \"circle\", \"burst\", \"ring\".\n\t * @property {String} spawnType\n\t * @readOnly\n\t */\n\tthis.spawnType = null;\n\t/**\n\t * A reference to the emitter function specific to the spawn type.\n\t * @property {Function} _spawnFunc\n\t * @private\n\t */\n\tthis._spawnFunc = null;\n\t/**\n\t * A rectangle relative to spawnPos to spawn particles inside if the spawn type is \"rect\".\n\t * @property {PIXI.Rectangle} spawnRect\n\t */\n\tthis.spawnRect = null;\n\t/**\n\t * A circle relative to spawnPos to spawn particles inside if the spawn type is \"circle\".\n\t * @property {PIXI.Circle} spawnCircle\n\t */\n\tthis.spawnCircle = null;\n\t/**\n\t * Number of particles to spawn each wave in a burst.\n\t * @property {int} particlesPerWave\n\t * @default 1\n\t */\n\tthis.particlesPerWave = 1;\n\t/**\n\t * Spacing between particles in a burst. 0 gives a random angle for each particle.\n\t * @property {Number} particleSpacing\n\t * @default 0\n\t */\n\tthis.particleSpacing = 0;\n\t/**\n\t * Angle at which to start spawning particles in a burst.\n\t * @property {Number} angleStart\n\t * @default 0\n\t */\n\tthis.angleStart = 0;\n\t/**\n\t * Rotation of the emitter or emitter's owner in degrees. This is added to\n\t * the calculated spawn angle.\n\t * To change this, use rotate().\n\t * @property {Number} rotation\n\t * @default 0\n\t * @readOnly\n\t */\n\tthis.rotation = 0;\n\t/**\n\t * The world position of the emitter's owner, to add spawnPos to when\n\t * spawning particles. To change this, use updateOwnerPos().\n\t * @property {PIXI.Point} ownerPos\n\t * @default {x:0, y:0}\n\t * @readOnly\n\t */\n\tthis.ownerPos = null;\n\t/**\n\t * The origin + spawnPos in the previous update, so that the spawn position\n\t * can be interpolated to space out particles better.\n\t * @property {PIXI.Point} _prevEmitterPos\n\t * @private\n\t */\n\tthis._prevEmitterPos = null;\n\t/**\n\t * If _prevEmitterPos is valid, to prevent interpolation on the first update\n\t * @property {Boolean} _prevPosIsValid\n\t * @private\n\t * @default false\n\t */\n\tthis._prevPosIsValid = false;\n\t/**\n\t * If either ownerPos or spawnPos has changed since the previous update.\n\t * @property {Boolean} _posChanged\n\t * @private\n\t */\n\tthis._posChanged = false;\n\t/**\n\t * If the parent is a ParticleContainer from Pixi V3\n\t * @property {Boolean} _parentIsPC\n\t * @private\n\t */\n\tthis._parentIsPC = false;\n\t/**\n\t * The container to add particles to.\n\t * @property {PIXI.Container} _parent\n\t * @private\n\t */\n\tthis._parent = null;\n\t/**\n\t * If particles should be added at the back of the display list instead of the front.\n\t * @property {Boolean} addAtBack\n\t */\n\tthis.addAtBack = false;\n\t/**\n\t * The current number of active particles.\n\t * @property {Number} particleCount\n\t * @readOnly\n\t */\n\tthis.particleCount = 0;\n\t/**\n\t * If particles should be emitted during update() calls. Setting this to false\n\t * stops new particles from being created, but allows existing ones to die out.\n\t * @property {Boolean} _emit\n\t * @private\n\t */\n\tthis._emit = false;\n\t/**\n\t * The timer for when to spawn particles in seconds, where numbers less\n\t * than 0 mean that particles should be spawned.\n\t * @property {Number} _spawnTimer\n\t * @private\n\t */\n\tthis._spawnTimer = 0;\n\t/**\n\t * The life of the emitter in seconds.\n\t * @property {Number} _emitterLife\n\t * @private\n\t */\n\tthis._emitterLife = -1;\n\t/**\n\t * The particles that are active and on the display list. This is the first particle in a\n\t * linked list.\n\t * @property {Particle} _activeParticlesFirst\n\t * @private\n\t */\n\tthis._activeParticlesFirst = null;\n\t/**\n\t * The particles that are active and on the display list. This is the last particle in a\n\t * linked list.\n\t * @property {Particle} _activeParticlesLast\n\t * @private\n\t */\n\tthis._activeParticlesLast = null;\n\t/**\n\t * The particles that are not currently being used. This is the first particle in a\n\t * linked list.\n\t * @property {Particle} _poolFirst\n\t * @private\n\t */\n\tthis._poolFirst = null;\n\t/**\n\t * The original config object that this emitter was initialized with.\n\t * @property {Object} _origConfig\n\t * @private\n\t */\n\tthis._origConfig = null;\n\t/**\n\t * The original particle image data that this emitter was initialized with.\n\t * @property {PIXI.Texture|Array|String} _origArt\n\t * @private\n\t */\n\tthis._origArt = null;\n\t/**\n\t * If the update function is called automatically from the shared ticker.\n\t * Setting this to false requires calling the update function manually.\n\t * @property {Boolean} _autoUpdate\n\t * @private\n\t */\n\tthis._autoUpdate = false;\n\t/**\n\t * If the emitter should destroy itself when all particles have died out. This is set by\n\t * playOnceAndDestroy();\n\t * @property {Boolean} _destroyWhenComplete\n\t * @private\n\t */\n\tthis._destroyWhenComplete = false;\n\t/**\n\t * A callback for when all particles have died out. This is set by\n\t * playOnceAndDestroy() or playOnce();\n\t * @property {Function} _completeCallback\n\t * @private\n\t */\n\tthis._completeCallback = null;\n\n\t//set the initial parent\n\tthis.parent = particleParent;\n\n\tif(particleImages && config)\n\t\tthis.init(particleImages, config);\n\n\t//save often used functions on the instance instead of the prototype for better speed\n\tthis.recycle = this.recycle;\n\tthis.update = this.update;\n\tthis.rotate = this.rotate;\n\tthis.updateSpawnPos = this.updateSpawnPos;\n\tthis.updateOwnerPos = this.updateOwnerPos;\n};\n\n// Reference to the prototype\nvar p = Emitter.prototype = {};\n\nvar helperPoint = new PIXI.Point();\n\n/**\n * Time between particle spawns in seconds. If this value is not a number greater than 0,\n * it will be set to 1 (particle per second) to prevent infinite loops.\n * @member {Number} PIXI.particles.Emitter#frequency\n */\nObject.defineProperty(p, \"frequency\",\n{\n\tget: function() { return this._frequency; },\n\tset: function(value)\n\t{\n\t\t//do some error checking to prevent infinite loops\n\t\tif(typeof value == \"number\" && value > 0)\n\t\t\tthis._frequency = value;\n\t\telse\n\t\t\tthis._frequency = 1;\n\t}\n});\n\n/**\n * The constructor used to create new particles. The default is\n * the built in Particle class. Setting this will dump any active or\n * pooled particles, if the emitter has already been used.\n * @member {Function} PIXI.particles.Emitter#particleConstructor\n */\nObject.defineProperty(p, \"particleConstructor\",\n{\n\tget: function() { return this._particleConstructor; },\n\tset: function(value)\n\t{\n\t\tif(value != this._particleConstructor)\n\t\t{\n\t\t\tthis._particleConstructor = value;\n\t\t\t//clean up existing particles\n\t\t\tthis.cleanup();\n\t\t\t//scrap all the particles\n\t\t\tfor (var particle = this._poolFirst; particle; particle = particle.next)\n\t\t\t{\n\t\t\t\tparticle.destroy();\n\t\t\t}\n\t\t\tthis._poolFirst = null;\n\t\t\t//re-initialize the emitter so that the new constructor can do anything it needs to\n\t\t\tif(this._origConfig && this._origArt)\n\t\t\t\tthis.init(this._origArt, this._origConfig);\n\t\t}\n\t}\n});\n\n/**\n* The container to add particles to. Settings this will dump any active particles.\n* @member {PIXI.Container} PIXI.particles.Emitter#parent\n*/\nObject.defineProperty(p, \"parent\",\n{\n\tget: function() { return this._parent; },\n\tset: function(value)\n\t{\n\t\t//if our previous parent was a ParticleContainer, then we need to remove\n\t\t//pooled particles from it\n\t\tif (this._parentIsPC) {\n\t\t\tfor (var particle = this._poolFirst; particle; particle = particle.next)\n\t\t\t{\n\t\t\t\tif(particle.parent)\n\t\t\t\t\tparticle.parent.removeChild(particle);\n\t\t\t}\n\t\t}\n\t\tthis.cleanup();\n\t\tthis._parent = value;\n\t\tthis._parentIsPC = ParticleContainer && value && value instanceof ParticleContainer;\n\t}\n});\n\n/**\n * Sets up the emitter based on the config settings.\n * @method PIXI.particles.Emitter#init\n * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles.\n * @param {Object} config A configuration object containing settings for the emitter.\n */\np.init = function(art, config)\n{\n\tif(!art || !config)\n\t\treturn;\n\t//clean up any existing particles\n\tthis.cleanup();\n\n\t//store the original config and particle images, in case we need to re-initialize\n\t//when the particle constructor is changed\n\tthis._origConfig = config;\n\tthis._origArt = art;\n\n\t//set up the array of data, also ensuring that it is an array\n\tart = Array.isArray(art) ? art.slice() : [art];\n\t//run the art through the particle class's parsing function\n\tvar partClass = this._particleConstructor;\n\tthis.particleImages = partClass.parseArt ? partClass.parseArt(art) : art;\n\t///////////////////////////\n\t// Particle Properties //\n\t///////////////////////////\n\t//set up the alpha\n\tif (config.alpha)\n\t{\n\t\tthis.startAlpha = config.alpha.start;\n\t\tthis.endAlpha = config.alpha.end;\n\t}\n\telse\n\t\tthis.startAlpha = this.endAlpha = 1;\n\t//set up the speed\n\tif (config.speed)\n\t{\n\t\tthis.startSpeed = config.speed.start;\n\t\tthis.endSpeed = config.speed.end;\n\t\tthis.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1;\n\t}\n\telse\n\t{\n\t\tthis.minimumSpeedMultiplier = 1;\n\t\tthis.startSpeed = this.endSpeed = 0;\n\t}\n\t//set up acceleration\n\tvar acceleration = config.acceleration;\n\tif(acceleration && (acceleration.x || acceleration.y))\n\t{\n\t\tthis.endSpeed = this.startSpeed;\n\t\tthis.acceleration = new PIXI.Point(acceleration.x, acceleration.y);\n\t\tthis.maxSpeed = config.maxSpeed || NaN;\n\t}\n\telse\n\t\tthis.acceleration = new PIXI.Point();\n\t//set up the scale\n\tif (config.scale)\n\t{\n\t\tthis.startScale = config.scale.start;\n\t\tthis.endScale = config.scale.end;\n\t\tthis.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1;\n\t}\n\telse\n\t\tthis.startScale = this.endScale = this.minimumScaleMultiplier = 1;\n\t//set up the color\n\tif (config.color)\n\t{\n\t\tthis.startColor = ParticleUtils.hexToRGB(config.color.start);\n\t\t//if it's just one color, only use the start color\n\t\tif (config.color.start != config.color.end)\n\t\t{\n\t\t\tthis.endColor = ParticleUtils.hexToRGB(config.color.end);\n\t\t}\n\t\telse\n\t\t\tthis.endColor = null;\n\t}\n\t//set up the start rotation\n\tif (config.startRotation)\n\t{\n\t\tthis.minStartRotation = config.startRotation.min;\n\t\tthis.maxStartRotation = config.startRotation.max;\n\t}\n\telse\n\t\tthis.minStartRotation = this.maxStartRotation = 0;\n\tif (config.noRotation &&\n\t\t(this.minStartRotation || this.maxStartRotation))\n\t{\n\t\tthis.noRotation = !!config.noRotation;\n\t}\n\telse\n\t\tthis.noRotation = false;\n\t//set up the rotation speed\n\tif (config.rotationSpeed)\n\t{\n\t\tthis.minRotationSpeed = config.rotationSpeed.min;\n\t\tthis.maxRotationSpeed = config.rotationSpeed.max;\n\t}\n\telse\n\t\tthis.minRotationSpeed = this.maxRotationSpeed = 0;\n\t//set up the lifetime\n\tthis.minLifetime = config.lifetime.min;\n\tthis.maxLifetime = config.lifetime.max;\n\t//get the blend mode\n\tthis.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode);\n\t//use the custom ease if provided\n\tif (config.ease)\n\t{\n\t\tthis.customEase = typeof config.ease == \"function\" ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tconfig.ease :\n\t\t\t\t\t\t\t\t\t\t\t\t\tParticleUtils.generateEase(config.ease);\n\t}\n\telse\n\t\tthis.customEase = null;\n\t//set up the extra data, running it through the particle class's parseData function.\n\tif(partClass.parseData)\n\t\tthis.extraData = partClass.parseData(config.extraData);\n\telse\n\t\tthis.extraData = config.extraData || null;\n\t//////////////////////////\n\t// Emitter Properties //\n\t//////////////////////////\n\t//reset spawn type specific settings\n\tthis.spawnRect = this.spawnCircle = null;\n\tthis.particlesPerWave = 1;\n\tthis.particleSpacing = 0;\n\tthis.angleStart = 0;\n\tvar spawnCircle;\n\t//determine the spawn function to use\n\tswitch(config.spawnType)\n\t{\n\t\tcase \"rect\":\n\t\t\tthis.spawnType = \"rect\";\n\t\t\tthis._spawnFunc = this._spawnRect;\n\t\t\tvar spawnRect = config.spawnRect;\n\t\t\tthis.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);\n\t\t\tbreak;\n\t\tcase \"circle\":\n\t\t\tthis.spawnType = \"circle\";\n\t\t\tthis._spawnFunc = this._spawnCircle;\n\t\t\tspawnCircle = config.spawnCircle;\n\t\t\tthis.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\n\t\t\tbreak;\n\t\tcase \"ring\":\n\t\t\tthis.spawnType = \"ring\";\n\t\t\tthis._spawnFunc = this._spawnRing;\n\t\t\tspawnCircle = config.spawnCircle;\n\t\t\tthis.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\n\t\t\tthis.spawnCircle.minRadius = spawnCircle.minR;\n\t\t\tbreak;\n\t\tcase \"burst\":\n\t\t\tthis.spawnType = \"burst\";\n\t\t\tthis._spawnFunc = this._spawnBurst;\n\t\t\tthis.particlesPerWave = config.particlesPerWave;\n\t\t\tthis.particleSpacing = config.particleSpacing;\n\t\t\tthis.angleStart = config.angleStart ? config.angleStart : 0;\n\t\t\tbreak;\n\t\tcase \"point\":\n\t\t\tthis.spawnType = \"point\";\n\t\t\tthis._spawnFunc = this._spawnPoint;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthis.spawnType = \"point\";\n\t\t\tthis._spawnFunc = this._spawnPoint;\n\t\t\tbreak;\n\t}\n\t//set the spawning frequency\n\tthis.frequency = config.frequency;\n\t//set the emitter lifetime\n\tthis.emitterLifetime = config.emitterLifetime || -1;\n\t//set the max particles\n\tthis.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000;\n\t//determine if we should add the particle at the back of the list or not\n\tthis.addAtBack = !!config.addAtBack;\n\t//reset the emitter position and rotation variables\n\tthis.rotation = 0;\n\tthis.ownerPos = new PIXI.Point();\n\tthis.spawnPos = new PIXI.Point(config.pos.x, config.pos.y);\n\tthis._prevEmitterPos = this.spawnPos.clone();\n\t//previous emitter position is invalid and should not be used for interpolation\n\tthis._prevPosIsValid = false;\n\t//start emitting\n\tthis._spawnTimer = 0;\n\tthis.emit = config.emit === undefined ? true : !!config.emit;\n\tthis.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate;\n};\n\n/**\n * Recycles an individual particle.\n * @method PIXI.particles.Emitter#recycle\n * @param {Particle} particle The particle to recycle.\n * @private\n */\np.recycle = function(particle)\n{\n\tif(particle.next)\n\t\tparticle.next.prev = particle.prev;\n\tif(particle.prev)\n\t\tparticle.prev.next = particle.next;\n\tif(particle == this._activeParticlesLast)\n\t\tthis._activeParticlesLast = particle.prev;\n\tif(particle == this._activeParticlesFirst)\n\t\tthis._activeParticlesFirst = particle.next;\n\t//add to pool\n\tparticle.prev = null;\n\tparticle.next = this._poolFirst;\n\tthis._poolFirst = particle;\n\t//remove child from display, or make it invisible if it is in a ParticleContainer\n\tif(this._parentIsPC)\n\t{\n\t\tparticle.alpha = 0;\n\t\tparticle.visible = false;\n\t}\n\telse\n\t{\n\t\tif(particle.parent)\n\t\t\tparticle.parent.removeChild(particle);\n\t}\n\t//decrease count\n\t--this.particleCount;\n};\n\n/**\n * Sets the rotation of the emitter to a new value.\n * @method PIXI.particles.Emitter#rotate\n * @param {Number} newRot The new rotation, in degrees.\n */\np.rotate = function(newRot)\n{\n\tif (this.rotation == newRot) return;\n\t//caclulate the difference in rotation for rotating spawnPos\n\tvar diff = newRot - this.rotation;\n\tthis.rotation = newRot;\n\t//rotate spawnPos\n\tParticleUtils.rotatePoint(diff, this.spawnPos);\n\t//mark the position as having changed\n\tthis._posChanged = true;\n};\n\n/**\n * Changes the spawn position of the emitter.\n * @method PIXI.particles.Emitter#updateSpawnPos\n * @param {Number} x The new x value of the spawn position for the emitter.\n * @param {Number} y The new y value of the spawn position for the emitter.\n */\np.updateSpawnPos = function(x, y)\n{\n\tthis._posChanged = true;\n\tthis.spawnPos.x = x;\n\tthis.spawnPos.y = y;\n};\n\n/**\n * Changes the position of the emitter's owner. You should call this if you are adding\n * particles to the world container that your emitter's owner is moving around in.\n * @method PIXI.particles.Emitter#updateOwnerPos\n * @param {Number} x The new x value of the emitter's owner.\n * @param {Number} y The new y value of the emitter's owner.\n */\np.updateOwnerPos = function(x, y)\n{\n\tthis._posChanged = true;\n\tthis.ownerPos.x = x;\n\tthis.ownerPos.y = y;\n};\n\n/**\n * Prevents emitter position interpolation in the next update.\n * This should be used if you made a major position change of your emitter's owner\n * that was not normal movement.\n * @method PIXI.particles.Emitter#resetPositionTracking\n */\np.resetPositionTracking = function()\n{\n\tthis._prevPosIsValid = false;\n};\n\n/**\n * If particles should be emitted during update() calls. Setting this to false\n * stops new particles from being created, but allows existing ones to die out.\n * @member {Boolean} PIXI.particles.Emitter#emit\n */\nObject.defineProperty(p, \"emit\",\n{\n\tget: function() { return this._emit; },\n\tset: function(value)\n\t{\n\t\tthis._emit = !!value;\n\t\tthis._emitterLife = this.emitterLifetime;\n\t}\n});\n\n/**\n * If the update function is called automatically from the shared ticker.\n * Setting this to false requires calling the update function manually.\n * @member {Boolean} PIXI.particles.Emitter#autoUpdate\n */\nObject.defineProperty(p, \"autoUpdate\",\n{\n\tget: function() { return this._autoUpdate; },\n\tset: function(value)\n\t{\n\t\tif (this._autoUpdate && !value)\n\t\t{\n\t\t\tticker.remove(this.update, this);\n\t\t}\n\t\telse if (!this._autoUpdate && value)\n\t\t{\n\t\t\tticker.add(this.update, this);\n\t\t}\n\t\tthis._autoUpdate = !!value;\n\t}\n});\n\n/**\n * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself\n * when particle emission is complete.\n * @method PIXI.particles.Emitter#playOnceAndDestroy\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\n */\np.playOnceAndDestroy = function(callback)\n{\n\tthis.autoUpdate = true;\n\tthis.emit = true;\n\tthis._destroyWhenComplete = true;\n\tthis._completeCallback = callback;\n};\n\n/**\n * Starts emitting particles, sets autoUpdate to true, and optionally calls a callback\n * when particle emission is complete.\n * @method PIXI.particles.Emitter#playOnce\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\n */\np.playOnce = function(callback)\n{\n\tthis.autoUpdate = true;\n\tthis.emit = true;\n\tthis._completeCallback = callback;\n};\n\n/**\n * Updates all particles spawned by this emitter and emits new ones.\n * @method PIXI.particles.Emitter#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n */\np.update = function(delta)\n{\n\tif (this._autoUpdate)\n\t{\n\t\tdelta = delta / PIXI.settings.TARGET_FPMS / 1000;\n\t}\n\n\t//if we don't have a parent to add particles to, then don't do anything.\n\t//this also works as a isDestroyed check\n\tif (!this._parent) return;\n\t//update existing particles\n\tvar i, particle, next;\n\tfor (particle = this._activeParticlesFirst; particle; particle = next)\n\t{\n\t\tnext = particle.next;\n\t\tparticle.update(delta);\n\t}\n\tvar prevX, prevY;\n\t//if the previous position is valid, store these for later interpolation\n\tif(this._prevPosIsValid)\n\t{\n\t\tprevX = this._prevEmitterPos.x;\n\t\tprevY = this._prevEmitterPos.y;\n\t}\n\t//store current position of the emitter as local variables\n\tvar curX = this.ownerPos.x + this.spawnPos.x;\n\tvar curY = this.ownerPos.y + this.spawnPos.y;\n\t//spawn new particles\n\tif (this._emit)\n\t{\n\t\t//decrease spawn timer\n\t\tthis._spawnTimer -= delta;\n\t\t//while _spawnTimer < 0, we have particles to spawn\n\t\twhile(this._spawnTimer <= 0)\n\t\t{\n\t\t\t//determine if the emitter should stop spawning\n\t\t\tif(this._emitterLife > 0)\n\t\t\t{\n\t\t\t\tthis._emitterLife -= this._frequency;\n\t\t\t\tif(this._emitterLife <= 0)\n\t\t\t\t{\n\t\t\t\t\tthis._spawnTimer = 0;\n\t\t\t\t\tthis._emitterLife = 0;\n\t\t\t\t\tthis.emit = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//determine if we have hit the particle limit\n\t\t\tif(this.particleCount >= this.maxParticles)\n\t\t\t{\n\t\t\t\tthis._spawnTimer += this._frequency;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t//determine the particle lifetime\n\t\t\tvar lifetime;\n\t\t\tif (this.minLifetime == this.maxLifetime)\n\t\t\t\tlifetime = this.minLifetime;\n\t\t\telse\n\t\t\t\tlifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime;\n\t\t\t//only make the particle if it wouldn't immediately destroy itself\n\t\t\tif(-this._spawnTimer < lifetime)\n\t\t\t{\n\t\t\t\t//If the position has changed and this isn't the first spawn,\n\t\t\t\t//interpolate the spawn position\n\t\t\t\tvar emitPosX, emitPosY;\n\t\t\t\tif (this._prevPosIsValid && this._posChanged)\n\t\t\t\t{\n\t\t\t\t\t//1 - _spawnTimer / delta, but _spawnTimer is negative\n\t\t\t\t\tvar lerp = 1 + this._spawnTimer / delta;\n\t\t\t\t\temitPosX = (curX - prevX) * lerp + prevX;\n\t\t\t\t\temitPosY = (curY - prevY) * lerp + prevY;\n\t\t\t\t}\n\t\t\t\telse//otherwise just set to the spawn position\n\t\t\t\t{\n\t\t\t\t\temitPosX = curX;\n\t\t\t\t\temitPosY = curY;\n\t\t\t\t}\n\t\t\t\t//create enough particles to fill the wave (non-burst types have a wave of 1)\n\t\t\t\ti = 0;\n\t\t\t\tfor(var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i)\n\t\t\t\t{\n\t\t\t\t\t//create particle\n\t\t\t\t\tvar p, rand;\n\t\t\t\t\tif(this._poolFirst)\n\t\t\t\t\t{\n\t\t\t\t\t\tp = this._poolFirst;\n\t\t\t\t\t\tthis._poolFirst = this._poolFirst.next;\n\t\t\t\t\t\tp.next = null;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp = new this.particleConstructor(this);\n\t\t\t\t\t}\n\n\t\t\t\t\t//set a random texture if we have more than one\n\t\t\t\t\tif(this.particleImages.length > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tp.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//if they are actually the same texture, a standard particle\n\t\t\t\t\t\t//will quit early from the texture setting in setTexture().\n\t\t\t\t\t\tp.applyArt(this.particleImages[0]);\n\t\t\t\t\t}\n\t\t\t\t\t//set up the start and end values\n\t\t\t\t\tp.startAlpha = this.startAlpha;\n\t\t\t\t\tp.endAlpha = this.endAlpha;\n\t\t\t\t\tif(this.minimumSpeedMultiplier != 1)\n\t\t\t\t\t{\n\t\t\t\t\t\trand = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier;\n\t\t\t\t\t\tp.startSpeed = this.startSpeed * rand;\n\t\t\t\t\t\tp.endSpeed = this.endSpeed * rand;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp.startSpeed = this.startSpeed;\n\t\t\t\t\t\tp.endSpeed = this.endSpeed;\n\t\t\t\t\t}\n\t\t\t\t\tp.acceleration.x = this.acceleration.x;\n\t\t\t\t\tp.acceleration.y = this.acceleration.y;\n\t\t\t\t\tp.maxSpeed = this.maxSpeed;\n\t\t\t\t\tif(this.minimumScaleMultiplier != 1)\n\t\t\t\t\t{\n\t\t\t\t\t\trand = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier;\n\t\t\t\t\t\tp.startScale = this.startScale * rand;\n\t\t\t\t\t\tp.endScale = this.endScale * rand;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tp.startScale = this.startScale;\n\t\t\t\t\t\tp.endScale = this.endScale;\n\t\t\t\t\t}\n\t\t\t\t\tp.startColor = this.startColor;\n\t\t\t\t\tp.endColor = this.endColor;\n\t\t\t\t\t//randomize the rotation speed\n\t\t\t\t\tif(this.minRotationSpeed == this.maxRotationSpeed)\n\t\t\t\t\t\tp.rotationSpeed = this.minRotationSpeed;\n\t\t\t\t\telse\n\t\t\t\t\t\tp.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed;\n\t\t\t\t\tp.noRotation = this.noRotation;\n\t\t\t\t\t//set up the lifetime\n\t\t\t\t\tp.maxLife = lifetime;\n\t\t\t\t\t//set the blend mode\n\t\t\t\t\tp.blendMode = this.particleBlendMode;\n\t\t\t\t\t//set the custom ease, if any\n\t\t\t\t\tp.ease = this.customEase;\n\t\t\t\t\t//set the extra data, if any\n\t\t\t\t\tp.extraData = this.extraData;\n\t\t\t\t\t//call the proper function to handle rotation and position of particle\n\t\t\t\t\tthis._spawnFunc(p, emitPosX, emitPosY, i);\n\t\t\t\t\t//initialize particle\n\t\t\t\t\tp.init();\n\t\t\t\t\t//update the particle by the time passed, so the particles are spread out properly\n\t\t\t\t\tp.update(-this._spawnTimer);//we want a positive delta, because a negative delta messes things up\n\t\t\t\t\t//add the particle to the display list\n\t\t\t\t\tif(!this._parentIsPC || !p.parent)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (this.addAtBack)\n\t\t\t\t\t\t\tthis._parent.addChildAt(p, 0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tthis._parent.addChild(p);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//kind of hacky, but performance friendly\n\t\t\t\t\t\t//shuffle children to correct place\n\t\t\t\t\t\tvar children = this._parent.children;\n\t\t\t\t\t\t//avoid using splice if possible\n\t\t\t\t\t\tif(children[0] == p)\n\t\t\t\t\t\t\tchildren.shift();\n\t\t\t\t\t\telse if(children[children.length-1] == p)\n\t\t\t\t\t\t\tchildren.pop();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar index = children.indexOf(p);\n\t\t\t\t\t\t\tchildren.splice(index, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(this.addAtBack)\n\t\t\t\t\t\t\tchildren.unshift(p);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tchildren.push(p);\n\t\t\t\t\t}\n\t\t\t\t\t//add particle to list of active particles\n\t\t\t\t\tif(this._activeParticlesLast)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis._activeParticlesLast.next = p;\n\t\t\t\t\t\tp.prev = this._activeParticlesLast;\n\t\t\t\t\t\tthis._activeParticlesLast = p;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthis._activeParticlesLast = this._activeParticlesFirst = p;\n\t\t\t\t\t}\n\t\t\t\t\t++this.particleCount;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//increase timer and continue on to any other particles that need to be created\n\t\t\tthis._spawnTimer += this._frequency;\n\t\t}\n\t}\n\t//if the position changed before this update, then keep track of that\n\tif(this._posChanged)\n\t{\n\t\tthis._prevEmitterPos.x = curX;\n\t\tthis._prevEmitterPos.y = curY;\n\t\tthis._prevPosIsValid = true;\n\t\tthis._posChanged = false;\n\t}\n\n\t//if we are all done and should destroy ourselves, take care of that\n\tif (!this._emit && !this._activeParticlesFirst)\n\t{\n\t\tif (this._completeCallback)\n\t\t{\n\t\t\tthis._completeCallback();\n\t\t}\n\t\tif (this._destroyWhenComplete)\n\t\t{\n\t\t\tthis.destroy();\n\t\t}\n\t}\n};\n\n/**\n * Positions a particle for a point type emitter.\n * @method PIXI.particles.Emitter#_spawnPoint\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnPoint = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on\n\t//starting particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\n\t//drop the particle at the emitter's position\n\tp.position.x = emitPosX;\n\tp.position.y = emitPosY;\n};\n\n/**\n * Positions a particle for a rectangle type emitter.\n * @method PIXI.particles.Emitter#_spawnRect\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnRect = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\n\t//place the particle at a random point in the rectangle\n\thelperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x;\n\thelperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y;\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a circle type emitter.\n * @method PIXI.particles.Emitter#_spawnCircle\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnCircle = function(p, emitPosX, emitPosY)\n{\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\n\t\t\t\t\tthis.minStartRotation + this.rotation;\n\t//place the particle at a random radius in the circle\n\thelperPoint.x = Math.random() * this.spawnCircle.radius;\n\thelperPoint.y = 0;\n\t//rotate the point to a random angle in the circle\n\tParticleUtils.rotatePoint(Math.random() * 360, helperPoint);\n\t//offset by the circle's center\n\thelperPoint.x += this.spawnCircle.x;\n\thelperPoint.y += this.spawnCircle.y;\n\t//rotate the point by the emitter's rotation\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\t//set the position, offset by the emitter's position\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a ring type emitter.\n * @method PIXI.particles.Emitter#_spawnRing\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave. Not used for this function.\n */\np._spawnRing = function(p, emitPosX, emitPosY)\n{\n\tvar spawnCircle = this.spawnCircle;\n\t//set the initial rotation/direction of the particle based on starting\n\t//particle angle and rotation of emitter\n\tif (this.minStartRotation == this.maxStartRotation)\n\t\tp.rotation = this.minStartRotation + this.rotation;\n\telse\n\t\tp.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\n\t\t\t\t\tthis.minStartRotation + this.rotation;\n\t//place the particle at a random radius in the ring\n\tif(spawnCircle.minRadius == spawnCircle.radius)\n\t{\n\t\thelperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) +\n\t\t\t\t\t\tspawnCircle.minRadius;\n\t}\n\telse\n\t\thelperPoint.x = spawnCircle.radius;\n\thelperPoint.y = 0;\n\t//rotate the point to a random angle in the circle\n\tvar angle = Math.random() * 360;\n\tp.rotation += angle;\n\tParticleUtils.rotatePoint(angle, helperPoint);\n\t//offset by the circle's center\n\thelperPoint.x += this.spawnCircle.x;\n\thelperPoint.y += this.spawnCircle.y;\n\t//rotate the point by the emitter's rotation\n\tif(this.rotation !== 0)\n\t\tParticleUtils.rotatePoint(this.rotation, helperPoint);\n\t//set the position, offset by the emitter's position\n\tp.position.x = emitPosX + helperPoint.x;\n\tp.position.y = emitPosY + helperPoint.y;\n};\n\n/**\n * Positions a particle for a burst type emitter.\n * @method PIXI.particles.Emitter#_spawnBurst\n * @private\n * @param {Particle} p The particle to position and rotate.\n * @param {Number} emitPosX The emitter's x position\n * @param {Number} emitPosY The emitter's y position\n * @param {int} i The particle number in the current wave.\n */\np._spawnBurst = function(p, emitPosX, emitPosY, i)\n{\n\t//set the initial rotation/direction of the particle based on spawn\n\t//angle and rotation of emitter\n\tif(this.particleSpacing === 0)\n\t\tp.rotation = Math.random() * 360;\n\telse\n\t\tp.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation;\n\t//drop the particle at the emitter's position\n\tp.position.x = emitPosX;\n\tp.position.y = emitPosY;\n};\n\n/**\n * Kills all active particles immediately.\n * @method PIXI.particles.Emitter#cleanup\n */\np.cleanup = function()\n{\n\tvar particle, next;\n\tfor (particle = this._activeParticlesFirst; particle; particle = next)\n\t{\n\t\tnext = particle.next;\n\t\tthis.recycle(particle);\n\t\tif(particle.parent)\n\t\t\tparticle.parent.removeChild(particle);\n\t}\n\tthis._activeParticlesFirst = this._activeParticlesLast = null;\n\tthis.particleCount = 0;\n};\n\n/**\n * Destroys the emitter and all of its particles.\n * @method PIXI.particles.Emitter#destroy\n */\np.destroy = function()\n{\n\t//make sure we aren't still listening to any tickers\n\tthis.autoUpdate = false;\n\t//puts all active particles in the pool, and removes them from the particle parent\n\tthis.cleanup();\n\t//wipe the pool clean\n\tvar next;\n\tfor (var particle = this._poolFirst; particle; particle = next)\n\t{\n\t\t//store next value so we don't lose it in our destroy call\n\t\tnext = particle.next;\n\t\tparticle.destroy();\n\t}\n\tthis._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos =\n\t\tthis.startColor = this.endColor = this.customEase = this._completeCallback = null;\n};\n\nmodule.exports = Emitter;","var ParticleUtils = require(\"./ParticleUtils\");\nvar Sprite = PIXI.Sprite;\n\n/**\n * An individual particle image. You shouldn't have to deal with these.\n * @memberof PIXI.particles\n * @class Particle\n * @extends PIXI.Sprite\n * @constructor\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle.\n */\nvar Particle = function(emitter)\n{\n\t//start off the sprite with a blank texture, since we are going to replace it\n\t//later when the particle is initialized.\n\tSprite.call(this);\n\n\t/**\n\t * The emitter that controls this particle.\n\t * @property {Emitter} emitter\n\t */\n\tthis.emitter = emitter;\n\t//particles should be centered\n\tthis.anchor.x = this.anchor.y = 0.5;\n\t/**\n\t * The velocity of the particle. Speed may change, but the angle also\n\t * contained in velocity is constant.\n\t * @property {PIXI.Point} velocity\n\t */\n\tthis.velocity = new PIXI.Point();\n\t/**\n\t * The maximum lifetime of this particle, in seconds.\n\t * @property {Number} maxLife\n\t */\n\tthis.maxLife = 0;\n\t/**\n\t * The current age of the particle, in seconds.\n\t * @property {Number} age\n\t */\n\tthis.age = 0;\n\t/**\n\t * A simple easing function to be applied to all properties that\n\t * are being interpolated.\n\t * @property {Function} ease\n\t */\n\tthis.ease = null;\n\t/**\n\t * Extra data that the emitter passes along for custom particles.\n\t * @property {Object} extraData\n\t */\n\tthis.extraData = null;\n\t/**\n\t * The alpha of the particle at the start of its life.\n\t * @property {Number} startAlpha\n\t */\n\tthis.startAlpha = 0;\n\t/**\n\t * The alpha of the particle at the end of its life.\n\t * @property {Number} endAlpha\n\t */\n\tthis.endAlpha = 0;\n\t/**\n\t * The speed of the particle at the start of its life.\n\t * @property {Number} startSpeed\n\t */\n\tthis.startSpeed = 0;\n\t/**\n\t * The speed of the particle at the end of its life.\n\t * @property {Number} endSpeed\n\t */\n\tthis.endSpeed = 0;\n\t/**\n\t * Acceleration to apply to the particle.\n\t * @property {PIXI.Point} accleration\n\t */\n\tthis.acceleration = new PIXI.Point();\n\t/**\n\t * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n\t * will disable the maximum speed.\n\t * @property {Number} maxSpeed\n\t * @default NaN\n\t */\n\tthis.maxSpeed = NaN;\n\t/**\n\t * The scale of the particle at the start of its life.\n\t * @property {Number} startScale\n\t */\n\tthis.startScale = 0;\n\t/**\n\t * The scale of the particle at the start of its life.\n\t * @property {Number} endScale\n\t */\n\tthis.endScale = 0;\n\t/**\n\t * The tint of the particle at the start of its life.\n\t * @property {Array} startColor\n\t */\n\tthis.startColor = null;\n\t/**\n\t * The red tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sR\n\t * @private\n\t */\n\tthis._sR = 0;\n\t/**\n\t * The green tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sG\n\t * @private\n\t */\n\tthis._sG = 0;\n\t/**\n\t * The blue tint of the particle at the start of its life.\n\t * This is pulled from startColor in init().\n\t * @property {uint} _sB\n\t * @private\n\t */\n\tthis._sB = 0;\n\t/**\n\t * The tint of the particle at the start of its life.\n\t * @property {Array} endColor\n\t */\n\tthis.endColor = null;\n\t/**\n\t * The red tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _eR\n\t * @private\n\t */\n\tthis._eR = 0;\n\t/**\n\t * The green tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _sG\n\t * @private\n\t */\n\tthis._eG = 0;\n\t/**\n\t * The blue tint of the particle at the end of its life.\n\t * This is pulled from endColor in init().\n\t * @property {uint} _sB\n\t * @private\n\t */\n\tthis._eB = 0;\n\t/**\n\t * If alpha should be interpolated at all.\n\t * @property {Boolean} _doAlpha\n\t * @private\n\t */\n\tthis._doAlpha = false;\n\t/**\n\t * If scale should be interpolated at all.\n\t * @property {Boolean} _doScale\n\t * @private\n\t */\n\tthis._doScale = false;\n\t/**\n\t * If speed should be interpolated at all.\n\t * @property {Boolean} _doSpeed\n\t * @private\n\t */\n\tthis._doSpeed = false;\n\t/**\n\t * If acceleration should be handled at all. _doSpeed is mutually exclusive with this,\n\t * and _doSpeed gets priority.\n\t * @property {Boolean} _doAcceleration\n\t * @private\n\t */\n\tthis._doAcceleration = false;\n\t/**\n\t * If color should be interpolated at all.\n\t * @property {Boolean} _doColor\n\t * @private\n\t */\n\tthis._doColor = false;\n\t/**\n\t * If normal movement should be handled. Subclasses wishing to override movement\n\t * can set this to false in init().\n\t * @property {Boolean} _doNormalMovement\n\t * @private\n\t */\n\tthis._doNormalMovement = false;\n\t/**\n\t * One divided by the max life of the particle, saved for slightly faster math.\n\t * @property {Number} _oneOverLife\n\t * @private\n\t */\n\tthis._oneOverLife = 0;\n\n\t/**\n\t * Reference to the next particle in the list.\n\t * @property {Particle} next\n\t * @private\n\t */\n\tthis.next = null;\n\n\t/**\n\t * Reference to the previous particle in the list.\n\t * @property {Particle} prev\n\t * @private\n\t */\n\tthis.prev = null;\n\n\t//save often used functions on the instance instead of the prototype for better speed\n\tthis.init = this.init;\n\tthis.Particle_init = this.Particle_init;\n\tthis.update = this.update;\n\tthis.Particle_update = this.Particle_update;\n\tthis.applyArt = this.applyArt;\n\tthis.kill = this.kill;\n};\n\n// Reference to the prototype\nvar p = Particle.prototype = Object.create(Sprite.prototype);\n\n/**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n * @method PIXI.particles.Particle#init\n */\n/**\n * A reference to init, so that subclasses can access it without the penalty of Function.call()\n * @method PIXI.particles.Particle#Particle_init\n * @protected\n */\np.init = p.Particle_init = function()\n{\n\t//reset the age\n\tthis.age = 0;\n\t//set up the velocity based on the start speed and rotation\n\tthis.velocity.x = this.startSpeed;\n\tthis.velocity.y = 0;\n\tParticleUtils.rotatePoint(this.rotation, this.velocity);\n\tif (this.noRotation)\n\t{\n\t\tthis.rotation = 0;\n\t}\n\telse\n\t{\n\t\t//convert rotation to Radians from Degrees\n\t\tthis.rotation *= ParticleUtils.DEG_TO_RADS;\n\t}\n\t//convert rotation speed to Radians from Degrees\n\tthis.rotationSpeed *= ParticleUtils.DEG_TO_RADS;\n\t//set alpha to inital alpha\n\tthis.alpha = this.startAlpha;\n\t//set scale to initial scale\n\tthis.scale.x = this.scale.y = this.startScale;\n\t//determine start and end color values\n\tif (this.startColor)\n\t{\n\t\tthis._sR = this.startColor[0];\n\t\tthis._sG = this.startColor[1];\n\t\tthis._sB = this.startColor[2];\n\t\tif(this.endColor)\n\t\t{\n\t\t\tthis._eR = this.endColor[0];\n\t\t\tthis._eG = this.endColor[1];\n\t\t\tthis._eB = this.endColor[2];\n\t\t}\n\t}\n\t//figure out what we need to interpolate\n\tthis._doAlpha = this.startAlpha != this.endAlpha;\n\tthis._doSpeed = this.startSpeed != this.endSpeed;\n\tthis._doScale = this.startScale != this.endScale;\n\tthis._doColor = !!this.endColor;\n\tthis._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0;\n\t//_doNormalMovement can be cancelled by subclasses\n\tthis._doNormalMovement = this._doSpeed || this.startSpeed !== 0 || this._doAcceleration;\n\t//save our lerp helper\n\tthis._oneOverLife = 1 / this.maxLife;\n\t//set the inital color\n\tthis.tint = ParticleUtils.combineRGBComponents(this._sR, this._sG, this._sB);\n\t//ensure visibility\n\tthis.visible = true;\n};\n\n/**\n * Sets the texture for the particle. This can be overridden to allow\n * for an animated particle.\n * @method PIXI.particles.Particle#applyArt\n * @param {PIXI.Texture} art The texture to set.\n */\np.applyArt = function(art)\n{\n\tthis.texture = art || ParticleUtils.EMPTY_TEXTURE;\n};\n\n/**\n * Updates the particle.\n * @method PIXI.particles.Particle#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\n * properties. A value of -1 means the particle died of old age instead.\n */\n/**\n * A reference to update so that subclasses can access the original without the overhead\n * of Function.call().\n * @method PIXI.particles.Particle#Particle_update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\n * properties. A value of -1 means the particle died of old age instead.\n * @protected\n */\np.update = p.Particle_update = function(delta)\n{\n\t//increase age\n\tthis.age += delta;\n\t//recycle particle if it is too old\n\tif(this.age >= this.maxLife)\n\t{\n\t\tthis.kill();\n\t\treturn -1;\n\t}\n\n\t//determine our interpolation value\n\tvar lerp = this.age * this._oneOverLife;//lifetime / maxLife;\n\tif (this.ease)\n\t{\n\t\tif(this.ease.length == 4)\n\t\t{\n\t\t\t//the t, b, c, d parameters that some tween libraries use\n\t\t\t//(time, initial value, end value, duration)\n\t\t\tlerp = this.ease(lerp, 0, 1, 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//the simplified version that we like that takes\n\t\t\t//one parameter, time from 0-1. TweenJS eases provide this usage.\n\t\t\tlerp = this.ease(lerp);\n\t\t}\n\t}\n\n\t//interpolate alpha\n\tif (this._doAlpha)\n\t\tthis.alpha = (this.endAlpha - this.startAlpha) * lerp + this.startAlpha;\n\t//interpolate scale\n\tif (this._doScale)\n\t{\n\t\tvar scale = (this.endScale - this.startScale) * lerp + this.startScale;\n\t\tthis.scale.x = this.scale.y = scale;\n\t}\n\t//handle movement\n\tif(this._doNormalMovement)\n\t{\n\t\t//interpolate speed\n\t\tif (this._doSpeed)\n\t\t{\n\t\t\tvar speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed;\n\t\t\tParticleUtils.normalize(this.velocity);\n\t\t\tParticleUtils.scaleBy(this.velocity, speed);\n\t\t}\n\t\telse if(this._doAcceleration)\n\t\t{\n\t\t\tthis.velocity.x += this.acceleration.x * delta;\n\t\t\tthis.velocity.y += this.acceleration.y * delta;\n\t\t\tif (this.maxSpeed)\n\t\t\t{\n\t\t\t\tvar currentSpeed = ParticleUtils.length(this.velocity);\n\t\t\t\t//if we are going faster than we should, clamp at the max speed\n\t\t\t\t//DO NOT recalculate vector length\n\t\t\t\tif (currentSpeed > this.maxSpeed)\n\t\t\t\t{\n\t\t\t\t\tParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//adjust position based on velocity\n\t\tthis.position.x += this.velocity.x * delta;\n\t\tthis.position.y += this.velocity.y * delta;\n\t}\n\t//interpolate color\n\tif (this._doColor)\n\t{\n\t\tvar r = (this._eR - this._sR) * lerp + this._sR;\n\t\tvar g = (this._eG - this._sG) * lerp + this._sG;\n\t\tvar b = (this._eB - this._sB) * lerp + this._sB;\n\t\tthis.tint = ParticleUtils.combineRGBComponents(r, g, b);\n\t}\n\t//update rotation\n\tif(this.rotationSpeed !== 0)\n\t{\n\t\tthis.rotation += this.rotationSpeed * delta;\n\t}\n\telse if(this.acceleration && !this.noRotation)\n\t{\n\t\tthis.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2;\n\t}\n\treturn lerp;\n};\n\n/**\n * Kills the particle, removing it from the display list\n * and telling the emitter to recycle it.\n * @method PIXI.particles.Particle#kill\n */\np.kill = function()\n{\n\tthis.emitter.recycle(this);\n};\n\np.Sprite_Destroy = Sprite.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.Particle#destroy\n */\np.destroy = function()\n{\n\tif (this.parent)\n\t\tthis.parent.removeChild(this);\n\tif (this.Sprite_Destroy)\n\t\tthis.Sprite_Destroy();\n\tthis.emitter = this.velocity = this.startColor = this.endColor = this.ease =\n\t\tthis.next = this.prev = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @method PIXI.particles.Particle.parseArt\n * @static\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\n * Any strings in the array will be converted to Textures via\n * Texture.fromImage().\n * @return {Array} The art, after any needed modifications.\n */\nParticle.parseArt = function(art)\n{\n\t//convert any strings to Textures.\n\tvar i;\n\tfor(i = art.length; i >= 0; --i)\n\t{\n\t\tif(typeof art[i] == \"string\")\n\t\t\tart[i] = PIXI.Texture.fromImage(art[i]);\n\t}\n\t//particles from different base textures will be slower in WebGL than if they\n\t//were from one spritesheet\n\tif(ParticleUtils.verbose)\n\t{\n\t\tfor(i = art.length - 1; i > 0; --i)\n\t\t{\n\t\t\tif(art[i].baseTexture != art[i - 1].baseTexture)\n\t\t\t{\n\t\t\t\tif (window.console)\n\t\t\t\t\tconsole.warn(\"PixiParticles: using particle textures from different images may hinder performance in WebGL\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn art;\n};\n\n/**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * Particle does nothing to the extra data.\n * @method PIXI.particles.Particle.parseData\n * @static\n * @param {Object} extraData The extra data from the particle config.\n * @return {Object} The parsed extra data.\n */\nParticle.parseData = function(extraData)\n{\n\treturn extraData;\n};\n\nmodule.exports = Particle;","\"use strict\";\n\nvar BLEND_MODES = PIXI.BLEND_MODES || PIXI.blendModes;\nvar Texture = PIXI.Texture;\n\n/**\n * Contains helper functions for particles and emitters to use.\n * @memberof PIXI.particles\n * @class ParticleUtils\n * @static\n */\nvar ParticleUtils = {};\n\n/**\n * If errors and warnings should be logged within the library.\n * @name PIXI.particles.ParticleUtils.verbose\n * @default false\n * @static\n */\nParticleUtils.verbose = false;\n\nvar DEG_TO_RADS = ParticleUtils.DEG_TO_RADS = Math.PI / 180;\n\nvar empty = ParticleUtils.EMPTY_TEXTURE = Texture.EMPTY;\n//prevent any events from being used on the empty texture, as well as destruction of it\n//v4 of Pixi does this, but doing it again won't hurt\nempty.on = empty.destroy = empty.once = empty.emit = function() {};\n\n/**\n * Rotates a point by a given angle.\n * @method PIXI.particles.ParticleUtils.rotatePoint\n * @param {Number} angle The angle to rotate by in degrees\n * @param {PIXI.Point} p The point to rotate around 0,0.\n * @static\n */\nParticleUtils.rotatePoint = function(angle, p)\n{\n\tif(!angle) return;\n\tangle *= DEG_TO_RADS;\n\tvar s = Math.sin(angle);\n\tvar c = Math.cos(angle);\n\tvar xnew = p.x * c - p.y * s;\n\tvar ynew = p.x * s + p.y * c;\n\tp.x = xnew;\n\tp.y = ynew;\n};\n\n/**\n * Combines separate color components (0-255) into a single uint color.\n * @method PIXI.particles.ParticleUtils.combineRGBComponents\n * @param {uint} r The red value of the color\n * @param {uint} g The green value of the color\n * @param {uint} b The blue value of the color\n * @return {uint} The color in the form of 0xRRGGBB\n * @static\n */\nParticleUtils.combineRGBComponents = function(r, g, b/*, a*/)\n{\n\treturn /*a << 24 |*/ r << 16 | g << 8 | b;\n};\n\n/**\n * Reduces the point to a length of 1.\n * @method PIXI.particles.ParticleUtils.normalize\n * @static\n * @param {PIXI.Point} point The point to normalize\n */\nParticleUtils.normalize = function(point)\n{\n\tvar oneOverLen = 1 / ParticleUtils.length(point);\n\tpoint.x *= oneOverLen;\n\tpoint.y *= oneOverLen;\n};\n\n/**\n * Multiplies the x and y values of this point by a value.\n * @method PIXI.particles.ParticleUtils.scaleBy\n * @static\n * @param {PIXI.Point} point The point to scaleBy\n * @param value {Number} The value to scale by.\n */\nParticleUtils.scaleBy = function(point, value)\n{\n\tpoint.x *= value;\n\tpoint.y *= value;\n};\n\n/**\n * Returns the length (or magnitude) of this point.\n * @method PIXI.particles.ParticleUtils.length\n * @static\n * @param {PIXI.Point} point The point to measure length\n * @return The length of this point.\n */\nParticleUtils.length = function(point)\n{\n\treturn Math.sqrt(point.x * point.x + point.y * point.y);\n};\n\n/**\n * Converts a hex string from \"#AARRGGBB\", \"#RRGGBB\", \"0xAARRGGBB\", \"0xRRGGBB\",\n * \"AARRGGBB\", or \"RRGGBB\" to an array of ints of 0-255 or Numbers from 0-1, as\n * [r, g, b, (a)].\n * @method PIXI.particles.ParticleUtils.hexToRGB\n * @param {String} color The input color string.\n * @param {Array} output An array to put the output in. If omitted, a new array is created.\n * @return The array of numeric color values.\n * @static\n */\nParticleUtils.hexToRGB = function(color, output)\n{\n\tif (output)\n\t\toutput.length = 0;\n\telse\n\t\toutput = [];\n\tif (color.charAt(0) == \"#\")\n\t\tcolor = color.substr(1);\n\telse if (color.indexOf(\"0x\") === 0)\n\t\tcolor = color.substr(2);\n\tvar alpha;\n\tif (color.length == 8)\n\t{\n\t\talpha = color.substr(0, 2);\n\t\tcolor = color.substr(2);\n\t}\n\toutput.push(parseInt(color.substr(0, 2), 16));//Red\n\toutput.push(parseInt(color.substr(2, 2), 16));//Green\n\toutput.push(parseInt(color.substr(4, 2), 16));//Blue\n\tif (alpha)\n\t\toutput.push(parseInt(alpha, 16));\n\treturn output;\n};\n\n/**\n * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated\n * by the related tool at http://www.greensock.com/customease/.\n * @method PIXI.particles.ParticleUtils.generateEase\n * @param {Array} segments An array of segments, as created by\n * http://www.greensock.com/customease/.\n * @return {Function} A function that calculates the percentage of change at\n * a given point in time (0-1 inclusive).\n * @static\n */\nParticleUtils.generateEase = function(segments)\n{\n\tvar qty = segments.length;\n\tvar oneOverQty = 1 / qty;\n\t/*\n\t * Calculates the percentage of change at a given point in time (0-1 inclusive).\n\t * @param {Number} time The time of the ease, 0-1 inclusive.\n\t * @return {Number} The percentage of the change, 0-1 inclusive (unless your\n\t * ease goes outside those bounds).\n\t */\n\tvar simpleEase = function(time)\n\t{\n\t\tvar t, s;\n\t\tvar i = (qty * time) | 0;//do a quick floor operation\n\t\tt = (time - (i * oneOverQty)) * qty;\n\t\ts = segments[i] || segments[qty - 1];\n\t\treturn (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s)));\n\t};\n\treturn simpleEase;\n};\n\n/**\n * Gets a blend mode, ensuring that it is valid.\n * @method PIXI.particles.ParticleUtils.getBlendMode\n * @param {String} name The name of the blend mode to get.\n * @return {int} The blend mode as specified in the PIXI.blendModes enumeration.\n * @static\n */\nParticleUtils.getBlendMode = function(name)\n{\n\tif (!name) return BLEND_MODES.NORMAL;\n\tname = name.toUpperCase();\n\twhile (name.indexOf(\" \") >= 0)\n\t\tname = name.replace(\" \", \"_\");\n\treturn BLEND_MODES[name] || BLEND_MODES.NORMAL;\n};\n\nmodule.exports = ParticleUtils;","\"use strict\";\n\nvar ParticleUtils = require(\"./ParticleUtils\"),\n\tParticle = require(\"./Particle\");\n\n/**\n * An particle that follows a path defined by an algebraic expression, e.g. \"sin(x)\" or\n * \"5x + 3\".\n * To use this class, the particle config must have a \"path\" string in the\n * \"extraData\" parameter. This string should have \"x\" in it to represent movement (from the\n * speed settings of the particle). It may have numbers, parentheses, the four basic\n * operations, and the following Math functions or properties (without the preceding \"Math.\"):\n * \"pow\", \"sqrt\", \"abs\", \"floor\", \"round\", \"ceil\", \"E\", \"PI\", \"sin\", \"cos\", \"tan\", \"asin\",\n * \"acos\", \"atan\", \"atan2\", \"log\".\n * The overall movement of the particle and the expression value become x and y positions for\n * the particle, respectively. The final position is rotated by the spawn rotation/angle of\n * the particle.\n *\n * Some example paths:\n *\n * \t\"sin(x/10) * 20\" // A sine wave path.\n * \t\"cos(x/100) * 30\" // Particles curve counterclockwise (for medium speed/low lifetime particles)\n * \t\"pow(x/10, 2) / 2\" // Particles curve clockwise (remember, +y is down).\n *\n * @memberof PIXI.particles\n * @class PathParticle\n * @extends PIXI.particles.Particle\n * @constructor\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle.\n */\nvar PathParticle = function(emitter)\n{\n\tParticle.call(this, emitter);\n\t/**\n\t * The function representing the path the particle should take.\n\t * @property {Function} path\n\t */\n\tthis.path = null;\n\t/**\n\t * The initial rotation in degrees of the particle, because the direction of the path\n\t * is based on that.\n\t * @property {Number} initialRotation\n\t */\n\tthis.initialRotation = 0;\n\t/**\n\t * The initial position of the particle, as all path movement is added to that.\n\t * @property {PIXI.Point} initialPosition\n\t */\n\tthis.initialPosition = new PIXI.Point();\n\t/**\n\t * Total single directional movement, due to speed.\n\t * @property {Number} movement\n\t */\n\tthis.movement = 0;\n};\n\n// Reference to the super class\nvar s = Particle.prototype;\n// Reference to the prototype\nvar p = PathParticle.prototype = Object.create(s);\n\n/**\n * A helper point for math things.\n * @property {Function} helperPoint\n * @private\n * @static\n */\nvar helperPoint = new PIXI.Point();\n\n/**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n * @method PIXI.particles.PathParticle#init\n */\np.init = function()\n{\n\t//get initial rotation before it is converted to radians\n\tthis.initialRotation = this.rotation;\n\t//standard init\n\tthis.Particle_init();\n\n\t//set the path for the particle\n\tthis.path = this.extraData.path;\n\t//cancel the normal movement behavior\n\tthis._doNormalMovement = !this.path;\n\t//reset movement\n\tthis.movement = 0;\n\t//grab position\n\tthis.initialPosition.x = this.position.x;\n\tthis.initialPosition.y = this.position.y;\n};\n\n//a hand picked list of Math functions (and a couple properties) that are allowable.\n//they should be used without the preceding \"Math.\"\nvar MATH_FUNCS =\n[\n\t\"pow\",\n\t\"sqrt\",\n\t\"abs\",\n\t\"floor\",\n\t\"round\",\n\t\"ceil\",\n\t\"E\",\n\t\"PI\",\n\t\"sin\",\n\t\"cos\",\n\t\"tan\",\n\t\"asin\",\n\t\"acos\",\n\t\"atan\",\n\t\"atan2\",\n\t\"log\"\n];\n//Allow the 4 basic operations, parentheses and all numbers/decimals, as well\n//as 'x', for the variable usage.\nvar WHITELISTER = \"[01234567890\\\\.\\\\*\\\\-\\\\+\\\\/\\\\(\\\\)x ,]\";\n//add the math functions to the regex string.\nfor(var index = MATH_FUNCS.length - 1; index >= 0; --index)\n{\n\tWHITELISTER += \"|\" + MATH_FUNCS[index];\n}\n//create an actual regular expression object from the string\nWHITELISTER = new RegExp(WHITELISTER, \"g\");\n\n/**\n * Parses a string into a function for path following.\n * This involves whitelisting the string for safety, inserting \"Math.\" to math function\n * names, and using `new Function()` to generate a function.\n * @method PIXI.particles.PathParticle~parsePath\n * @private\n * @static\n * @param {String} pathString The string to parse.\n * @return {Function} The path function - takes x, outputs y.\n */\nvar parsePath = function(pathString)\n{\n\tvar matches = pathString.match(WHITELISTER);\n\tfor(var i = matches.length - 1; i >= 0; --i)\n\t{\n\t\tif(MATH_FUNCS.indexOf(matches[i]) >= 0)\n\t\t\tmatches[i] = \"Math.\" + matches[i];\n\t}\n\tpathString = matches.join(\"\");\n\treturn new Function(\"x\", \"return \"+ pathString + \";\");\n};\n\n/**\n * Updates the particle.\n * @method PIXI.particles.PathParticle#update\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\n */\np.update = function(delta)\n{\n\tvar lerp = this.Particle_update(delta);\n\t//if the particle died during the update, then don't bother\n\tif(lerp >= 0 && this.path)\n\t{\n\t\t//increase linear movement based on speed\n\t\tvar speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed;\n\t\tthis.movement += speed * delta;\n\t\t//set up the helper point for rotation\n\t\thelperPoint.x = this.movement;\n\t\thelperPoint.y = this.path(this.movement);\n\t\tParticleUtils.rotatePoint(this.initialRotation, helperPoint);\n\t\tthis.position.x = this.initialPosition.x + helperPoint.x;\n\t\tthis.position.y = this.initialPosition.y + helperPoint.y;\n\t}\n};\n\np.Particle_destroy = Particle.prototype.destroy;\n/**\n * Destroys the particle, removing references and preventing future use.\n * @method PIXI.particles.PathParticle#destroy\n */\np.destroy = function()\n{\n\tthis.Particle_destroy();\n\tthis.path = this.initialPosition = null;\n};\n\n/**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time. This just runs Particle.parseArt().\n * @method PIXI.particles.PathParticle.parseArt\n * @static\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\n * Any strings in the array will be converted to Textures via\n * Texture.fromImage().\n * @return {Array} The art, after any needed modifications.\n */\nPathParticle.parseArt = function(art)\n{\n\treturn Particle.parseArt(art);\n};\n\n/**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * PathParticle checks for the existence of path data, and parses the path data for use\n * by particle instances.\n * @method PIXI.particles.PathParticle.parseData\n * @static\n * @param {Object} extraData The extra data from the particle config.\n * @return {Object} The parsed extra data.\n */\nPathParticle.parseData = function(extraData)\n{\n\tvar output = {};\n\tif(extraData && extraData.path)\n\t{\n\t\ttry\n\t\t{\n\t\t\toutput.path = parsePath(extraData.path);\n\t\t}\n\t\tcatch(e)\n\t\t{\n\t\t\tif(ParticleUtils.verbose)\n\t\t\t\tconsole.error(\"PathParticle: error in parsing path expression\");\n\t\t\toutput.path = null;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(ParticleUtils.verbose)\n\t\t\tconsole.error(\"PathParticle requires a path string in extraData!\");\n\t\toutput.path = null;\n\t}\n\treturn output;\n};\n\nmodule.exports = PathParticle;","exports.ParticleUtils = require(\"./ParticleUtils.js\");\nexports.Particle = require(\"./Particle.js\");\nexports.Emitter = require(\"./Emitter.js\");\nexports.PathParticle = require(\"./PathParticle.js\");\nexports.AnimatedParticle = require(\"./AnimatedParticle.js\");\nrequire(\"./deprecation.js\");","\"use strict\";\n\n// Check for window, fallback to global\nvar global = typeof window !== 'undefined' ? window : GLOBAL;\n\n//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not\nif (!global.PIXI.particles) {\n\tglobal.PIXI.particles = {};\n}\n\n// Export for Node-compatible environments like Electron\nif (typeof module !== 'undefined' && module.exports)\n{\n\t// Attempt to require the pixi module\n\tif (typeof PIXI === 'undefined')\n\t{\n\t\t// Include the Pixi.js module\n\t\trequire('pixi.js');\n\t}\n\n\t// Export the module\n\tmodule.exports = global.PIXI.particles || particles;\n}\n// If we're in the browser make sure PIXI is available\nelse if (typeof PIXI === 'undefined')\n{\n\tthrow \"pixi-particles requires pixi.js to be loaded first\";\n}\n\n// get the library itself\nvar particles = require('./particles');\n\n// insert the lirbary into the particles namespace on PIXI\nfor (var prop in particles) {\n\tglobal.PIXI.particles[prop] = particles[prop];\n}"],"sourceRoot":"."} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","ts-dist/AnimatedParticle.js","ts-dist/Emitter.js","ts-dist/Particle.js","ts-dist/ParticleUtils.js","ts-dist/PathParticle.js","ts-dist/PropertyList.js","ts-dist/PropertyNode.js","ts-dist/particles.js","ts-dist"],"names":["f","exports","module","define","amd","g","window","global","self","this","pixiParticles","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","_dereq_","__extends","extendStatics","Object","setPrototypeOf","__proto__","Array","d","b","p","hasOwnProperty","__","constructor","prototype","create","defineProperty","value","Particle_1","Texture","PIXI","AnimatedParticle","_super","emitter","_this","textures","duration","framerate","elapsed","loop","init","Particle_init","maxLife","applyArt","art","update","delta","lerp","Particle_update","frame","texture","EMPTY","destroy","Particle_destroy","parseArt","data","output","tex","outTextures","outArr","j","push","fromImage","dupe","count","default","ParticleUtils_1","PropertyNode_1","ticker","shared","helperPoint","Point","Emitter","particleParent","particleImages","config","_particleConstructor","startAlpha","startSpeed","minimumSpeedMultiplier","acceleration","maxSpeed","NaN","startScale","minimumScaleMultiplier","startColor","minLifetime","maxLifetime","minStartRotation","maxStartRotation","noRotation","minRotationSpeed","maxRotationSpeed","particleBlendMode","customEase","extraData","_frequency","spawnChance","maxParticles","emitterLifetime","spawnPos","spawnType","_spawnFunc","spawnRect","spawnCircle","particlesPerWave","particleSpacing","angleStart","rotation","ownerPos","_prevEmitterPos","_prevPosIsValid","_posChanged","_parent","addAtBack","particleCount","_emit","_spawnTimer","_emitterLife","_activeParticlesFirst","_activeParticlesLast","_poolFirst","_origConfig","_origArt","_autoUpdate","_destroyWhenComplete","_completeCallback","parent","recycle","rotate","updateSpawnPos","updateOwnerPos","get","set","enumerable","configurable","cleanup","particle","next","isArray","slice","partClass","alpha","createList","speed","x","y","scale","color","startRotation","min","max","rotationSpeed","lifetime","getBlendMode","blendMode","ease","generateEase","parseData","_spawnRect","Rectangle","w","h","_spawnCircle","Circle","_spawnRing","minRadius","minR","_spawnBurst","_spawnPoint","frequency","pos","clone","emit","undefined","autoUpdate","prev","removeChild","newRot","diff","rotatePoint","resetPositionTracking","remove","add","playOnceAndDestroy","callback","playOnce","settings","TARGET_FPMS","prevX","prevY","curX","curY","Math","random","emitPosX","emitPosY","len","particleConstructor","floor","alphaList","reset","speedMultiplier","speedList","scaleMultiplier","scaleList","colorList","children","shift","pop","index","indexOf","splice","unshift","addChildAt","addChild","position","width","height","radius","angle","PropertyList_1","Sprite","Particle","anchor","velocity","age","_doAlpha","_doScale","_doSpeed","_doAcceleration","_doColor","_doNormalMovement","_oneOverLife","Sprite_destroy","kill","current","DEG_TO_RADS","tint","combineRGBComponents","visible","interpolate","normalize","scaleBy","currentSpeed","atan2","verbose","baseTexture","console","warn","BLEND_MODES","ParticleUtils","PI","sin","c","cos","xnew","ynew","point","oneOverLen","sqrt","hexToRGB","charAt","substr","parseInt","segments","qty","oneOverQty","time","cp","name","NORMAL","toUpperCase","replace","createSteppedGradient","list","numSteps","first","isStepped","currentNode","nextIndex","curVal","nextVal","MATH_FUNCS","WHITELISTER","RegExp","concat","join","parsePath","pathString","matches","match","Function","PathParticle","path","initialRotation","initialPosition","movement","error","intValueSimple","intColorSimple","intValueComplex","intColorComplex","intValueStepped","intColorStepped","PropertyList","isColor","PropertyNode","array","node","start","end","ParticleUtils_js_1","Particle_js_1","Emitter_js_1","PathParticle_js_1","AnimatedParticle_js_1","particles","prop"],"mappings":";;;;;;;CAAA,SAAAA,GAAA,GAAA,gBAAAC,UAAA,mBAAAC,QAAAA,OAAAD,QAAAD,QAAA,IAAA,kBAAAG,SAAAA,OAAAC,IAAAD,UAAAH,OAAA,CAAA,GAAAK,EAAAA,GAAA,mBAAAC,QAAAA,OAAA,mBAAAC,QAAAA,OAAA,mBAAAC,MAAAA,KAAAC,KAAAJ,EAAAK,cAAAV,MAAA,WAAA,MAAA,YAAA,QAAAW,GAAAC,EAAAC,EAAAC,GAAA,QAAAC,GAAAC,EAAAC,GAAA,IAAAJ,EAAAG,GAAA,CAAA,IAAAJ,EAAAI,GAAA,CAAA,GAAAE,GAAA,kBAAAC,UAAAA,OAAA,KAAAF,GAAAC,EAAA,MAAAA,GAAAF,GAAA,EAAA,IAAAI,EAAA,MAAAA,GAAAJ,GAAA,EAAA,IAAAhB,GAAA,GAAAqB,OAAA,uBAAAL,EAAA,IAAA,MAAAhB,GAAAsB,KAAA,mBAAAtB,EAAA,GAAAuB,GAAAV,EAAAG,IAAAf,WAAAW,GAAAI,GAAA,GAAAQ,KAAAD,EAAAtB,QAAA,SAAAU,GAAA,GAAAE,GAAAD,EAAAI,GAAA,GAAAL,EAAA,OAAAI,GAAAF,GAAAF,IAAAY,EAAAA,EAAAtB,QAAAU,EAAAC,EAAAC,EAAAC,GAAA,MAAAD,GAAAG,GAAAf,QAAA,IAAA,GAAAmB,GAAA,kBAAAD,UAAAA,QAAAH,EAAA,EAAAA,EAAAF,EAAAW,OAAAT,IAAAD,EAAAD,EAAAE,GAAA,OAAAD,GAAA,MAAAJ,OAAAe,GAAA,SAAAC,EAAAzB,EAAAD,GCAA,YACA,IAAA2B,GAAAnB,MAAAA,KAAAmB,WAAA,WACA,GAAAC,GAAAC,OAAAC,iBACAC,uBAAAC,QAAA,SAAAC,EAAAC,GAAAD,EAAAF,UAAAG,IACA,SAAAD,EAAAC,GAAA,IAAA,GAAAC,KAAAD,GAAAA,EAAAE,eAAAD,KAAAF,EAAAE,GAAAD,EAAAC,IACA,OAAA,UAAAF,EAAAC,GAEA,QAAAG,KAAA7B,KAAA8B,YAAAL,EADAL,EAAAK,EAAAC,GAEAD,EAAAM,UAAA,OAAAL,EAAAL,OAAAW,OAAAN,IAAAG,EAAAE,UAAAL,EAAAK,UAAA,GAAAF,OAGAR,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAC,GAAAjB,EAAA,cACAkB,EAAAC,KAAAD,QAoCAE,EAAA,SAAAC,GAEA,QAAAD,GAAAE,GACA,GAAAC,GAAAF,EAAAxB,KAAAf,KAAAwC,IAAAxC,IAMA,OALAyC,GAAAC,SAAA,KACAD,EAAAE,SAAA,EACAF,EAAAG,UAAA,EACAH,EAAAI,QAAA,EACAJ,EAAAK,MAAA,EACAL,EA4GA,MApHAtB,GAAAmB,EAAAC,GAeAD,EAAAP,UAAAgB,KAAA,WACA/C,KAAAgD,gBACAhD,KAAA6C,QAAA,EAEA7C,KAAA4C,UAAA,IACA5C,KAAA2C,SAAA3C,KAAAiD,QACAjD,KAAA4C,UAAA5C,KAAA0C,SAAA1B,OAAAhB,KAAA2C,WAQAL,EAAAP,UAAAmB,SAAA,SAAAC,GACAnD,KAAA0C,SAAAS,EAAAT,SACA1C,KAAA4C,UAAAO,EAAAP,UACA5C,KAAA2C,SAAAQ,EAAAR,SACA3C,KAAA8C,KAAAK,EAAAL,MAOAR,EAAAP,UAAAqB,OAAA,SAAAC,GACA,GAAAC,GAAAtD,KAAAuD,gBAAAF,EAEA,IAAAC,GAAA,EAAA,CACAtD,KAAA6C,SAAAQ,EACArD,KAAA6C,QAAA7C,KAAA2C,WAEA3C,KAAA8C,KACA9C,KAAA6C,QAAA7C,KAAA6C,QAAA7C,KAAA2C,SAEA3C,KAAA6C,QAAA7C,KAAA2C,SAAA,KAEA,IAAAa,GAAAxD,KAAA6C,QAAA7C,KAAA4C,UAAA,KAAA,CACA5C,MAAAyD,QAAAzD,KAAA0C,SAAAc,IAAAnB,KAAAD,QAAAsB,MAEA,MAAAJ,IAMAhB,EAAAP,UAAA4B,QAAA,WACA3D,KAAA4D,mBACA5D,KAAA0C,SAAA,MAUAJ,EAAAuB,SAAA,SAAAV,GAGA,IAAA,GAFAW,GAAAC,EAAArB,EAAAsB,EAAAC,EACAC,KACAvD,EAAA,EAAAA,EAAAwC,EAAAnC,SAAAL,EAAA,CACAmD,EAAAX,EAAAxC,GACAuD,EAAAvD,GAAAoD,KACAA,EAAArB,SAAAuB,KACAvB,EAAAoB,EAAApB,QACA,KAAA,GAAAyB,GAAA,EAAAA,EAAAzB,EAAA1B,SAAAmD,EAEA,GAAA,iBADAH,EAAAtB,EAAAyB,IAEAF,EAAAG,KAAAhC,EAAAiC,UAAAL,QACA,IAAAA,YAAA5B,GACA6B,EAAAG,KAAAJ,OACA,CACA,GAAAM,GAAAN,EAAAO,OAAA,CAKA,KAHAP,EADA,gBAAAA,GAAAP,QACArB,EAAAiC,UAAAL,EAAAP,SAEAO,EAAAP,QACAa,EAAA,IAAAA,EACAL,EAAAG,KAAAJ,GAKA,aAAAF,EAAAlB,WAEAmB,EAAAnB,WAAA,EACAmB,EAAApB,SAAA,EACAoB,EAAAjB,MAAA,IAIAiB,EAAAjB,OAAAgB,EAAAhB,KAEAiB,EAAAnB,UAAAkB,EAAAlB,UAAA,EAAAkB,EAAAlB,UAAA,GAEAmB,EAAApB,SAAAsB,EAAAjD,OAAA+C,EAAAnB,WAGA,MAAAsB,IAEA5B,GACAH,EAAAqC,QACAhF,GAAAgF,QAAAlC,wCCxKA,YACAjB,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAuC,GAAAvD,EAAA,mBACAiB,EAAAjB,EAAA,cACAwD,EAAAxD,EAAA,kBACAyD,EAAAtC,KAAAsC,OAAAC,OACAC,EAAA,GAAAxC,MAAAyC,MAiBAC,EAAA,WACA,QAAAA,GAAAC,EAAAC,EAAAC,GACAlF,KAAAmF,qBAAAhD,EAAAqC,QAEAxE,KAAAiF,eAAA,KACAjF,KAAAoF,WAAA,KACApF,KAAAqF,WAAA,KACArF,KAAAsF,uBAAA,EACAtF,KAAAuF,aAAA,KACAvF,KAAAwF,SAAAC,IACAzF,KAAA0F,WAAA,KACA1F,KAAA2F,uBAAA,EACA3F,KAAA4F,WAAA,KACA5F,KAAA6F,YAAA,EACA7F,KAAA8F,YAAA,EACA9F,KAAA+F,iBAAA,EACA/F,KAAAgG,iBAAA,EACAhG,KAAAiG,YAAA,EACAjG,KAAAkG,iBAAA,EACAlG,KAAAmG,iBAAA,EACAnG,KAAAoG,kBAAA,EACApG,KAAAqG,WAAA,KACArG,KAAAsG,UAAA,KAEAtG,KAAAuG,WAAA,EACAvG,KAAAwG,YAAA,EACAxG,KAAAyG,aAAA,IACAzG,KAAA0G,iBAAA,EACA1G,KAAA2G,SAAA,KACA3G,KAAA4G,UAAA,KACA5G,KAAA6G,WAAA,KACA7G,KAAA8G,UAAA,KACA9G,KAAA+G,YAAA,KACA/G,KAAAgH,iBAAA,EACAhH,KAAAiH,gBAAA,EACAjH,KAAAkH,WAAA,EAEAlH,KAAAmH,SAAA,EACAnH,KAAAoH,SAAA,KACApH,KAAAqH,gBAAA,KACArH,KAAAsH,iBAAA,EACAtH,KAAAuH,aAAA,EACAvH,KAAAwH,QAAA,KACAxH,KAAAyH,WAAA,EACAzH,KAAA0H,cAAA,EACA1H,KAAA2H,OAAA,EACA3H,KAAA4H,YAAA,EACA5H,KAAA6H,cAAA,EACA7H,KAAA8H,sBAAA,KACA9H,KAAA+H,qBAAA,KACA/H,KAAAgI,WAAA,KACAhI,KAAAiI,YAAA,KACAjI,KAAAkI,SAAA,KACAlI,KAAAmI,aAAA,EACAnI,KAAAoI,sBAAA,EACApI,KAAAqI,kBAAA,KAEArI,KAAAsI,OAAAtD,EACAC,GAAAC,GACAlF,KAAA+C,KAAAkC,EAAAC,GAEAlF,KAAAuI,QAAAvI,KAAAuI,QACAvI,KAAAoD,OAAApD,KAAAoD,OACApD,KAAAwI,OAAAxI,KAAAwI,OACAxI,KAAAyI,eAAAzI,KAAAyI,eACAzI,KAAA0I,eAAA1I,KAAA0I,eA0sBA,MAxsBArH,QAAAY,eAAA8C,EAAAhD,UAAA,aAMA4G,IAAA,WAAA,MAAA3I,MAAAuG,YACAqC,IAAA,SAAA1G,GAGAlC,KAAAuG,WADA,gBAAArE,IAAAA,EAAA,EACAA,EAEA,GAEA2G,YAAA,EACAC,cAAA,IAEAzH,OAAAY,eAAA8C,EAAAhD,UAAA,uBAOA4G,IAAA,WAAA,MAAA3I,MAAAmF,sBACAyD,IAAA,SAAA1G,GACA,GAAAA,GAAAlC,KAAAmF,qBAAA,CACAnF,KAAAmF,qBAAAjD,EAEAlC,KAAA+I,SAEA,KAAA,GAAAC,GAAAhJ,KAAAgI,WAAAgB,EAAAA,EAAAA,EAAAC,KACAD,EAAArF,SAEA3D,MAAAgI,WAAA,KAEAhI,KAAAiI,aAAAjI,KAAAkI,UACAlI,KAAA+C,KAAA/C,KAAAkI,SAAAlI,KAAAiI,eAGAY,YAAA,EACAC,cAAA,IAEAzH,OAAAY,eAAA8C,EAAAhD,UAAA,UAKA4G,IAAA,WAAA,MAAA3I,MAAAwH,SACAoB,IAAA,SAAA1G,GACAlC,KAAA+I,UACA/I,KAAAwH,QAAAtF,GAEA2G,YAAA,EACAC,cAAA,IAQA/D,EAAAhD,UAAAgB,KAAA,SAAAI,EAAA+B,GACA,GAAA/B,GAAA+B,EAAA,CAGAlF,KAAA+I,UAGA/I,KAAAiI,YAAA/C,EACAlF,KAAAkI,SAAA/E,EAEAA,EAAA3B,MAAA0H,QAAA/F,GAAAA,EAAAgG,SAAAhG,EAEA,IAAAiG,GAAApJ,KAAAmF,oBACAnF,MAAAiF,eAAAmE,EAAAvF,SAAAuF,EAAAvF,SAAAV,GAAAA,EAKA+B,EAAAmE,MACArJ,KAAAoF,WAAAV,EAAAF,QAAA8E,WAAApE,EAAAmE,OAGArJ,KAAAoF,WAAA,GAAAV,GAAAF,QAAA,EAAA,GAEAU,EAAAqE,OACAvJ,KAAAqF,WAAAX,EAAAF,QAAA8E,WAAApE,EAAAqE,OACAvJ,KAAAsF,uBAAAJ,EAAAqE,MAAAjE,wBAAA,IAGAtF,KAAAsF,uBAAA,EACAtF,KAAAqF,WAAA,GAAAX,GAAAF,QAAA,EAAA,GAGA,IAAAe,GAAAL,EAAAK,YACAA,KAAAA,EAAAiE,GAAAjE,EAAAkE,IAEAzJ,KAAAqF,WAAA4D,KAAA,KACAjJ,KAAAuF,aAAA,GAAAlD,MAAAyC,MAAAS,EAAAiE,EAAAjE,EAAAkE,GACAzJ,KAAAwF,SAAAN,EAAAM,UAAAC,KAGAzF,KAAAuF,aAAA,GAAAlD,MAAAyC,MAEAI,EAAAwE,OACA1J,KAAA0F,WAAAhB,EAAAF,QAAA8E,WAAApE,EAAAwE,OACA1J,KAAA2F,uBAAAT,EAAAwE,MAAA/D,wBAAA,IAGA3F,KAAA0F,WAAA,GAAAhB,GAAAF,QAAA,EAAA,GACAxE,KAAA2F,uBAAA,GAGAT,EAAAyE,MACA3J,KAAA4F,WAAAlB,EAAAF,QAAA8E,WAAApE,EAAAyE,OAGA3J,KAAA4F,WAAA,GAAAlB,GAAAF,SAAAnE,EAAA,IAAAT,EAAA,IAAA8B,EAAA,KAAA,GAGAwD,EAAA0E,eACA5J,KAAA+F,iBAAAb,EAAA0E,cAAAC,IACA7J,KAAAgG,iBAAAd,EAAA0E,cAAAE,KAGA9J,KAAA+F,iBAAA/F,KAAAgG,iBAAA,EACAd,EAAAe,aACAjG,KAAA+F,kBAAA/F,KAAAgG,kBACAhG,KAAAiG,aAAAf,EAAAe,WAGAjG,KAAAiG,YAAA,EAEAf,EAAA6E,eACA/J,KAAAkG,iBAAAhB,EAAA6E,cAAAF,IACA7J,KAAAmG,iBAAAjB,EAAA6E,cAAAD,KAGA9J,KAAAkG,iBAAAlG,KAAAmG,iBAAA,EAEAnG,KAAA6F,YAAAX,EAAA8E,SAAAH,IACA7J,KAAA8F,YAAAZ,EAAA8E,SAAAF,IAEA9J,KAAAoG,kBAAA3B,EAAAD,QAAAyF,aAAA/E,EAAAgF,WAEAhF,EAAAiF,KACAnK,KAAAqG,WAAA,kBAAAnB,GAAAiF,KACAjF,EAAAiF,KACA1F,EAAAD,QAAA4F,aAAAlF,EAAAiF,MAGAnK,KAAAqG,WAAA,KAEA+C,EAAAiB,UACArK,KAAAsG,UAAA8C,EAAAiB,UAAAnF,EAAAoB,WAEAtG,KAAAsG,UAAApB,EAAAoB,WAAA,KAKAtG,KAAA8G,UAAA9G,KAAA+G,YAAA,KACA/G,KAAAgH,iBAAA,EACA9B,EAAA8B,kBAAA9B,EAAA8B,iBAAA,IACAhH,KAAAgH,iBAAA9B,EAAA8B,kBACAhH,KAAAiH,gBAAA,EACAjH,KAAAkH,WAAA,CACA,IAAAH,EAEA,QAAA7B,EAAA0B,WACA,IAAA,OACA5G,KAAA4G,UAAA,OACA5G,KAAA6G,WAAA7G,KAAAsK,UACA,IAAAxD,GAAA5B,EAAA4B,SACA9G,MAAA8G,UAAA,GAAAzE,MAAAkI,UAAAzD,EAAA0C,EAAA1C,EAAA2C,EAAA3C,EAAA0D,EAAA1D,EAAA2D,EACA,MACA,KAAA,SACAzK,KAAA4G,UAAA,SACA5G,KAAA6G,WAAA7G,KAAA0K,aACA3D,EAAA7B,EAAA6B,YACA/G,KAAA+G,YAAA,GAAA1E,MAAAsI,OAAA5D,EAAAyC,EAAAzC,EAAA0C,EAAA1C,EAAA1G,EACA,MACA,KAAA,OACAL,KAAA4G,UAAA,OACA5G,KAAA6G,WAAA7G,KAAA4K,WACA7D,EAAA7B,EAAA6B,YACA/G,KAAA+G,YAAA,GAAA1E,MAAAsI,OAAA5D,EAAAyC,EAAAzC,EAAA0C,EAAA1C,EAAA1G,GACAL,KAAA+G,YAAA8D,UAAA9D,EAAA+D,IACA,MACA,KAAA,QACA9K,KAAA4G,UAAA,QACA5G,KAAA6G,WAAA7G,KAAA+K,YACA/K,KAAAiH,gBAAA/B,EAAA+B,gBACAjH,KAAAkH,WAAAhC,EAAAgC,WAAAhC,EAAAgC,WAAA,CACA,MACA,KAAA,QAIA,QACAlH,KAAA4G,UAAA,QACA5G,KAAA6G,WAAA7G,KAAAgL,YAIAhL,KAAAiL,UAAA/F,EAAA+F,UACAjL,KAAAwG,YAAA,gBAAAtB,GAAAsB,aAAAtB,EAAAsB,YAAA,EAAAtB,EAAAsB,YAAA,EAEAxG,KAAA0G,gBAAAxB,EAAAwB,kBAAA,EAEA1G,KAAAyG,aAAAvB,EAAAuB,aAAA,EAAAvB,EAAAuB,aAAA,IAEAzG,KAAAyH,YAAAvC,EAAAuC,UAEAzH,KAAAmH,SAAA,EACAnH,KAAAoH,SAAA,GAAA/E,MAAAyC,MACA9E,KAAA2G,SAAA,GAAAtE,MAAAyC,MAAAI,EAAAgG,IAAA1B,EAAAtE,EAAAgG,IAAAzB,GACAzJ,KAAAqH,gBAAArH,KAAA2G,SAAAwE,QAEAnL,KAAAsH,iBAAA,EAEAtH,KAAA4H,YAAA,EACA5H,KAAAoL,SAAAC,KAAAnG,EAAAkG,QAAAlG,EAAAkG,KACApL,KAAAsL,eAAAD,KAAAnG,EAAAoG,cAAApG,EAAAoG,aAQAvG,EAAAhD,UAAAwG,QAAA,SAAAS,GACAA,EAAAC,OACAD,EAAAC,KAAAsC,KAAAvC,EAAAuC,MACAvC,EAAAuC,OACAvC,EAAAuC,KAAAtC,KAAAD,EAAAC,MACAD,GAAAhJ,KAAA+H,uBACA/H,KAAA+H,qBAAAiB,EAAAuC,MACAvC,GAAAhJ,KAAA8H,wBACA9H,KAAA8H,sBAAAkB,EAAAC,MAEAD,EAAAuC,KAAA,KACAvC,EAAAC,KAAAjJ,KAAAgI,WACAhI,KAAAgI,WAAAgB,EAEAA,EAAAV,QACAU,EAAAV,OAAAkD,YAAAxC,KAEAhJ,KAAA0H,eAOA3C,EAAAhD,UAAAyG,OAAA,SAAAiD,GACA,GAAAzL,KAAAmH,UAAAsE,EAAA,CAGA,GAAAC,GAAAD,EAAAzL,KAAAmH,QACAnH,MAAAmH,SAAAsE,EAEAhH,EAAAD,QAAAmH,YAAAD,EAAA1L,KAAA2G,UAEA3G,KAAAuH,aAAA,IAQAxC,EAAAhD,UAAA0G,eAAA,SAAAe,EAAAC,GACAzJ,KAAAuH,aAAA,EACAvH,KAAA2G,SAAA6C,EAAAA,EACAxJ,KAAA2G,SAAA8C,EAAAA,GASA1E,EAAAhD,UAAA2G,eAAA,SAAAc,EAAAC,GACAzJ,KAAAuH,aAAA,EACAvH,KAAAoH,SAAAoC,EAAAA,EACAxJ,KAAAoH,SAAAqC,EAAAA,GAQA1E,EAAAhD,UAAA6J,sBAAA,WACA5L,KAAAsH,iBAAA,GAEAjG,OAAAY,eAAA8C,EAAAhD,UAAA,QAMA4G,IAAA,WAAA,MAAA3I,MAAA2H,OACAiB,IAAA,SAAA1G,GACAlC,KAAA2H,QAAAzF,EACAlC,KAAA6H,aAAA7H,KAAA0G,iBAEAmC,YAAA,EACAC,cAAA,IAGAzH,OAAAY,eAAA8C,EAAAhD,UAAA,cAMA4G,IAAA,WAAA,MAAA3I,MAAAmI,aACAS,IAAA,SAAA1G,GACAlC,KAAAmI,cAAAjG,EACAyC,EAAAkH,OAAA7L,KAAAoD,OAAApD,OAEAA,KAAAmI,aAAAjG,GACAyC,EAAAmH,IAAA9L,KAAAoD,OAAApD,MAEAA,KAAAmI,cAAAjG,GAEA2G,YAAA,EACAC,cAAA,IAQA/D,EAAAhD,UAAAgK,mBAAA,SAAAC,GACAhM,KAAAsL,YAAA,EACAtL,KAAAoL,MAAA,EACApL,KAAAoI,sBAAA,EACApI,KAAAqI,kBAAA2D,GAOAjH,EAAAhD,UAAAkK,SAAA,SAAAD,GACAhM,KAAAoL,MAAA,EACApL,KAAAqI,kBAAA2D,GAOAjH,EAAAhD,UAAAqB,OAAA,SAAAC,GAMA,GALArD,KAAAmI,cACA9E,EAAAA,EAAAhB,KAAA6J,SAAAC,YAAA,KAIAnM,KAAAwH,QAAA,CAGA,GAAA7G,GAAAqI,EAAAC,CACA,KAAAD,EAAAhJ,KAAA8H,sBAAAkB,EAAAA,EAAAC,EACAA,EAAAD,EAAAC,KACAD,EAAA5F,OAAAC,EAEA,IAAA+I,GAAAC,CAEArM,MAAAsH,kBACA8E,EAAApM,KAAAqH,gBAAAmC,EACA6C,EAAArM,KAAAqH,gBAAAoC,EAGA,IAAA6C,GAAAtM,KAAAoH,SAAAoC,EAAAxJ,KAAA2G,SAAA6C,EACA+C,EAAAvM,KAAAoH,SAAAqC,EAAAzJ,KAAA2G,SAAA8C,CAEA,IAAAzJ,KAAA2H,MAIA,IAFA3H,KAAA4H,aAAAvE,EAEArD,KAAA4H,aAAA,GAAA,CAEA,GAAA5H,KAAA6H,aAAA,IACA7H,KAAA6H,cAAA7H,KAAAuG,WACAvG,KAAA6H,cAAA,GAAA,CACA7H,KAAA4H,YAAA,EACA5H,KAAA6H,aAAA,EACA7H,KAAAoL,MAAA,CACA,OAIA,GAAApL,KAAA0H,eAAA1H,KAAAyG,aACAzG,KAAA4H,aAAA5H,KAAAuG,eADA,CAKA,GAAAyD,OAAA,EAMA,IAJAA,EADAhK,KAAA6F,aAAA7F,KAAA8F,YACA9F,KAAA6F,YAEA2G,KAAAC,UAAAzM,KAAA8F,YAAA9F,KAAA6F,aAAA7F,KAAA6F,aAEA7F,KAAA4H,YAAAoC,EAAA,CAGA,GAAA0C,OAAA,GAAAC,MAAA,EACA,IAAA3M,KAAAsH,iBAAAtH,KAAAuH,YAAA,CAEA,GAAAjE,GAAA,EAAAtD,KAAA4H,YAAAvE,CACAqJ,IAAAJ,EAAAF,GAAA9I,EAAA8I,EACAO,GAAAJ,EAAAF,GAAA/I,EAAA+I,MAGAK,GAAAJ,EACAK,EAAAJ,CAGA5L,GAAA,CACA,KAAA,GAAAiM,GAAAJ,KAAA3C,IAAA7J,KAAAgH,iBAAAhH,KAAAyG,aAAAzG,KAAA0H,eAAA/G,EAAAiM,IAAAjM,EAEA,KAAAX,KAAAwG,YAAA,GAAAgG,KAAAC,UAAAzM,KAAAwG,aAAA,CAGA,GAAA7E,OAAA,EAqDA,IApDA3B,KAAAgI,YACArG,EAAA3B,KAAAgI,WACAhI,KAAAgI,WAAAhI,KAAAgI,WAAAiB,KACAtH,EAAAsH,KAAA,MAGAtH,EAAA,GAAA3B,MAAA6M,oBAAA7M,MAGAA,KAAAiF,eAAAjE,OAAA,EACAW,EAAAuB,SAAAlD,KAAAiF,eAAAuH,KAAAM,MAAAN,KAAAC,SAAAzM,KAAAiF,eAAAjE,UAKAW,EAAAuB,SAAAlD,KAAAiF,eAAA,IAGAtD,EAAAoL,UAAAC,MAAAhN,KAAAoF,YACA,GAAApF,KAAAsF,yBACA3D,EAAAsL,gBAAAT,KAAAC,UAAA,EAAAzM,KAAAsF,wBAAAtF,KAAAsF,wBAEA3D,EAAAuL,UAAAF,MAAAhN,KAAAqF,YACA1D,EAAA4D,aAAAiE,EAAAxJ,KAAAuF,aAAAiE,EACA7H,EAAA4D,aAAAkE,EAAAzJ,KAAAuF,aAAAkE,EACA9H,EAAA6D,SAAAxF,KAAAwF,SACA,GAAAxF,KAAA2F,yBACAhE,EAAAwL,gBAAAX,KAAAC,UAAA,EAAAzM,KAAA2F,wBAAA3F,KAAA2F,wBAEAhE,EAAAyL,UAAAJ,MAAAhN,KAAA0F,YACA/D,EAAA0L,UAAAL,MAAAhN,KAAA4F,YAEA5F,KAAAkG,kBAAAlG,KAAAmG,iBACAxE,EAAAoI,cAAA/J,KAAAkG,iBAEAvE,EAAAoI,cAAAyC,KAAAC,UAAAzM,KAAAmG,iBAAAnG,KAAAkG,kBAAAlG,KAAAkG,iBACAvE,EAAAsE,WAAAjG,KAAAiG,WAEAtE,EAAAsB,QAAA+G,EAEArI,EAAAuI,UAAAlK,KAAAoG,kBAEAzE,EAAAwI,KAAAnK,KAAAqG,WAEA1E,EAAA2E,UAAAtG,KAAAsG,UAEAtG,KAAA6G,WAAAlF,EAAA+K,EAAAC,EAAAhM,GAEAgB,EAAAoB,OAEApB,EAAAyB,QAAApD,KAAA4H,aAEAjG,EAAA2G,OAMA,CAGA,GAAAgF,GAAAtN,KAAAwH,QAAA8F,QAEA,IAAAA,EAAA,IAAA3L,EACA2L,EAAAC,YACA,IAAAD,EAAAA,EAAAtM,OAAA,IAAAW,EACA2L,EAAAE,UACA,CACA,GAAAC,GAAAH,EAAAI,QAAA/L,EACA2L,GAAAK,OAAAF,EAAA,GAEAzN,KAAAyH,UACA6F,EAAAM,QAAAjM,GAEA2L,EAAAlJ,KAAAzC,OArBA3B,MAAAyH,UACAzH,KAAAwH,QAAAqG,WAAAlM,EAAA,GAEA3B,KAAAwH,QAAAsG,SAAAnM,EAqBA3B,MAAA+H,sBACA/H,KAAA+H,qBAAAkB,KAAAtH,EACAA,EAAA4J,KAAAvL,KAAA+H,qBACA/H,KAAA+H,qBAAApG,GAGA3B,KAAA+H,qBAAA/H,KAAA8H,sBAAAnG,IAEA3B,KAAA0H,eAIA1H,KAAA4H,aAAA5H,KAAAuG,YAIAvG,KAAAuH,cACAvH,KAAAqH,gBAAAmC,EAAA8C,EACAtM,KAAAqH,gBAAAoC,EAAA8C,EACAvM,KAAAsH,iBAAA,EACAtH,KAAAuH,aAAA,GAGAvH,KAAA2H,OAAA3H,KAAA8H,wBACA9H,KAAAqI,mBACArI,KAAAqI,oBAEArI,KAAAoI,sBACApI,KAAA2D,aAaAoB,EAAAhD,UAAAiJ,YAAA,SAAArJ,EAAA+K,EAAAC,GAGA3M,KAAA+F,kBAAA/F,KAAAgG,iBACArE,EAAAwF,SAAAnH,KAAA+F,iBAAA/F,KAAAmH,SAEAxF,EAAAwF,SAAAqF,KAAAC,UAAAzM,KAAAgG,iBAAAhG,KAAA+F,kBAAA/F,KAAA+F,iBAAA/F,KAAAmH,SAEAxF,EAAAoM,SAAAvE,EAAAkD,EACA/K,EAAAoM,SAAAtE,EAAAkD,GAWA5H,EAAAhD,UAAAuI,WAAA,SAAA3I,EAAA+K,EAAAC,GAGA3M,KAAA+F,kBAAA/F,KAAAgG,iBACArE,EAAAwF,SAAAnH,KAAA+F,iBAAA/F,KAAAmH,SAEAxF,EAAAwF,SAAAqF,KAAAC,UAAAzM,KAAAgG,iBAAAhG,KAAA+F,kBAAA/F,KAAA+F,iBAAA/F,KAAAmH,SAEAtC,EAAA2E,EAAAgD,KAAAC,SAAAzM,KAAA8G,UAAAkH,MAAAhO,KAAA8G,UAAA0C,EACA3E,EAAA4E,EAAA+C,KAAAC,SAAAzM,KAAA8G,UAAAmH,OAAAjO,KAAA8G,UAAA2C,EACA,IAAAzJ,KAAAmH,UACA1C,EAAAD,QAAAmH,YAAA3L,KAAAmH,SAAAtC,GACAlD,EAAAoM,SAAAvE,EAAAkD,EAAA7H,EAAA2E,EACA7H,EAAAoM,SAAAtE,EAAAkD,EAAA9H,EAAA4E,GAWA1E,EAAAhD,UAAA2I,aAAA,SAAA/I,EAAA+K,EAAAC,GAGA3M,KAAA+F,kBAAA/F,KAAAgG,iBACArE,EAAAwF,SAAAnH,KAAA+F,iBAAA/F,KAAAmH,SAEAxF,EAAAwF,SAAAqF,KAAAC,UAAAzM,KAAAgG,iBAAAhG,KAAA+F,kBACA/F,KAAA+F,iBAAA/F,KAAAmH,SAEAtC,EAAA2E,EAAAgD,KAAAC,SAAAzM,KAAA+G,YAAAmH,OACArJ,EAAA4E,EAAA,EAEAhF,EAAAD,QAAAmH,YAAA,IAAAa,KAAAC,SAAA5H,GAEAA,EAAA2E,GAAAxJ,KAAA+G,YAAAyC,EACA3E,EAAA4E,GAAAzJ,KAAA+G,YAAA0C,EAEA,IAAAzJ,KAAAmH,UACA1C,EAAAD,QAAAmH,YAAA3L,KAAAmH,SAAAtC,GAEAlD,EAAAoM,SAAAvE,EAAAkD,EAAA7H,EAAA2E,EACA7H,EAAAoM,SAAAtE,EAAAkD,EAAA9H,EAAA4E,GAWA1E,EAAAhD,UAAA6I,WAAA,SAAAjJ,EAAA+K,EAAAC,GACA,GAAA5F,GAAA/G,KAAA+G,WAGA/G,MAAA+F,kBAAA/F,KAAAgG,iBACArE,EAAAwF,SAAAnH,KAAA+F,iBAAA/F,KAAAmH,SAEAxF,EAAAwF,SAAAqF,KAAAC,UAAAzM,KAAAgG,iBAAAhG,KAAA+F,kBACA/F,KAAA+F,iBAAA/F,KAAAmH,SAEAJ,EAAA8D,WAAA9D,EAAAmH,OACArJ,EAAA2E,EAAAgD,KAAAC,UAAA1F,EAAAmH,OAAAnH,EAAA8D,WACA9D,EAAA8D,UAGAhG,EAAA2E,EAAAzC,EAAAmH,OACArJ,EAAA4E,EAAA,CAEA,IAAA0E,GAAA,IAAA3B,KAAAC,QACA9K,GAAAwF,UAAAgH,EACA1J,EAAAD,QAAAmH,YAAAwC,EAAAtJ,GAEAA,EAAA2E,GAAAxJ,KAAA+G,YAAAyC,EACA3E,EAAA4E,GAAAzJ,KAAA+G,YAAA0C,EAEA,IAAAzJ,KAAAmH,UACA1C,EAAAD,QAAAmH,YAAA3L,KAAAmH,SAAAtC,GAEAlD,EAAAoM,SAAAvE,EAAAkD,EAAA7H,EAAA2E,EACA7H,EAAAoM,SAAAtE,EAAAkD,EAAA9H,EAAA4E,GAWA1E,EAAAhD,UAAAgJ,YAAA,SAAApJ,EAAA+K,EAAAC,EAAAhM,GAGA,IAAAX,KAAAiH,gBACAtF,EAAAwF,SAAA,IAAAqF,KAAAC,SAEA9K,EAAAwF,SAAAnH,KAAAkH,WAAAlH,KAAAiH,gBAAAtG,EAAAX,KAAAmH,SAEAxF,EAAAoM,SAAAvE,EAAAkD,EACA/K,EAAAoM,SAAAtE,EAAAkD,GAMA5H,EAAAhD,UAAAgH,QAAA,WACA,GAAAC,GAAAC,CACA,KAAAD,EAAAhJ,KAAA8H,sBAAAkB,EAAAA,EAAAC,EACAA,EAAAD,EAAAC,KACAjJ,KAAAuI,QAAAS,GACAA,EAAAV,QACAU,EAAAV,OAAAkD,YAAAxC,EAEAhJ,MAAA8H,sBAAA9H,KAAA+H,qBAAA,KACA/H,KAAA0H,cAAA,GAMA3C,EAAAhD,UAAA4B,QAAA,WAEA3D,KAAAsL,YAAA,EAEAtL,KAAA+I,SAGA,KAAA,GADAE,GACAD,EAAAhJ,KAAAgI,WAAAgB,EAAAA,EAAAC,EAEAA,EAAAD,EAAAC,KACAD,EAAArF,SAEA3D,MAAAgI,WAAAhI,KAAAwH,QAAAxH,KAAAiF,eAAAjF,KAAA2G,SAAA3G,KAAAoH,SACApH,KAAA4F,WAAA5F,KAAA0F,WAAA1F,KAAAoF,WAAApF,KAAAqF,WACArF,KAAAqG,WAAArG,KAAAqI,kBAAA,MAEAtD,IAEAvF,GAAAgF,QAAAO,+ECpyBA,YACA,IAAA5D,GAAAnB,MAAAA,KAAAmB,WAAA,WACA,GAAAC,GAAAC,OAAAC,iBACAC,uBAAAC,QAAA,SAAAC,EAAAC,GAAAD,EAAAF,UAAAG,IACA,SAAAD,EAAAC,GAAA,IAAA,GAAAC,KAAAD,GAAAA,EAAAE,eAAAD,KAAAF,EAAAE,GAAAD,EAAAC,IACA,OAAA,UAAAF,EAAAC,GAEA,QAAAG,KAAA7B,KAAA8B,YAAAL,EADAL,EAAAK,EAAAC,GAEAD,EAAAM,UAAA,OAAAL,EAAAL,OAAAW,OAAAN,IAAAG,EAAAE,UAAAL,EAAAK,UAAA,GAAAF,OAGAR,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAuC,GAAAvD,EAAA,mBACAkN,EAAAlN,EAAA,kBACAmN,EAAAhM,KAAAgM,OASAC,EAAA,SAAA/L,GAEA,QAAA+L,GAAA9L,GACA,GAAAC,GAGAF,EAAAxB,KAAAf,OAAAA,IAwGA,OAvGAyC,GAAAD,QAAAA,EAEAC,EAAA8L,OAAA/E,EAAA/G,EAAA8L,OAAA9E,EAAA,GACAhH,EAAA+L,SAAA,GAAAnM,MAAAyC,MACArC,EAAAQ,QAAA,EACAR,EAAAgM,IAAA,EACAhM,EAAA0H,KAAA,KACA1H,EAAA6D,UAAA,KACA7D,EAAAsK,UAAA,GAAAqB,GAAA5J,QACA/B,EAAAyK,UAAA,GAAAkB,GAAA5J,QACA/B,EAAAwK,gBAAA,EAKAxK,EAAA8C,aAAA,GAAAlD,MAAAyC,MAOArC,EAAA+C,SAAAC,IAKAhD,EAAA2K,UAAA,GAAAgB,GAAA5J,QAKA/B,EAAA0K,gBAAA,EAKA1K,EAAA4K,UAAA,GAAAe,GAAA5J,SAAA,GAMA/B,EAAAiM,UAAA,EAMAjM,EAAAkM,UAAA,EAMAlM,EAAAmM,UAAA,EAOAnM,EAAAoM,iBAAA,EAMApM,EAAAqM,UAAA,EAOArM,EAAAsM,mBAAA,EAMAtM,EAAAuM,aAAA,EAMAvM,EAAAwG,KAAA,KAMAxG,EAAA8I,KAAA,KAEA9I,EAAAM,KAAAN,EAAAM,KACAN,EAAAO,cAAAsL,EAAAvM,UAAAgB,KACAN,EAAAW,OAAAX,EAAAW,OACAX,EAAAc,gBAAA+K,EAAAvM,UAAAqB,OACAX,EAAAwM,eAAA1M,EAAAR,UAAA4B,QACAlB,EAAAmB,iBAAA0K,EAAAvM,UAAA4B,QACAlB,EAAAS,SAAAT,EAAAS,SACAT,EAAAyM,KAAAzM,EAAAyM,KACAzM,EA0LA,MAvSAtB,GAAAmN,EAAA/L,GAoHA+L,EAAAvM,UAAAgB,KAAA,WAEA/C,KAAAyO,IAAA,EAEAzO,KAAAwO,SAAAhF,EAAAxJ,KAAAkN,UAAAiC,QAAAjN,MAAAlC,KAAAiN,gBACAjN,KAAAwO,SAAA/E,EAAA,EACAhF,EAAAD,QAAAmH,YAAA3L,KAAAmH,SAAAnH,KAAAwO,UACAxO,KAAAiG,WACAjG,KAAAmH,SAAA,EAIAnH,KAAAmH,UAAA1C,EAAAD,QAAA4K,YAGApP,KAAA+J,eAAAtF,EAAAD,QAAA4K,YAEApP,KAAAqJ,MAAArJ,KAAA+M,UAAAoC,QAAAjN,MAEAlC,KAAA0J,MAAAF,EAAAxJ,KAAA0J,MAAAD,EAAAzJ,KAAAoN,UAAA+B,QAAAjN,MAEAlC,KAAA0O,WAAA1O,KAAA+M,UAAAoC,QAAAlG,KACAjJ,KAAA4O,WAAA5O,KAAAkN,UAAAiC,QAAAlG,KACAjJ,KAAA2O,WAAA3O,KAAAoN,UAAA+B,QAAAlG,KACAjJ,KAAA8O,WAAA9O,KAAAqN,UAAA8B,QAAAlG,KACAjJ,KAAA6O,gBAAA,IAAA7O,KAAAuF,aAAAiE,GAAA,IAAAxJ,KAAAuF,aAAAkE,EAEAzJ,KAAA+O,kBAAA/O,KAAA4O,UAAA,IAAA5O,KAAAkN,UAAAiC,QAAAjN,OAAAlC,KAAA6O,gBAEA7O,KAAAgP,aAAA,EAAAhP,KAAAiD,OAEA,IAAA0G,GAAA3J,KAAAqN,UAAA8B,QAAAjN,KACAlC,MAAAqP,KAAA5K,EAAAD,QAAA8K,qBAAA3F,EAAAtJ,EAAAsJ,EAAA/J,EAAA+J,EAAAjI,GAEA1B,KAAAuP,SAAA,GAQAjB,EAAAvM,UAAAmB,SAAA,SAAAC,GACAnD,KAAAyD,QAAAN,GAAAd,KAAAD,QAAAsB,OASA4K,EAAAvM,UAAAqB,OAAA,SAAAC,GAIA,GAFArD,KAAAyO,KAAApL,EAEArD,KAAAyO,KAAAzO,KAAAiD,QAEA,MADAjD,MAAAkP,QACA,CAGA,IAAA5L,GAAAtD,KAAAyO,IAAAzO,KAAAgP,YAiBA,IAhBAhP,KAAAmK,OAIA7G,EAHA,GAAAtD,KAAAmK,KAAAnJ,OAGAhB,KAAAmK,KAAA7G,EAAA,EAAA,EAAA,GAKAtD,KAAAmK,KAAA7G,IAIAtD,KAAA0O,WACA1O,KAAAqJ,MAAArJ,KAAA+M,UAAAyC,YAAAlM,IAEAtD,KAAA2O,SAAA,CACA,GAAAjF,GAAA1J,KAAAoN,UAAAoC,YAAAlM,GAAAtD,KAAAmN,eACAnN,MAAA0J,MAAAF,EAAAxJ,KAAA0J,MAAAD,EAAAC,EAGA,GAAA1J,KAAA+O,kBAAA,CAEA,GAAA/O,KAAA4O,SAAA,CACA,GAAArF,GAAAvJ,KAAAkN,UAAAsC,YAAAlM,GAAAtD,KAAAiN,eACAxI,GAAAD,QAAAiL,UAAAzP,KAAAwO,UACA/J,EAAAD,QAAAkL,QAAA1P,KAAAwO,SAAAjF,OAEA,IAAAvJ,KAAA6O,kBACA7O,KAAAwO,SAAAhF,GAAAxJ,KAAAuF,aAAAiE,EAAAnG,EACArD,KAAAwO,SAAA/E,GAAAzJ,KAAAuF,aAAAkE,EAAApG,EACArD,KAAAwF,UAAA,CACA,GAAAmK,GAAAlL,EAAAD,QAAAxD,OAAAhB,KAAAwO,SAGAmB,GAAA3P,KAAAwF,UACAf,EAAAD,QAAAkL,QAAA1P,KAAAwO,SAAAxO,KAAAwF,SAAAmK,GAKA3P,KAAA+N,SAAAvE,GAAAxJ,KAAAwO,SAAAhF,EAAAnG,EACArD,KAAA+N,SAAAtE,GAAAzJ,KAAAwO,SAAA/E,EAAApG,EAaA,MAVArD,MAAA8O,WACA9O,KAAAqP,KAAArP,KAAAqN,UAAAmC,YAAAlM,IAGA,IAAAtD,KAAA+J,cACA/J,KAAAmH,UAAAnH,KAAA+J,cAAA1G,EAEArD,KAAAuF,eAAAvF,KAAAiG,aACAjG,KAAAmH,SAAAqF,KAAAoD,MAAA5P,KAAAwO,SAAA/E,EAAAzJ,KAAAwO,SAAAhF,IAEAlG,GAOAgL,EAAAvM,UAAAmN,KAAA,WACAlP,KAAAwC,QAAA+F,QAAAvI,OAMAsO,EAAAvM,UAAA4B,QAAA,WACA3D,KAAAsI,QACAtI,KAAAsI,OAAAkD,YAAAxL,MACAA,KAAAiP,iBACAjP,KAAAwC,QAAAxC,KAAAwO,SAAAxO,KAAAqN,UAAArN,KAAAoN,UAAApN,KAAA+M,UACA/M,KAAAkN,UAAAlN,KAAAmK,KAAAnK,KAAAiJ,KAAAjJ,KAAAuL,KAAA,MAYA+C,EAAAzK,SAAA,SAAAV,GAEA,GAAAxC,EACA,KAAAA,EAAAwC,EAAAnC,OAAAL,GAAA,IAAAA,EACA,gBAAAwC,GAAAxC,KACAwC,EAAAxC,GAAA0B,KAAAD,QAAAiC,UAAAlB,EAAAxC,IAIA,IAAA8D,EAAAD,QAAAqL,QACA,IAAAlP,EAAAwC,EAAAnC,OAAA,EAAAL,EAAA,IAAAA,EACA,GAAAwC,EAAAxC,GAAAmP,aAAA3M,EAAAxC,EAAA,GAAAmP,YAAA,CACAjQ,OAAAkQ,SACAA,QAAAC,KAAA,+FACA,OAIA,MAAA7M,IAUAmL,EAAAjE,UAAA,SAAA/D,GACA,MAAAA,IAEAgI,GACAD,EACA7O,GAAAgF,QAAA8J,gECjUA,YACAjN,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAA+N,GAAA5N,KAAA4N,YACAvL,EAAAxD,EAAA,kBAOAgP,GAOAL,SAAA,EACAT,YAAA5C,KAAA2D,GAAA,IAQAxE,YAAA,SAAAwC,EAAAxM,GACA,GAAAwM,EAAA,CAEAA,GAAA+B,EAAAd,WACA,IAAA9O,GAAAkM,KAAA4D,IAAAjC,GACAkC,EAAA7D,KAAA8D,IAAAnC,GACAoC,EAAA5O,EAAA6H,EAAA6G,EAAA1O,EAAA8H,EAAAnJ,EACAkQ,EAAA7O,EAAA6H,EAAAlJ,EAAAqB,EAAA8H,EAAA4G,CACA1O,GAAA6H,EAAA+G,EACA5O,EAAA8H,EAAA+G,IAWAlB,qBAAA,SAAAjP,EAAAT,EAAA8B,GACA,MAAArB,IAAA,GAAAT,GAAA,EAAA8B,GAQA+N,UAAA,SAAAgB,GACA,GAAAC,GAAA,EAAAR,EAAAlP,OAAAyP,EACAA,GAAAjH,GAAAkH,EACAD,EAAAhH,GAAAiH,GASAhB,QAAA,SAAAe,EAAAvO,GACAuO,EAAAjH,GAAAtH,EACAuO,EAAAhH,GAAAvH,GASAlB,OAAA,SAAAyP,GACA,MAAAjE,MAAAmE,KAAAF,EAAAjH,EAAAiH,EAAAjH,EAAAiH,EAAAhH,EAAAgH,EAAAhH,IAYAmH,SAAA,SAAAjH,EAAA5F,GACAA,IACAA,MACA,KAAA4F,EAAAkH,OAAA,GACAlH,EAAAA,EAAAmH,OAAA,GACA,IAAAnH,EAAA+D,QAAA,QACA/D,EAAAA,EAAAmH,OAAA,GACA,IAAAzH,EAUA,OATA,IAAAM,EAAA3I,SACAqI,EAAAM,EAAAmH,OAAA,EAAA,GACAnH,EAAAA,EAAAmH,OAAA,IAEA/M,EAAA1D,EAAA0Q,SAAApH,EAAAmH,OAAA,EAAA,GAAA,IACA/M,EAAAnE,EAAAmR,SAAApH,EAAAmH,OAAA,EAAA,GAAA,IACA/M,EAAArC,EAAAqP,SAAApH,EAAAmH,OAAA,EAAA,GAAA,IACAzH,IACAtF,EAAAtD,EAAAsQ,SAAA1H,EAAA,KACAtF,GAYAqG,aAAA,SAAA4G,GACA,GAAAC,GAAAD,EAAAhQ,OACAkQ,EAAA,EAAAD,CAOA,OAAA,UAAAE,GACA,GAAAhR,GAAAG,EACAK,EAAAsQ,EAAAE,EAAA,CAGA,OAFAhR,IAAAgR,EAAAxQ,EAAAuQ,GAAAD,EACA3Q,EAAA0Q,EAAArQ,IAAAqQ,EAAAC,EAAA,GACA3Q,EAAAA,EAAAH,GAAA,GAAA,EAAAA,IAAAG,EAAA8Q,GAAA9Q,EAAAA,GAAAH,GAAAG,EAAAJ,EAAAI,EAAAA,MAUA2J,aAAA,SAAAoH,GACA,IAAAA,EACA,MAAApB,GAAAqB,MAEA,KADAD,EAAAA,EAAAE,cACAF,EAAA3D,QAAA,MAAA,GACA2D,EAAAA,EAAAG,QAAA,IAAA,IACA,OAAAvB,GAAAoB,IAAApB,EAAAqB,QAYAG,sBAAA,SAAAC,EAAAC,OACA,KAAAA,IAAAA,EAAA,KACA,gBAAAA,IAAAA,GAAA,KACAA,EAAA,GACA,IAAAC,GAAA,GAAAlN,GAAAF,QAAAkN,EAAA,GAAAxP,MAAAwP,EAAA,GAAAP,KACAS,GAAAC,WAAA,CAKA,KAAA,GAJAC,GAAAF,EACAzC,EAAAuC,EAAA,GACAK,EAAA,EACA9I,EAAAyI,EAAAK,GACApR,EAAA,EAAAA,EAAAgR,IAAAhR,EAAA,CAGA,IAFA,GAAA2C,GAAA3C,EAAAgR,EAEArO,EAAA2F,EAAAkI,MACAhC,EAAAlG,EACAA,EAAAyI,IAAAK,EAGAzO,IAAAA,EAAA6L,EAAAgC,OAAAlI,EAAAkI,KAAAhC,EAAAgC,KACA,IAAAa,GAAA9B,EAAAU,SAAAzB,EAAAjN,OACA+P,EAAA/B,EAAAU,SAAA3H,EAAA/G,OACA6B,IACAA,GAAA1D,GAAA4R,EAAA5R,EAAA2R,EAAA3R,GAAAiD,EAAA0O,EAAA3R,EACA0D,EAAAnE,GAAAqS,EAAArS,EAAAoS,EAAApS,GAAA0D,EAAA0O,EAAApS,EACAmE,EAAArC,GAAAuQ,EAAAvQ,EAAAsQ,EAAAtQ,GAAA4B,EAAA0O,EAAAtQ,EACAoQ,EAAA7I,KAAA,GAAAvE,GAAAF,QAAAT,EAAApD,EAAAgR,GACAG,EAAAA,EAAA7I,KAIA,MAAA2I,IAGApS,GAAAgF,QAAA0L,4CCnMA,YACA,IAAA/O,GAAAnB,MAAAA,KAAAmB,WAAA,WACA,GAAAC,GAAAC,OAAAC,iBACAC,uBAAAC,QAAA,SAAAC,EAAAC,GAAAD,EAAAF,UAAAG,IACA,SAAAD,EAAAC,GAAA,IAAA,GAAAC,KAAAD,GAAAA,EAAAE,eAAAD,KAAAF,EAAAE,GAAAD,EAAAC,IACA,OAAA,UAAAF,EAAAC,GAEA,QAAAG,KAAA7B,KAAA8B,YAAAL,EADAL,EAAAK,EAAAC,GAEAD,EAAAM,UAAA,OAAAL,EAAAL,OAAAW,OAAAN,IAAAG,EAAAE,UAAAL,EAAAK,UAAA,GAAAF,OAGAR,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAuC,GAAAvD,EAAA,mBACAiB,EAAAjB,EAAA,cAKA2D,EAAA,GAAAxC,MAAAyC,MAGAoN,GACA,MACA,OACA,MACA,QACA,QACA,OACA,IACA,KACA,MACA,MACA,MACA,OACA,OACA,OACA,QACA,OAGAC,EAAA,GAAAC,SAGA,yCACAC,OAAAH,GAAAI,KAAA,KAAA,KAWAC,EAAA,SAAAC,GAEA,IAAA,GADAC,GAAAD,EAAAE,MAAAP,GACAxR,EAAA8R,EAAAzR,OAAA,EAAAL,GAAA,IAAAA,EACAuR,EAAAxE,QAAA+E,EAAA9R,KAAA,IACA8R,EAAA9R,GAAA,QAAA8R,EAAA9R,GAGA,OADA6R,GAAAC,EAAAH,KAAA,IACA,GAAAK,UAAA,IAAA,UAAAH,EAAA,MA2BAI,EAAA,SAAArQ,GAEA,QAAAqQ,GAAApQ,GACA,GAAAC,GAAAF,EAAAxB,KAAAf,KAAAwC,IAAAxC,IAKA,OAJAyC,GAAAoQ,KAAA,KACApQ,EAAAqQ,gBAAA,EACArQ,EAAAsQ,gBAAA,GAAA1Q,MAAAyC,MACArC,EAAAuQ,SAAA,EACAvQ,EA4FA,MAnGAtB,GAAAyR,EAAArQ,GAcAqQ,EAAA7Q,UAAAgB,KAAA,WAEA/C,KAAA8S,gBAAA9S,KAAAmH,SAEAnH,KAAAgD,gBAEAhD,KAAA6S,KAAA7S,KAAAsG,UAAAuM,KAEA7S,KAAA+O,mBAAA/O,KAAA6S,KAEA7S,KAAAgT,SAAA,EAEAhT,KAAA+S,gBAAAvJ,EAAAxJ,KAAA+N,SAAAvE,EACAxJ,KAAA+S,gBAAAtJ,EAAAzJ,KAAA+N,SAAAtE,GAOAmJ,EAAA7Q,UAAAqB,OAAA,SAAAC,GACA,GAAAC,GAAAtD,KAAAuD,gBAAAF,EAEA,IAAAC,GAAA,GAAAtD,KAAA6S,KAAA,CAEA,GAAAtJ,GAAAvJ,KAAAkN,UAAAsC,YAAAlM,GAAAtD,KAAAiN,eACAjN,MAAAgT,UAAAzJ,EAAAlG,EAEAwB,EAAA2E,EAAAxJ,KAAAgT,SACAnO,EAAA4E,EAAAzJ,KAAA6S,KAAA7S,KAAAgT,UACAvO,EAAAD,QAAAmH,YAAA3L,KAAA8S,gBAAAjO,GACA7E,KAAA+N,SAAAvE,EAAAxJ,KAAA+S,gBAAAvJ,EAAA3E,EAAA2E,EACAxJ,KAAA+N,SAAAtE,EAAAzJ,KAAA+S,gBAAAtJ,EAAA5E,EAAA4E,EAEA,MAAAnG,IAMAsP,EAAA7Q,UAAA4B,QAAA,WACA3D,KAAA4D,mBACA5D,KAAA6S,KAAA7S,KAAA+S,gBAAA,MAYAH,EAAA/O,SAAA,SAAAV,GACA,MAAAhB,GAAAqC,QAAAX,SAAAV,IAWAyP,EAAAvI,UAAA,SAAA/D,GACA,GAAAvC,KACA,IAAAuC,GAAAA,EAAAuM,KACA,IACA9O,EAAA8O,KAAAN,EAAAjM,EAAAuM,MAEA,MAAA3S,GACAuE,EAAAD,QAAAqL,SACAE,QAAAkD,MAAA,kDACAlP,EAAA8O,KAAA,SAIApO,GAAAD,QAAAqL,SACAE,QAAAkD,MAAA,qDACAlP,EAAA8O,KAAA,IAEA,OAAA9O,IAEA6O,GACAzQ,EAAAqC,QACAhF,GAAAgF,QAAAoO,4DC/LA,YA4CA,SAAAM,GAAA5P,GAGA,MAFAtD,MAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,KACAtD,KAAAiJ,KAAA/G,MAAAlC,KAAAmP,QAAAjN,OAAAoB,EAAAtD,KAAAmP,QAAAjN,MAEA,QAAAiR,GAAA7P,GACAtD,KAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,GACA,IAAA0O,GAAAhS,KAAAmP,QAAAjN,MAAA+P,EAAAjS,KAAAiJ,KAAA/G,MACA7B,GAAA4R,EAAA5R,EAAA2R,EAAA3R,GAAAiD,EAAA0O,EAAA3R,EACAT,GAAAqS,EAAArS,EAAAoS,EAAApS,GAAA0D,EAAA0O,EAAApS,EACA8B,GAAAuQ,EAAAvQ,EAAAsQ,EAAAtQ,GAAA4B,EAAA0O,EAAAtQ,CACA,OAAA+C,GAAAD,QAAA8K,qBAAAjP,EAAAT,EAAA8B,GAEA,QAAA0R,GAAA9P,GAIA,IAHAtD,KAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,IAEAA,EAAAtD,KAAAiJ,KAAAkI,MACAnR,KAAAmP,QAAAnP,KAAAiJ,KACAjJ,KAAAiJ,KAAAjJ,KAAAiJ,KAAAA,IAIA,OADA3F,IAAAA,EAAAtD,KAAAmP,QAAAgC,OAAAnR,KAAAiJ,KAAAkI,KAAAnR,KAAAmP,QAAAgC,OACAnR,KAAAiJ,KAAA/G,MAAAlC,KAAAmP,QAAAjN,OAAAoB,EAAAtD,KAAAmP,QAAAjN,MAEA,QAAAmR,GAAA/P,GAIA,IAHAtD,KAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,IAEAA,EAAAtD,KAAAiJ,KAAAkI,MACAnR,KAAAmP,QAAAnP,KAAAiJ,KACAjJ,KAAAiJ,KAAAjJ,KAAAiJ,KAAAA,IAGA3F,IAAAA,EAAAtD,KAAAmP,QAAAgC,OAAAnR,KAAAiJ,KAAAkI,KAAAnR,KAAAmP,QAAAgC,KACA,IAAAa,GAAAhS,KAAAmP,QAAAjN,MAAA+P,EAAAjS,KAAAiJ,KAAA/G,MACA7B,GAAA4R,EAAA5R,EAAA2R,EAAA3R,GAAAiD,EAAA0O,EAAA3R,EACAT,GAAAqS,EAAArS,EAAAoS,EAAApS,GAAA0D,EAAA0O,EAAApS,EACA8B,GAAAuQ,EAAAvQ,EAAAsQ,EAAAtQ,GAAA4B,EAAA0O,EAAAtQ,CACA,OAAA+C,GAAAD,QAAA8K,qBAAAjP,EAAAT,EAAA8B,GAEA,QAAA4R,GAAAhQ,GAIA,IAHAtD,KAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,IAEAtD,KAAAiJ,MAAA3F,EAAAtD,KAAAiJ,KAAAkI,MACAnR,KAAAmP,QAAAnP,KAAAiJ,KACAjJ,KAAAiJ,KAAAjJ,KAAAiJ,KAAAA,IAEA,OAAAjJ,MAAAmP,QAAAjN,MAEA,QAAAqR,GAAAjQ,GAIA,IAHAtD,KAAAmK,OACA7G,EAAAtD,KAAAmK,KAAA7G,IAEAtD,KAAAiJ,MAAA3F,EAAAtD,KAAAiJ,KAAAkI,MACAnR,KAAAmP,QAAAnP,KAAAiJ,KACAjJ,KAAAiJ,KAAAjJ,KAAAiJ,KAAAA,IAEA,IAAA+I,GAAAhS,KAAAmP,QAAAjN,KACA,OAAAuC,GAAAD,QAAA8K,qBAAA0C,EAAA3R,EAAA2R,EAAApS,EAAAoS,EAAAtQ,GAxGAL,OAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAuC,GAAAvD,EAAA,mBASAsS,EAAA,WACA,QAAAA,GAAAC,OACA,KAAAA,IAAAA,GAAA,GACAzT,KAAAmP,QAAA,KACAnP,KAAAiJ,KAAA,KACAjJ,KAAAyT,UAAAA,EACAzT,KAAAwP,YAAA,KACAxP,KAAAmK,KAAA,KAuBA,MAfAqJ,GAAAzR,UAAAiL,MAAA,SAAA4E,GACA5R,KAAAmP,QAAAyC,EACA5R,KAAAiJ,KAAA2I,EAAA3I,KACAjJ,KAAAiJ,MAAAjJ,KAAAiJ,KAAAkI,MAAA,EAEAnR,KAAAwP,YAAAxP,KAAAyT,QAAAN,EAAAD,EAEAtB,EAAAC,UACA7R,KAAAwP,YAAAxP,KAAAyT,QAAAF,EAAAD,EAGAtT,KAAAwP,YAAAxP,KAAAyT,QAAAJ,EAAAD,EAEApT,KAAAmK,KAAAnK,KAAAmP,QAAAhF,MAEAqJ,IAEAhU,GAAAgF,QAAAgP,6CC3CA,YACAnS,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAAuC,GAAAvD,EAAA,mBAUAwS,EAAA,WACA,QAAAA,GAAAxR,EAAAiP,EAAAhH,GACAnK,KAAAkC,MAAA,gBAAAA,GAAAuC,EAAAD,QAAAoM,SAAA1O,GAAAA,EACAlC,KAAAmR,KAAAA,EACAnR,KAAAiJ,KAAA,KACAjJ,KAAA6R,WAAA,EAEA7R,KAAAmK,KADAA,EACA,kBAAAA,GAAAA,EAAA1F,EAAAD,QAAA4F,aAAAD,GAGA,KAuCA,MAxBAuJ,GAAApK,WAAA,SAAAxF,GACA,GAAAtC,MAAA0H,QAAApF,EAAA4N,MAAA,CACA,GAAAiC,GAAA7P,EAAA4N,KACAkC,MAAA,GAAAhC,MAAA,EAGA,IAFAA,EAAAgC,EAAA,GAAAF,GAAAC,EAAA,GAAAzR,MAAAyR,EAAA,GAAAxC,KAAArN,EAAAqG,MAEAwJ,EAAA3S,OAAA,GAAA,IAAA2S,EAAA3S,QAAA2S,EAAA,GAAAzR,QAAAyR,EAAA,GAAAzR,MACA,IAAA,GAAAvB,GAAA,EAAAA,EAAAgT,EAAA3S,SAAAL,EACAiT,EAAA3K,KAAA,GAAAyK,GAAAC,EAAAhT,GAAAuB,MAAAyR,EAAAhT,GAAAwQ,MACAyC,EAAAA,EAAA3K,IAIA,OADA2I,GAAAC,YAAA/N,EAAA+N,UACAD,EAIA,GAAAiC,GAAA,GAAAH,GAAA5P,EAAA+P,MAAA,EAIA,OAFA/P,GAAAgQ,MAAAhQ,EAAA+P,QACAA,EAAA5K,KAAA,GAAAyK,GAAA5P,EAAAgQ,IAAA,IACAD,GAGAH,IAEAlU,GAAAgF,QAAAkP,6CC/DA,YACArS,QAAAY,eAAAzC,EAAA,cAAA0C,OAAA,GACA,IAAA6R,GAAA7S,EAAA,qBACA1B,GAAA0Q,cAAA6D,EAAAvP,OACA,IAAAwP,GAAA9S,EAAA,gBACA1B,GAAA8O,SAAA0F,EAAAxP,OACA,IAAAyP,GAAA/S,EAAA,eACA1B,GAAAuF,QAAAkP,EAAAzP,OACA,IAAA0P,GAAAhT,EAAA,oBACA1B,GAAAoT,aAAAsB,EAAA1P,OACA,IAAA2P,GAAAjT,EAAA,wBACA1B,GAAA8C,iBAAA6R,EAAA3P,yICXA,YAGA,IAFAnD,OAAAY,eAAAzC,EAAA,cAAA0C,OAAA,IAEA,mBAAAG,MACA,KAAA,oDAGAA,MAAA+R,YACA/R,KAAA+R,aAGA,IAAAA,GAAAlT,EAAA,cAEA,KAAA,GAAAmT,KAAAD,GACA/R,KAAA+R,UAAAC,GAAAD,EAAAC","file":"pixi-particles.min.js","sourcesContent":["(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0) {\r\n this.elapsed += delta;\r\n if (this.elapsed > this.duration) {\r\n //loop elapsed back around\r\n if (this.loop)\r\n this.elapsed = this.elapsed % this.duration;\r\n else\r\n this.elapsed = this.duration - 0.000001;\r\n }\r\n var frame = (this.elapsed * this.framerate + 0.0000001) | 0;\r\n this.texture = this.textures[frame] || PIXI.Texture.EMPTY;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.AnimatedParticle#destroy\r\n */\r\n AnimatedParticle.prototype.destroy = function () {\r\n this.Particle_destroy();\r\n this.textures = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time.\r\n * @method PIXI.particles.AnimatedParticle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data, properly formatted for AnimatedParticle.\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n AnimatedParticle.parseArt = function (art) {\r\n var data, output, textures, tex, outTextures;\r\n var outArr = [];\r\n for (var i = 0; i < art.length; ++i) {\r\n data = art[i];\r\n outArr[i] = output = {};\r\n output.textures = outTextures = [];\r\n textures = data.textures;\r\n for (var j = 0; j < textures.length; ++j) {\r\n tex = textures[j];\r\n if (typeof tex == \"string\")\r\n outTextures.push(Texture.fromImage(tex));\r\n else if (tex instanceof Texture)\r\n outTextures.push(tex);\r\n else {\r\n var dupe = tex.count || 1;\r\n if (typeof tex.texture == \"string\")\r\n tex = Texture.fromImage(tex.texture);\r\n else\r\n tex = tex.texture;\r\n for (; dupe > 0; --dupe) {\r\n outTextures.push(tex);\r\n }\r\n }\r\n }\r\n //use these values to signify that the animation should match the particle life time.\r\n if (data.framerate == \"matchLife\") {\r\n //-1 means that it should be calculated\r\n output.framerate = -1;\r\n output.duration = 0;\r\n output.loop = false;\r\n }\r\n else {\r\n //determine if the animation should loop\r\n output.loop = !!data.loop;\r\n //get the framerate, default to 60\r\n output.framerate = data.framerate > 0 ? data.framerate : 60;\r\n //determine the duration\r\n output.duration = outTextures.length / output.framerate;\r\n }\r\n }\r\n return outArr;\r\n };\r\n return AnimatedParticle;\r\n}(Particle_1.default));\r\nexports.default = AnimatedParticle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar Particle_1 = require(\"./Particle\");\r\nvar PropertyNode_1 = require(\"./PropertyNode\");\r\nvar ticker = PIXI.ticker.shared;\r\nvar helperPoint = new PIXI.Point();\r\n/**\r\n * A particle emitter.\r\n * @memberof PIXI.particles\r\n * @class Emitter\r\n * @constructor\r\n * @param {PIXI.Container} particleParent The container to add the\r\n * particles to.\r\n * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use\r\n * for the particles. Strings will be turned\r\n * into textures via Texture.fromImage().\r\n * @param {Object} [config] A configuration object containing settings for the emitter.\r\n * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter\r\n * will start disabled.\r\n * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter\r\n * will automatically call update via the PIXI shared ticker.\r\n */\r\nvar Emitter = /** @class */ (function () {\r\n function Emitter(particleParent, particleImages, config) {\r\n this._particleConstructor = Particle_1.default;\r\n //properties for individual particles\r\n this.particleImages = null;\r\n this.startAlpha = null;\r\n this.startSpeed = null;\r\n this.minimumSpeedMultiplier = 1;\r\n this.acceleration = null;\r\n this.maxSpeed = NaN;\r\n this.startScale = null;\r\n this.minimumScaleMultiplier = 1;\r\n this.startColor = null;\r\n this.minLifetime = 0;\r\n this.maxLifetime = 0;\r\n this.minStartRotation = 0;\r\n this.maxStartRotation = 0;\r\n this.noRotation = false;\r\n this.minRotationSpeed = 0;\r\n this.maxRotationSpeed = 0;\r\n this.particleBlendMode = 0;\r\n this.customEase = null;\r\n this.extraData = null;\r\n //properties for spawning particles\r\n this._frequency = 1;\r\n this.spawnChance = 1;\r\n this.maxParticles = 1000;\r\n this.emitterLifetime = -1;\r\n this.spawnPos = null;\r\n this.spawnType = null;\r\n this._spawnFunc = null;\r\n this.spawnRect = null;\r\n this.spawnCircle = null;\r\n this.particlesPerWave = 1;\r\n this.particleSpacing = 0;\r\n this.angleStart = 0;\r\n //emitter properties\r\n this.rotation = 0;\r\n this.ownerPos = null;\r\n this._prevEmitterPos = null;\r\n this._prevPosIsValid = false;\r\n this._posChanged = false;\r\n this._parent = null;\r\n this.addAtBack = false;\r\n this.particleCount = 0;\r\n this._emit = false;\r\n this._spawnTimer = 0;\r\n this._emitterLife = -1;\r\n this._activeParticlesFirst = null;\r\n this._activeParticlesLast = null;\r\n this._poolFirst = null;\r\n this._origConfig = null;\r\n this._origArt = null;\r\n this._autoUpdate = false;\r\n this._destroyWhenComplete = false;\r\n this._completeCallback = null;\r\n //set the initial parent\r\n this.parent = particleParent;\r\n if (particleImages && config)\r\n this.init(particleImages, config);\r\n //save often used functions on the instance instead of the prototype for better speed\r\n this.recycle = this.recycle;\r\n this.update = this.update;\r\n this.rotate = this.rotate;\r\n this.updateSpawnPos = this.updateSpawnPos;\r\n this.updateOwnerPos = this.updateOwnerPos;\r\n }\r\n Object.defineProperty(Emitter.prototype, \"frequency\", {\r\n /**\r\n * Time between particle spawns in seconds. If this value is not a number greater than 0,\r\n * it will be set to 1 (particle per second) to prevent infinite loops.\r\n * @member {Number} PIXI.particles.Emitter#frequency\r\n */\r\n get: function () { return this._frequency; },\r\n set: function (value) {\r\n //do some error checking to prevent infinite loops\r\n if (typeof value == \"number\" && value > 0)\r\n this._frequency = value;\r\n else\r\n this._frequency = 1;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n Object.defineProperty(Emitter.prototype, \"particleConstructor\", {\r\n /**\r\n * The constructor used to create new particles. The default is\r\n * the built in Particle class. Setting this will dump any active or\r\n * pooled particles, if the emitter has already been used.\r\n * @member {Function} PIXI.particles.Emitter#particleConstructor\r\n */\r\n get: function () { return this._particleConstructor; },\r\n set: function (value) {\r\n if (value != this._particleConstructor) {\r\n this._particleConstructor = value;\r\n //clean up existing particles\r\n this.cleanup();\r\n //scrap all the particles\r\n for (var particle = this._poolFirst; particle; particle = particle.next) {\r\n particle.destroy();\r\n }\r\n this._poolFirst = null;\r\n //re-initialize the emitter so that the new constructor can do anything it needs to\r\n if (this._origConfig && this._origArt)\r\n this.init(this._origArt, this._origConfig);\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n Object.defineProperty(Emitter.prototype, \"parent\", {\r\n /**\r\n * The container to add particles to. Settings this will dump any active particles.\r\n * @member {PIXI.Container} PIXI.particles.Emitter#parent\r\n */\r\n get: function () { return this._parent; },\r\n set: function (value) {\r\n this.cleanup();\r\n this._parent = value;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * Sets up the emitter based on the config settings.\r\n * @method PIXI.particles.Emitter#init\r\n * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles.\r\n * @param {Object} config A configuration object containing settings for the emitter.\r\n */\r\n Emitter.prototype.init = function (art, config) {\r\n if (!art || !config)\r\n return;\r\n //clean up any existing particles\r\n this.cleanup();\r\n //store the original config and particle images, in case we need to re-initialize\r\n //when the particle constructor is changed\r\n this._origConfig = config;\r\n this._origArt = art;\r\n //set up the array of data, also ensuring that it is an array\r\n art = Array.isArray(art) ? art.slice() : [art];\r\n //run the art through the particle class's parsing function\r\n var partClass = this._particleConstructor;\r\n this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art;\r\n ///////////////////////////\r\n // Particle Properties //\r\n ///////////////////////////\r\n //set up the alpha\r\n if (config.alpha) {\r\n this.startAlpha = PropertyNode_1.default.createList(config.alpha);\r\n }\r\n else\r\n this.startAlpha = new PropertyNode_1.default(1, 0);\r\n //set up the speed\r\n if (config.speed) {\r\n this.startSpeed = PropertyNode_1.default.createList(config.speed);\r\n this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1;\r\n }\r\n else {\r\n this.minimumSpeedMultiplier = 1;\r\n this.startSpeed = new PropertyNode_1.default(0, 0);\r\n }\r\n //set up acceleration\r\n var acceleration = config.acceleration;\r\n if (acceleration && (acceleration.x || acceleration.y)) {\r\n //make sure we disable speed interpolation\r\n this.startSpeed.next = null;\r\n this.acceleration = new PIXI.Point(acceleration.x, acceleration.y);\r\n this.maxSpeed = config.maxSpeed || NaN;\r\n }\r\n else\r\n this.acceleration = new PIXI.Point();\r\n //set up the scale\r\n if (config.scale) {\r\n this.startScale = PropertyNode_1.default.createList(config.scale);\r\n this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1;\r\n }\r\n else {\r\n this.startScale = new PropertyNode_1.default(1, 0);\r\n this.minimumScaleMultiplier = 1;\r\n }\r\n //set up the color\r\n if (config.color) {\r\n this.startColor = PropertyNode_1.default.createList(config.color);\r\n }\r\n else {\r\n this.startColor = new PropertyNode_1.default({ r: 0xFF, g: 0xFF, b: 0xFF }, 0);\r\n }\r\n //set up the start rotation\r\n if (config.startRotation) {\r\n this.minStartRotation = config.startRotation.min;\r\n this.maxStartRotation = config.startRotation.max;\r\n }\r\n else\r\n this.minStartRotation = this.maxStartRotation = 0;\r\n if (config.noRotation &&\r\n (this.minStartRotation || this.maxStartRotation)) {\r\n this.noRotation = !!config.noRotation;\r\n }\r\n else\r\n this.noRotation = false;\r\n //set up the rotation speed\r\n if (config.rotationSpeed) {\r\n this.minRotationSpeed = config.rotationSpeed.min;\r\n this.maxRotationSpeed = config.rotationSpeed.max;\r\n }\r\n else\r\n this.minRotationSpeed = this.maxRotationSpeed = 0;\r\n //set up the lifetime\r\n this.minLifetime = config.lifetime.min;\r\n this.maxLifetime = config.lifetime.max;\r\n //get the blend mode\r\n this.particleBlendMode = ParticleUtils_1.default.getBlendMode(config.blendMode);\r\n //use the custom ease if provided\r\n if (config.ease) {\r\n this.customEase = typeof config.ease == \"function\" ?\r\n config.ease :\r\n ParticleUtils_1.default.generateEase(config.ease);\r\n }\r\n else\r\n this.customEase = null;\r\n //set up the extra data, running it through the particle class's parseData function.\r\n if (partClass.parseData)\r\n this.extraData = partClass.parseData(config.extraData);\r\n else\r\n this.extraData = config.extraData || null;\r\n //////////////////////////\r\n // Emitter Properties //\r\n //////////////////////////\r\n //reset spawn type specific settings\r\n this.spawnRect = this.spawnCircle = null;\r\n this.particlesPerWave = 1;\r\n if (config.particlesPerWave && config.particlesPerWave > 1)\r\n this.particlesPerWave = config.particlesPerWave;\r\n this.particleSpacing = 0;\r\n this.angleStart = 0;\r\n var spawnCircle;\r\n //determine the spawn function to use\r\n switch (config.spawnType) {\r\n case \"rect\":\r\n this.spawnType = \"rect\";\r\n this._spawnFunc = this._spawnRect;\r\n var spawnRect = config.spawnRect;\r\n this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);\r\n break;\r\n case \"circle\":\r\n this.spawnType = \"circle\";\r\n this._spawnFunc = this._spawnCircle;\r\n spawnCircle = config.spawnCircle;\r\n this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\r\n break;\r\n case \"ring\":\r\n this.spawnType = \"ring\";\r\n this._spawnFunc = this._spawnRing;\r\n spawnCircle = config.spawnCircle;\r\n this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r);\r\n this.spawnCircle.minRadius = spawnCircle.minR;\r\n break;\r\n case \"burst\":\r\n this.spawnType = \"burst\";\r\n this._spawnFunc = this._spawnBurst;\r\n this.particleSpacing = config.particleSpacing;\r\n this.angleStart = config.angleStart ? config.angleStart : 0;\r\n break;\r\n case \"point\":\r\n this.spawnType = \"point\";\r\n this._spawnFunc = this._spawnPoint;\r\n break;\r\n default:\r\n this.spawnType = \"point\";\r\n this._spawnFunc = this._spawnPoint;\r\n break;\r\n }\r\n //set the spawning frequency\r\n this.frequency = config.frequency;\r\n this.spawnChance = (typeof config.spawnChance === 'number' && config.spawnChance > 0) ? config.spawnChance : 1;\r\n //set the emitter lifetime\r\n this.emitterLifetime = config.emitterLifetime || -1;\r\n //set the max particles\r\n this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000;\r\n //determine if we should add the particle at the back of the list or not\r\n this.addAtBack = !!config.addAtBack;\r\n //reset the emitter position and rotation variables\r\n this.rotation = 0;\r\n this.ownerPos = new PIXI.Point();\r\n this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y);\r\n this._prevEmitterPos = this.spawnPos.clone();\r\n //previous emitter position is invalid and should not be used for interpolation\r\n this._prevPosIsValid = false;\r\n //start emitting\r\n this._spawnTimer = 0;\r\n this.emit = config.emit === undefined ? true : !!config.emit;\r\n this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate;\r\n };\r\n /**\r\n * Recycles an individual particle.\r\n * @method PIXI.particles.Emitter#recycle\r\n * @param {Particle} particle The particle to recycle.\r\n * @private\r\n */\r\n Emitter.prototype.recycle = function (particle) {\r\n if (particle.next)\r\n particle.next.prev = particle.prev;\r\n if (particle.prev)\r\n particle.prev.next = particle.next;\r\n if (particle == this._activeParticlesLast)\r\n this._activeParticlesLast = particle.prev;\r\n if (particle == this._activeParticlesFirst)\r\n this._activeParticlesFirst = particle.next;\r\n //add to pool\r\n particle.prev = null;\r\n particle.next = this._poolFirst;\r\n this._poolFirst = particle;\r\n //remove child from display, or make it invisible if it is in a ParticleContainer\r\n if (particle.parent)\r\n particle.parent.removeChild(particle);\r\n //decrease count\r\n --this.particleCount;\r\n };\r\n /**\r\n * Sets the rotation of the emitter to a new value.\r\n * @method PIXI.particles.Emitter#rotate\r\n * @param {Number} newRot The new rotation, in degrees.\r\n */\r\n Emitter.prototype.rotate = function (newRot) {\r\n if (this.rotation == newRot)\r\n return;\r\n //caclulate the difference in rotation for rotating spawnPos\r\n var diff = newRot - this.rotation;\r\n this.rotation = newRot;\r\n //rotate spawnPos\r\n ParticleUtils_1.default.rotatePoint(diff, this.spawnPos);\r\n //mark the position as having changed\r\n this._posChanged = true;\r\n };\r\n /**\r\n * Changes the spawn position of the emitter.\r\n * @method PIXI.particles.Emitter#updateSpawnPos\r\n * @param {Number} x The new x value of the spawn position for the emitter.\r\n * @param {Number} y The new y value of the spawn position for the emitter.\r\n */\r\n Emitter.prototype.updateSpawnPos = function (x, y) {\r\n this._posChanged = true;\r\n this.spawnPos.x = x;\r\n this.spawnPos.y = y;\r\n };\r\n /**\r\n * Changes the position of the emitter's owner. You should call this if you are adding\r\n * particles to the world container that your emitter's owner is moving around in.\r\n * @method PIXI.particles.Emitter#updateOwnerPos\r\n * @param {Number} x The new x value of the emitter's owner.\r\n * @param {Number} y The new y value of the emitter's owner.\r\n */\r\n Emitter.prototype.updateOwnerPos = function (x, y) {\r\n this._posChanged = true;\r\n this.ownerPos.x = x;\r\n this.ownerPos.y = y;\r\n };\r\n /**\r\n * Prevents emitter position interpolation in the next update.\r\n * This should be used if you made a major position change of your emitter's owner\r\n * that was not normal movement.\r\n * @method PIXI.particles.Emitter#resetPositionTracking\r\n */\r\n Emitter.prototype.resetPositionTracking = function () {\r\n this._prevPosIsValid = false;\r\n };\r\n Object.defineProperty(Emitter.prototype, \"emit\", {\r\n /**\r\n * If particles should be emitted during update() calls. Setting this to false\r\n * stops new particles from being created, but allows existing ones to die out.\r\n * @member {Boolean} PIXI.particles.Emitter#emit\r\n */\r\n get: function () { return this._emit; },\r\n set: function (value) {\r\n this._emit = !!value;\r\n this._emitterLife = this.emitterLifetime;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n ;\r\n Object.defineProperty(Emitter.prototype, \"autoUpdate\", {\r\n /**\r\n * If the update function is called automatically from the shared ticker.\r\n * Setting this to false requires calling the update function manually.\r\n * @member {Boolean} PIXI.particles.Emitter#autoUpdate\r\n */\r\n get: function () { return this._autoUpdate; },\r\n set: function (value) {\r\n if (this._autoUpdate && !value) {\r\n ticker.remove(this.update, this);\r\n }\r\n else if (!this._autoUpdate && value) {\r\n ticker.add(this.update, this);\r\n }\r\n this._autoUpdate = !!value;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself\r\n * when particle emission is complete.\r\n * @method PIXI.particles.Emitter#playOnceAndDestroy\r\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\r\n */\r\n Emitter.prototype.playOnceAndDestroy = function (callback) {\r\n this.autoUpdate = true;\r\n this.emit = true;\r\n this._destroyWhenComplete = true;\r\n this._completeCallback = callback;\r\n };\r\n /**\r\n * Starts emitting particles and optionally calls a callback when particle emission is complete.\r\n * @method PIXI.particles.Emitter#playOnce\r\n * @param {Function} [callback] Callback for when emission is complete (all particles have died off)\r\n */\r\n Emitter.prototype.playOnce = function (callback) {\r\n this.emit = true;\r\n this._completeCallback = callback;\r\n };\r\n /**\r\n * Updates all particles spawned by this emitter and emits new ones.\r\n * @method PIXI.particles.Emitter#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n */\r\n Emitter.prototype.update = function (delta) {\r\n if (this._autoUpdate) {\r\n delta = delta / PIXI.settings.TARGET_FPMS / 1000;\r\n }\r\n //if we don't have a parent to add particles to, then don't do anything.\r\n //this also works as a isDestroyed check\r\n if (!this._parent)\r\n return;\r\n //update existing particles\r\n var i, particle, next;\r\n for (particle = this._activeParticlesFirst; particle; particle = next) {\r\n next = particle.next;\r\n particle.update(delta);\r\n }\r\n var prevX, prevY;\r\n //if the previous position is valid, store these for later interpolation\r\n if (this._prevPosIsValid) {\r\n prevX = this._prevEmitterPos.x;\r\n prevY = this._prevEmitterPos.y;\r\n }\r\n //store current position of the emitter as local variables\r\n var curX = this.ownerPos.x + this.spawnPos.x;\r\n var curY = this.ownerPos.y + this.spawnPos.y;\r\n //spawn new particles\r\n if (this._emit) {\r\n //decrease spawn timer\r\n this._spawnTimer -= delta;\r\n //while _spawnTimer < 0, we have particles to spawn\r\n while (this._spawnTimer <= 0) {\r\n //determine if the emitter should stop spawning\r\n if (this._emitterLife > 0) {\r\n this._emitterLife -= this._frequency;\r\n if (this._emitterLife <= 0) {\r\n this._spawnTimer = 0;\r\n this._emitterLife = 0;\r\n this.emit = false;\r\n break;\r\n }\r\n }\r\n //determine if we have hit the particle limit\r\n if (this.particleCount >= this.maxParticles) {\r\n this._spawnTimer += this._frequency;\r\n continue;\r\n }\r\n //determine the particle lifetime\r\n var lifetime = void 0;\r\n if (this.minLifetime == this.maxLifetime)\r\n lifetime = this.minLifetime;\r\n else\r\n lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime;\r\n //only make the particle if it wouldn't immediately destroy itself\r\n if (-this._spawnTimer < lifetime) {\r\n //If the position has changed and this isn't the first spawn,\r\n //interpolate the spawn position\r\n var emitPosX = void 0, emitPosY = void 0;\r\n if (this._prevPosIsValid && this._posChanged) {\r\n //1 - _spawnTimer / delta, but _spawnTimer is negative\r\n var lerp = 1 + this._spawnTimer / delta;\r\n emitPosX = (curX - prevX) * lerp + prevX;\r\n emitPosY = (curY - prevY) * lerp + prevY;\r\n }\r\n else {\r\n emitPosX = curX;\r\n emitPosY = curY;\r\n }\r\n //create enough particles to fill the wave (non-burst types have a wave of 1)\r\n i = 0;\r\n for (var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) {\r\n //see if we actually spawn one\r\n if (this.spawnChance < 1 && Math.random() >= this.spawnChance)\r\n continue;\r\n //create particle\r\n var p = void 0;\r\n if (this._poolFirst) {\r\n p = this._poolFirst;\r\n this._poolFirst = this._poolFirst.next;\r\n p.next = null;\r\n }\r\n else {\r\n p = new this.particleConstructor(this);\r\n }\r\n //set a random texture if we have more than one\r\n if (this.particleImages.length > 1) {\r\n p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]);\r\n }\r\n else {\r\n //if they are actually the same texture, a standard particle\r\n //will quit early from the texture setting in setTexture().\r\n p.applyArt(this.particleImages[0]);\r\n }\r\n //set up the start and end values\r\n p.alphaList.reset(this.startAlpha);\r\n if (this.minimumSpeedMultiplier != 1) {\r\n p.speedMultiplier = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier;\r\n }\r\n p.speedList.reset(this.startSpeed);\r\n p.acceleration.x = this.acceleration.x;\r\n p.acceleration.y = this.acceleration.y;\r\n p.maxSpeed = this.maxSpeed;\r\n if (this.minimumScaleMultiplier != 1) {\r\n p.scaleMultiplier = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier;\r\n }\r\n p.scaleList.reset(this.startScale);\r\n p.colorList.reset(this.startColor);\r\n //randomize the rotation speed\r\n if (this.minRotationSpeed == this.maxRotationSpeed)\r\n p.rotationSpeed = this.minRotationSpeed;\r\n else\r\n p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed;\r\n p.noRotation = this.noRotation;\r\n //set up the lifetime\r\n p.maxLife = lifetime;\r\n //set the blend mode\r\n p.blendMode = this.particleBlendMode;\r\n //set the custom ease, if any\r\n p.ease = this.customEase;\r\n //set the extra data, if any\r\n p.extraData = this.extraData;\r\n //call the proper function to handle rotation and position of particle\r\n this._spawnFunc(p, emitPosX, emitPosY, i);\r\n //initialize particle\r\n p.init();\r\n //update the particle by the time passed, so the particles are spread out properly\r\n p.update(-this._spawnTimer); //we want a positive delta, because a negative delta messes things up\r\n //add the particle to the display list\r\n if (!p.parent) {\r\n if (this.addAtBack)\r\n this._parent.addChildAt(p, 0);\r\n else\r\n this._parent.addChild(p);\r\n }\r\n else {\r\n //kind of hacky, but performance friendly\r\n //shuffle children to correct place\r\n var children = this._parent.children;\r\n //avoid using splice if possible\r\n if (children[0] == p)\r\n children.shift();\r\n else if (children[children.length - 1] == p)\r\n children.pop();\r\n else {\r\n var index = children.indexOf(p);\r\n children.splice(index, 1);\r\n }\r\n if (this.addAtBack)\r\n children.unshift(p);\r\n else\r\n children.push(p);\r\n }\r\n //add particle to list of active particles\r\n if (this._activeParticlesLast) {\r\n this._activeParticlesLast.next = p;\r\n p.prev = this._activeParticlesLast;\r\n this._activeParticlesLast = p;\r\n }\r\n else {\r\n this._activeParticlesLast = this._activeParticlesFirst = p;\r\n }\r\n ++this.particleCount;\r\n }\r\n }\r\n //increase timer and continue on to any other particles that need to be created\r\n this._spawnTimer += this._frequency;\r\n }\r\n }\r\n //if the position changed before this update, then keep track of that\r\n if (this._posChanged) {\r\n this._prevEmitterPos.x = curX;\r\n this._prevEmitterPos.y = curY;\r\n this._prevPosIsValid = true;\r\n this._posChanged = false;\r\n }\r\n //if we are all done and should destroy ourselves, take care of that\r\n if (!this._emit && !this._activeParticlesFirst) {\r\n if (this._completeCallback) {\r\n this._completeCallback();\r\n }\r\n if (this._destroyWhenComplete) {\r\n this.destroy();\r\n }\r\n }\r\n };\r\n /**\r\n * Positions a particle for a point type emitter.\r\n * @method PIXI.particles.Emitter#_spawnPoint\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnPoint = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on\r\n //starting particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\r\n //drop the particle at the emitter's position\r\n p.position.x = emitPosX;\r\n p.position.y = emitPosY;\r\n };\r\n /**\r\n * Positions a particle for a rectangle type emitter.\r\n * @method PIXI.particles.Emitter#_spawnRect\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnRect = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation;\r\n //place the particle at a random point in the rectangle\r\n helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x;\r\n helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y;\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a circle type emitter.\r\n * @method PIXI.particles.Emitter#_spawnCircle\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnCircle = function (p, emitPosX, emitPosY) {\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\r\n this.minStartRotation + this.rotation;\r\n //place the particle at a random radius in the circle\r\n helperPoint.x = Math.random() * this.spawnCircle.radius;\r\n helperPoint.y = 0;\r\n //rotate the point to a random angle in the circle\r\n ParticleUtils_1.default.rotatePoint(Math.random() * 360, helperPoint);\r\n //offset by the circle's center\r\n helperPoint.x += this.spawnCircle.x;\r\n helperPoint.y += this.spawnCircle.y;\r\n //rotate the point by the emitter's rotation\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n //set the position, offset by the emitter's position\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a ring type emitter.\r\n * @method PIXI.particles.Emitter#_spawnRing\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave. Not used for this function.\r\n */\r\n Emitter.prototype._spawnRing = function (p, emitPosX, emitPosY) {\r\n var spawnCircle = this.spawnCircle;\r\n //set the initial rotation/direction of the particle based on starting\r\n //particle angle and rotation of emitter\r\n if (this.minStartRotation == this.maxStartRotation)\r\n p.rotation = this.minStartRotation + this.rotation;\r\n else\r\n p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) +\r\n this.minStartRotation + this.rotation;\r\n //place the particle at a random radius in the ring\r\n if (spawnCircle.minRadius == spawnCircle.radius) {\r\n helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) +\r\n spawnCircle.minRadius;\r\n }\r\n else\r\n helperPoint.x = spawnCircle.radius;\r\n helperPoint.y = 0;\r\n //rotate the point to a random angle in the circle\r\n var angle = Math.random() * 360;\r\n p.rotation += angle;\r\n ParticleUtils_1.default.rotatePoint(angle, helperPoint);\r\n //offset by the circle's center\r\n helperPoint.x += this.spawnCircle.x;\r\n helperPoint.y += this.spawnCircle.y;\r\n //rotate the point by the emitter's rotation\r\n if (this.rotation !== 0)\r\n ParticleUtils_1.default.rotatePoint(this.rotation, helperPoint);\r\n //set the position, offset by the emitter's position\r\n p.position.x = emitPosX + helperPoint.x;\r\n p.position.y = emitPosY + helperPoint.y;\r\n };\r\n /**\r\n * Positions a particle for a burst type emitter.\r\n * @method PIXI.particles.Emitter#_spawnBurst\r\n * @private\r\n * @param {Particle} p The particle to position and rotate.\r\n * @param {Number} emitPosX The emitter's x position\r\n * @param {Number} emitPosY The emitter's y position\r\n * @param {int} i The particle number in the current wave.\r\n */\r\n Emitter.prototype._spawnBurst = function (p, emitPosX, emitPosY, i) {\r\n //set the initial rotation/direction of the particle based on spawn\r\n //angle and rotation of emitter\r\n if (this.particleSpacing === 0)\r\n p.rotation = Math.random() * 360;\r\n else\r\n p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation;\r\n //drop the particle at the emitter's position\r\n p.position.x = emitPosX;\r\n p.position.y = emitPosY;\r\n };\r\n /**\r\n * Kills all active particles immediately.\r\n * @method PIXI.particles.Emitter#cleanup\r\n */\r\n Emitter.prototype.cleanup = function () {\r\n var particle, next;\r\n for (particle = this._activeParticlesFirst; particle; particle = next) {\r\n next = particle.next;\r\n this.recycle(particle);\r\n if (particle.parent)\r\n particle.parent.removeChild(particle);\r\n }\r\n this._activeParticlesFirst = this._activeParticlesLast = null;\r\n this.particleCount = 0;\r\n };\r\n /**\r\n * Destroys the emitter and all of its particles.\r\n * @method PIXI.particles.Emitter#destroy\r\n */\r\n Emitter.prototype.destroy = function () {\r\n //make sure we aren't still listening to any tickers\r\n this.autoUpdate = false;\r\n //puts all active particles in the pool, and removes them from the particle parent\r\n this.cleanup();\r\n //wipe the pool clean\r\n var next;\r\n for (var particle = this._poolFirst; particle; particle = next) {\r\n //store next value so we don't lose it in our destroy call\r\n next = particle.next;\r\n particle.destroy();\r\n }\r\n this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos =\r\n this.startColor = this.startScale = this.startAlpha = this.startSpeed =\r\n this.customEase = this._completeCallback = null;\r\n };\r\n return Emitter;\r\n}());\r\nexports.default = Emitter;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar PropertyList_1 = require(\"./PropertyList\");\r\nvar Sprite = PIXI.Sprite;\r\n/**\r\n * An individual particle image. You shouldn't have to deal with these.\r\n * @memberof PIXI.particles\r\n * @class Particle\r\n * @extends PIXI.Sprite\r\n * @constructor\r\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle.\r\n */\r\nvar Particle = /** @class */ (function (_super) {\r\n __extends(Particle, _super);\r\n function Particle(emitter) {\r\n var _this = \r\n //start off the sprite with a blank texture, since we are going to replace it\r\n //later when the particle is initialized.\r\n _super.call(this) || this;\r\n _this.emitter = emitter;\r\n //particles should be centered\r\n _this.anchor.x = _this.anchor.y = 0.5;\r\n _this.velocity = new PIXI.Point();\r\n _this.maxLife = 0;\r\n _this.age = 0;\r\n _this.ease = null;\r\n _this.extraData = null;\r\n _this.alphaList = new PropertyList_1.default();\r\n _this.speedList = new PropertyList_1.default();\r\n _this.speedMultiplier = 1;\r\n /**\r\n * Acceleration to apply to the particle.\r\n * @property {PIXI.Point} accleration\r\n */\r\n _this.acceleration = new PIXI.Point();\r\n /**\r\n * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\r\n * will disable the maximum speed.\r\n * @property {Number} maxSpeed\r\n * @default NaN\r\n */\r\n _this.maxSpeed = NaN;\r\n /**\r\n * The scale of the particle throughout its life.\r\n * @property {PIXI.particles.PropertyList} scaleList\r\n */\r\n _this.scaleList = new PropertyList_1.default();\r\n /**\r\n * A multiplier from 0-1 applied to the scale of the particle at all times.\r\n * @property {number} scaleMultiplier\r\n */\r\n _this.scaleMultiplier = 1;\r\n /**\r\n * The tint of the particle throughout its life.\r\n * @property {PIXI.particles.PropertyList} colorList\r\n */\r\n _this.colorList = new PropertyList_1.default(true);\r\n /**\r\n * If alpha should be interpolated at all.\r\n * @property {Boolean} _doAlpha\r\n * @private\r\n */\r\n _this._doAlpha = false;\r\n /**\r\n * If scale should be interpolated at all.\r\n * @property {Boolean} _doScale\r\n * @private\r\n */\r\n _this._doScale = false;\r\n /**\r\n * If speed should be interpolated at all.\r\n * @property {Boolean} _doSpeed\r\n * @private\r\n */\r\n _this._doSpeed = false;\r\n /**\r\n * If acceleration should be handled at all. _doSpeed is mutually exclusive with this,\r\n * and _doSpeed gets priority.\r\n * @property {Boolean} _doAcceleration\r\n * @private\r\n */\r\n _this._doAcceleration = false;\r\n /**\r\n * If color should be interpolated at all.\r\n * @property {Boolean} _doColor\r\n * @private\r\n */\r\n _this._doColor = false;\r\n /**\r\n * If normal movement should be handled. Subclasses wishing to override movement\r\n * can set this to false in init().\r\n * @property {Boolean} _doNormalMovement\r\n * @private\r\n */\r\n _this._doNormalMovement = false;\r\n /**\r\n * One divided by the max life of the particle, saved for slightly faster math.\r\n * @property {Number} _oneOverLife\r\n * @private\r\n */\r\n _this._oneOverLife = 0;\r\n /**\r\n * Reference to the next particle in the list.\r\n * @property {Particle} next\r\n * @private\r\n */\r\n _this.next = null;\r\n /**\r\n * Reference to the previous particle in the list.\r\n * @property {Particle} prev\r\n * @private\r\n */\r\n _this.prev = null;\r\n //save often used functions on the instance instead of the prototype for better speed\r\n _this.init = _this.init;\r\n _this.Particle_init = Particle.prototype.init;\r\n _this.update = _this.update;\r\n _this.Particle_update = Particle.prototype.update;\r\n _this.Sprite_destroy = _super.prototype.destroy;\r\n _this.Particle_destroy = Particle.prototype.destroy;\r\n _this.applyArt = _this.applyArt;\r\n _this.kill = _this.kill;\r\n return _this;\r\n }\r\n /**\r\n * Initializes the particle for use, based on the properties that have to\r\n * have been set already on the particle.\r\n * @method PIXI.particles.Particle#init\r\n */\r\n Particle.prototype.init = function () {\r\n //reset the age\r\n this.age = 0;\r\n //set up the velocity based on the start speed and rotation\r\n this.velocity.x = this.speedList.current.value * this.speedMultiplier;\r\n this.velocity.y = 0;\r\n ParticleUtils_1.default.rotatePoint(this.rotation, this.velocity);\r\n if (this.noRotation) {\r\n this.rotation = 0;\r\n }\r\n else {\r\n //convert rotation to Radians from Degrees\r\n this.rotation *= ParticleUtils_1.default.DEG_TO_RADS;\r\n }\r\n //convert rotation speed to Radians from Degrees\r\n this.rotationSpeed *= ParticleUtils_1.default.DEG_TO_RADS;\r\n //set alpha to inital alpha\r\n this.alpha = this.alphaList.current.value;\r\n //set scale to initial scale\r\n this.scale.x = this.scale.y = this.scaleList.current.value;\r\n //figure out what we need to interpolate\r\n this._doAlpha = !!this.alphaList.current.next;\r\n this._doSpeed = !!this.speedList.current.next;\r\n this._doScale = !!this.scaleList.current.next;\r\n this._doColor = !!this.colorList.current.next;\r\n this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0;\r\n //_doNormalMovement can be cancelled by subclasses\r\n this._doNormalMovement = this._doSpeed || this.speedList.current.value !== 0 || this._doAcceleration;\r\n //save our lerp helper\r\n this._oneOverLife = 1 / this.maxLife;\r\n //set the inital color\r\n var color = this.colorList.current.value;\r\n this.tint = ParticleUtils_1.default.combineRGBComponents(color.r, color.g, color.b);\r\n //ensure visibility\r\n this.visible = true;\r\n };\r\n /**\r\n * Sets the texture for the particle. This can be overridden to allow\r\n * for an animated particle.\r\n * @method PIXI.particles.Particle#applyArt\r\n * @param {PIXI.Texture} art The texture to set.\r\n */\r\n Particle.prototype.applyArt = function (art) {\r\n this.texture = art || PIXI.Texture.EMPTY;\r\n };\r\n /**\r\n * Updates the particle.\r\n * @method PIXI.particles.Particle#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle\r\n * properties. A value of -1 means the particle died of old age instead.\r\n */\r\n Particle.prototype.update = function (delta) {\r\n //increase age\r\n this.age += delta;\r\n //recycle particle if it is too old\r\n if (this.age >= this.maxLife) {\r\n this.kill();\r\n return -1;\r\n }\r\n //determine our interpolation value\r\n var lerp = this.age * this._oneOverLife; //lifetime / maxLife;\r\n if (this.ease) {\r\n if (this.ease.length == 4) {\r\n //the t, b, c, d parameters that some tween libraries use\r\n //(time, initial value, end value, duration)\r\n lerp = this.ease(lerp, 0, 1, 1);\r\n }\r\n else {\r\n //the simplified version that we like that takes\r\n //one parameter, time from 0-1. TweenJS eases provide this usage.\r\n lerp = this.ease(lerp);\r\n }\r\n }\r\n //interpolate alpha\r\n if (this._doAlpha)\r\n this.alpha = this.alphaList.interpolate(lerp);\r\n //interpolate scale\r\n if (this._doScale) {\r\n var scale = this.scaleList.interpolate(lerp) * this.scaleMultiplier;\r\n this.scale.x = this.scale.y = scale;\r\n }\r\n //handle movement\r\n if (this._doNormalMovement) {\r\n //interpolate speed\r\n if (this._doSpeed) {\r\n var speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\r\n ParticleUtils_1.default.normalize(this.velocity);\r\n ParticleUtils_1.default.scaleBy(this.velocity, speed);\r\n }\r\n else if (this._doAcceleration) {\r\n this.velocity.x += this.acceleration.x * delta;\r\n this.velocity.y += this.acceleration.y * delta;\r\n if (this.maxSpeed) {\r\n var currentSpeed = ParticleUtils_1.default.length(this.velocity);\r\n //if we are going faster than we should, clamp at the max speed\r\n //DO NOT recalculate vector length\r\n if (currentSpeed > this.maxSpeed) {\r\n ParticleUtils_1.default.scaleBy(this.velocity, this.maxSpeed / currentSpeed);\r\n }\r\n }\r\n }\r\n //adjust position based on velocity\r\n this.position.x += this.velocity.x * delta;\r\n this.position.y += this.velocity.y * delta;\r\n }\r\n //interpolate color\r\n if (this._doColor) {\r\n this.tint = this.colorList.interpolate(lerp);\r\n }\r\n //update rotation\r\n if (this.rotationSpeed !== 0) {\r\n this.rotation += this.rotationSpeed * delta;\r\n }\r\n else if (this.acceleration && !this.noRotation) {\r\n this.rotation = Math.atan2(this.velocity.y, this.velocity.x); // + Math.PI / 2;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Kills the particle, removing it from the display list\r\n * and telling the emitter to recycle it.\r\n * @method PIXI.particles.Particle#kill\r\n */\r\n Particle.prototype.kill = function () {\r\n this.emitter.recycle(this);\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.Particle#destroy\r\n */\r\n Particle.prototype.destroy = function () {\r\n if (this.parent)\r\n this.parent.removeChild(this);\r\n this.Sprite_destroy();\r\n this.emitter = this.velocity = this.colorList = this.scaleList = this.alphaList =\r\n this.speedList = this.ease = this.next = this.prev = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time.\r\n * @method PIXI.particles.Particle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\r\n * Any strings in the array will be converted to Textures via\r\n * Texture.fromImage().\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n Particle.parseArt = function (art) {\r\n //convert any strings to Textures.\r\n var i;\r\n for (i = art.length; i >= 0; --i) {\r\n if (typeof art[i] == \"string\")\r\n art[i] = PIXI.Texture.fromImage(art[i]);\r\n }\r\n //particles from different base textures will be slower in WebGL than if they\r\n //were from one spritesheet\r\n if (ParticleUtils_1.default.verbose) {\r\n for (i = art.length - 1; i > 0; --i) {\r\n if (art[i].baseTexture != art[i - 1].baseTexture) {\r\n if (window.console)\r\n console.warn(\"PixiParticles: using particle textures from different images may hinder performance in WebGL\");\r\n break;\r\n }\r\n }\r\n }\r\n return art;\r\n };\r\n /**\r\n * Parses extra emitter data to ensure it is set up for this particle class.\r\n * Particle does nothing to the extra data.\r\n * @method PIXI.particles.Particle.parseData\r\n * @static\r\n * @param {Object} extraData The extra data from the particle config.\r\n * @return {Object} The parsed extra data.\r\n */\r\n Particle.parseData = function (extraData) {\r\n return extraData;\r\n };\r\n return Particle;\r\n}(Sprite));\r\nexports.default = Particle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar BLEND_MODES = PIXI.BLEND_MODES;\r\nvar PropertyNode_1 = require(\"./PropertyNode\");\r\n/**\r\n * Contains helper functions for particles and emitters to use.\r\n * @memberof PIXI.particles\r\n * @class ParticleUtils\r\n * @static\r\n */\r\nvar ParticleUtils = {\r\n /**\r\n * If errors and warnings should be logged within the library.\r\n * @name PIXI.particles.ParticleUtils.verbose\r\n * @default false\r\n * @static\r\n */\r\n verbose: false,\r\n DEG_TO_RADS: Math.PI / 180,\r\n /**\r\n * Rotates a point by a given angle.\r\n * @method PIXI.particles.ParticleUtils.rotatePoint\r\n * @param {Number} angle The angle to rotate by in degrees\r\n * @param {PIXI.Point} p The point to rotate around 0,0.\r\n * @static\r\n */\r\n rotatePoint: function (angle, p) {\r\n if (!angle)\r\n return;\r\n angle *= ParticleUtils.DEG_TO_RADS;\r\n var s = Math.sin(angle);\r\n var c = Math.cos(angle);\r\n var xnew = p.x * c - p.y * s;\r\n var ynew = p.x * s + p.y * c;\r\n p.x = xnew;\r\n p.y = ynew;\r\n },\r\n /**\r\n * Combines separate color components (0-255) into a single uint color.\r\n * @method PIXI.particles.ParticleUtils.combineRGBComponents\r\n * @param {uint} r The red value of the color\r\n * @param {uint} g The green value of the color\r\n * @param {uint} b The blue value of the color\r\n * @return {uint} The color in the form of 0xRRGGBB\r\n * @static\r\n */\r\n combineRGBComponents: function (r, g, b /*, a*/) {\r\n return /*a << 24 |*/ r << 16 | g << 8 | b;\r\n },\r\n /**\r\n * Reduces the point to a length of 1.\r\n * @method PIXI.particles.ParticleUtils.normalize\r\n * @static\r\n * @param {PIXI.Point} point The point to normalize\r\n */\r\n normalize: function (point) {\r\n var oneOverLen = 1 / ParticleUtils.length(point);\r\n point.x *= oneOverLen;\r\n point.y *= oneOverLen;\r\n },\r\n /**\r\n * Multiplies the x and y values of this point by a value.\r\n * @method PIXI.particles.ParticleUtils.scaleBy\r\n * @static\r\n * @param {PIXI.Point} point The point to scaleBy\r\n * @param {number} value The value to scale by.\r\n */\r\n scaleBy: function (point, value) {\r\n point.x *= value;\r\n point.y *= value;\r\n },\r\n /**\r\n * Returns the length (or magnitude) of this point.\r\n * @method PIXI.particles.ParticleUtils.length\r\n * @static\r\n * @param {PIXI.Point} point The point to measure length\r\n * @return The length of this point.\r\n */\r\n length: function (point) {\r\n return Math.sqrt(point.x * point.x + point.y * point.y);\r\n },\r\n /**\r\n * Converts a hex string from \"#AARRGGBB\", \"#RRGGBB\", \"0xAARRGGBB\", \"0xRRGGBB\",\r\n * \"AARRGGBB\", or \"RRGGBB\" to an object of ints of 0-255, as\r\n * {r, g, b, (a)}.\r\n * @method PIXI.particles.ParticleUtils.hexToRGB\r\n * @param {string} color The input color string.\r\n * @param {Object} [output] An object to put the output in. If omitted, a new object is created.\r\n * @return The object with r, g, and b properties, possibly with an a property.\r\n * @static\r\n */\r\n hexToRGB: function (color, output) {\r\n if (!output)\r\n output = {};\r\n if (color.charAt(0) == \"#\")\r\n color = color.substr(1);\r\n else if (color.indexOf(\"0x\") === 0)\r\n color = color.substr(2);\r\n var alpha;\r\n if (color.length == 8) {\r\n alpha = color.substr(0, 2);\r\n color = color.substr(2);\r\n }\r\n output.r = parseInt(color.substr(0, 2), 16); //Red\r\n output.g = parseInt(color.substr(2, 2), 16); //Green\r\n output.b = parseInt(color.substr(4, 2), 16); //Blue\r\n if (alpha)\r\n output.a = parseInt(alpha, 16);\r\n return output;\r\n },\r\n /**\r\n * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated\r\n * by the related tool at http://www.greensock.com/customease/.\r\n * @method PIXI.particles.ParticleUtils.generateEase\r\n * @param {Array} segments An array of segments, as created by\r\n * http://www.greensock.com/customease/.\r\n * @return {Function} A function that calculates the percentage of change at\r\n * a given point in time (0-1 inclusive).\r\n * @static\r\n */\r\n generateEase: function (segments) {\r\n var qty = segments.length;\r\n var oneOverQty = 1 / qty;\r\n /*\r\n * Calculates the percentage of change at a given point in time (0-1 inclusive).\r\n * @param {Number} time The time of the ease, 0-1 inclusive.\r\n * @return {Number} The percentage of the change, 0-1 inclusive (unless your\r\n * ease goes outside those bounds).\r\n */\r\n return function (time) {\r\n var t, s;\r\n var i = (qty * time) | 0; //do a quick floor operation\r\n t = (time - (i * oneOverQty)) * qty;\r\n s = segments[i] || segments[qty - 1];\r\n return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s)));\r\n };\r\n },\r\n /**\r\n * Gets a blend mode, ensuring that it is valid.\r\n * @method PIXI.particles.ParticleUtils.getBlendMode\r\n * @param {string} name The name of the blend mode to get.\r\n * @return {int} The blend mode as specified in the PIXI.BLEND_MODES enumeration.\r\n * @static\r\n */\r\n getBlendMode: function (name) {\r\n if (!name)\r\n return BLEND_MODES.NORMAL;\r\n name = name.toUpperCase();\r\n while (name.indexOf(\" \") >= 0)\r\n name = name.replace(\" \", \"_\");\r\n return BLEND_MODES[name] || BLEND_MODES.NORMAL;\r\n },\r\n /**\r\n * Converts a list of {value, time} objects starting at time 0 and ending at time 1 into an evenly\r\n * spaced stepped list of PropertyNodes for color values. This is primarily to handle conversion of\r\n * linear gradients to fewer colors, allowing for some optimization for Canvas2d fallbacks.\r\n * @method PIXI.particles.ParticleUtils.createSteppedGradient\r\n * @param {Array} list The list of data to convert.\r\n * @param {number} [numSteps=10] The number of steps to use.\r\n * @return {PIXI.particles.PropertyNode} The blend mode as specified in the PIXI.blendModes enumeration.\r\n * @static\r\n */\r\n createSteppedGradient: function (list, numSteps) {\r\n if (numSteps === void 0) { numSteps = 10; }\r\n if (typeof numSteps !== 'number' || numSteps <= 0)\r\n numSteps = 10;\r\n var first = new PropertyNode_1.default(list[0].value, list[0].time);\r\n first.isStepped = true;\r\n var currentNode = first;\r\n var current = list[0];\r\n var nextIndex = 1;\r\n var next = list[nextIndex];\r\n for (var i = 1; i < numSteps; ++i) {\r\n var lerp = i / numSteps;\r\n //ensure we are on the right segment, if multiple\r\n while (lerp > next.time) {\r\n current = next;\r\n next = list[++nextIndex];\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - current.time) / (next.time - current.time);\r\n var curVal = ParticleUtils.hexToRGB(current.value);\r\n var nextVal = ParticleUtils.hexToRGB(next.value);\r\n var output = {};\r\n output.r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n output.g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n output.b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n currentNode.next = new PropertyNode_1.default(output, i / numSteps);\r\n currentNode = currentNode.next;\r\n }\r\n //we don't need to have a PropertyNode for time of 1, because in a stepped version at that point\r\n //the particle has died of old age\r\n return first;\r\n }\r\n};\r\nexports.default = ParticleUtils;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\nvar Particle_1 = require(\"./Particle\");\r\n/**\r\n * A helper point for math things.\r\n * @private\r\n */\r\nvar helperPoint = new PIXI.Point();\r\n//a hand picked list of Math functions (and a couple properties) that are allowable.\r\n//they should be used without the preceding \"Math.\"\r\nvar MATH_FUNCS = [\r\n \"pow\",\r\n \"sqrt\",\r\n \"abs\",\r\n \"floor\",\r\n \"round\",\r\n \"ceil\",\r\n \"E\",\r\n \"PI\",\r\n \"sin\",\r\n \"cos\",\r\n \"tan\",\r\n \"asin\",\r\n \"acos\",\r\n \"atan\",\r\n \"atan2\",\r\n \"log\"\r\n];\r\n//create an actual regular expression object from the string\r\nvar WHITELISTER = new RegExp([\r\n //Allow the 4 basic operations, parentheses and all numbers/decimals, as well\r\n //as 'x', for the variable usage.\r\n \"[01234567890\\\\.\\\\*\\\\-\\\\+\\\\/\\\\(\\\\)x ,]\",\r\n].concat(MATH_FUNCS).join(\"|\"), \"g\");\r\n/**\r\n * Parses a string into a function for path following.\r\n * This involves whitelisting the string for safety, inserting \"Math.\" to math function\r\n * names, and using `new Function()` to generate a function.\r\n * @method PIXI.particles.PathParticle~parsePath\r\n * @private\r\n * @static\r\n * @param {String} pathString The string to parse.\r\n * @return {Function} The path function - takes x, outputs y.\r\n */\r\nvar parsePath = function (pathString) {\r\n var matches = pathString.match(WHITELISTER);\r\n for (var i = matches.length - 1; i >= 0; --i) {\r\n if (MATH_FUNCS.indexOf(matches[i]) >= 0)\r\n matches[i] = \"Math.\" + matches[i];\r\n }\r\n pathString = matches.join(\"\");\r\n return new Function(\"x\", \"return \" + pathString + \";\");\r\n};\r\n/**\r\n * An particle that follows a path defined by an algebraic expression, e.g. \"sin(x)\" or\r\n * \"5x + 3\".\r\n * To use this class, the particle config must have a \"path\" string in the\r\n * \"extraData\" parameter. This string should have \"x\" in it to represent movement (from the\r\n * speed settings of the particle). It may have numbers, parentheses, the four basic\r\n * operations, and the following Math functions or properties (without the preceding \"Math.\"):\r\n * \"pow\", \"sqrt\", \"abs\", \"floor\", \"round\", \"ceil\", \"E\", \"PI\", \"sin\", \"cos\", \"tan\", \"asin\",\r\n * \"acos\", \"atan\", \"atan2\", \"log\".\r\n * The overall movement of the particle and the expression value become x and y positions for\r\n * the particle, respectively. The final position is rotated by the spawn rotation/angle of\r\n * the particle.\r\n *\r\n * Some example paths:\r\n *\r\n * \t\"sin(x/10) * 20\" // A sine wave path.\r\n * \t\"cos(x/100) * 30\" // Particles curve counterclockwise (for medium speed/low lifetime particles)\r\n * \t\"pow(x/10, 2) / 2\" // Particles curve clockwise (remember, +y is down).\r\n *\r\n * @memberof PIXI.particles\r\n * @class PathParticle\r\n * @extends PIXI.particles.Particle\r\n * @constructor\r\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle.\r\n */\r\nvar PathParticle = /** @class */ (function (_super) {\r\n __extends(PathParticle, _super);\r\n function PathParticle(emitter) {\r\n var _this = _super.call(this, emitter) || this;\r\n _this.path = null;\r\n _this.initialRotation = 0;\r\n _this.initialPosition = new PIXI.Point();\r\n _this.movement = 0;\r\n return _this;\r\n }\r\n /**\r\n * Initializes the particle for use, based on the properties that have to\r\n * have been set already on the particle.\r\n * @method PIXI.particles.PathParticle#init\r\n */\r\n PathParticle.prototype.init = function () {\r\n //get initial rotation before it is converted to radians\r\n this.initialRotation = this.rotation;\r\n //standard init\r\n this.Particle_init();\r\n //set the path for the particle\r\n this.path = this.extraData.path;\r\n //cancel the normal movement behavior\r\n this._doNormalMovement = !this.path;\r\n //reset movement\r\n this.movement = 0;\r\n //grab position\r\n this.initialPosition.x = this.position.x;\r\n this.initialPosition.y = this.position.y;\r\n };\r\n /**\r\n * Updates the particle.\r\n * @method PIXI.particles.PathParticle#update\r\n * @param {Number} delta Time elapsed since the previous frame, in __seconds__.\r\n */\r\n PathParticle.prototype.update = function (delta) {\r\n var lerp = this.Particle_update(delta);\r\n //if the particle died during the update, then don't bother\r\n if (lerp >= 0 && this.path) {\r\n //increase linear movement based on speed\r\n var speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\r\n this.movement += speed * delta;\r\n //set up the helper point for rotation\r\n helperPoint.x = this.movement;\r\n helperPoint.y = this.path(this.movement);\r\n ParticleUtils_1.default.rotatePoint(this.initialRotation, helperPoint);\r\n this.position.x = this.initialPosition.x + helperPoint.x;\r\n this.position.y = this.initialPosition.y + helperPoint.y;\r\n }\r\n return lerp;\r\n };\r\n /**\r\n * Destroys the particle, removing references and preventing future use.\r\n * @method PIXI.particles.PathParticle#destroy\r\n */\r\n PathParticle.prototype.destroy = function () {\r\n this.Particle_destroy();\r\n this.path = this.initialPosition = null;\r\n };\r\n /**\r\n * Checks over the art that was passed to the Emitter's init() function, to do any special\r\n * modifications to prepare it ahead of time. This just runs Particle.parseArt().\r\n * @method PIXI.particles.PathParticle.parseArt\r\n * @static\r\n * @param {Array} art The array of art data. For Particle, it should be an array of Textures.\r\n * Any strings in the array will be converted to Textures via\r\n * Texture.fromImage().\r\n * @return {Array} The art, after any needed modifications.\r\n */\r\n PathParticle.parseArt = function (art) {\r\n return Particle_1.default.parseArt(art);\r\n };\r\n /**\r\n * Parses extra emitter data to ensure it is set up for this particle class.\r\n * PathParticle checks for the existence of path data, and parses the path data for use\r\n * by particle instances.\r\n * @method PIXI.particles.PathParticle.parseData\r\n * @static\r\n * @param {Object} extraData The extra data from the particle config.\r\n * @return {Object} The parsed extra data.\r\n */\r\n PathParticle.parseData = function (extraData) {\r\n var output = {};\r\n if (extraData && extraData.path) {\r\n try {\r\n output.path = parsePath(extraData.path);\r\n }\r\n catch (e) {\r\n if (ParticleUtils_1.default.verbose)\r\n console.error(\"PathParticle: error in parsing path expression\");\r\n output.path = null;\r\n }\r\n }\r\n else {\r\n if (ParticleUtils_1.default.verbose)\r\n console.error(\"PathParticle requires a path string in extraData!\");\r\n output.path = null;\r\n }\r\n return output;\r\n };\r\n return PathParticle;\r\n}(Particle_1.default));\r\nexports.default = PathParticle;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\n/**\r\n * Singly linked list container for keeping track of interpolated properties for particles.\r\n * Each Particle will have one of these for each interpolated property.\r\n * @memberof PIXI.particles\r\n * @class PropertyList\r\n * @constructor\r\n * @param {boolean} isColor If this list handles color values\r\n */\r\nvar PropertyList = /** @class */ (function () {\r\n function PropertyList(isColor) {\r\n if (isColor === void 0) { isColor = false; }\r\n this.current = null;\r\n this.next = null;\r\n this.isColor = !!isColor;\r\n this.interpolate = null;\r\n this.ease = null;\r\n }\r\n /**\r\n * Resets the list for use.\r\n * @method interpolate\r\n * @param {PIXI.particles.PropertyNode} first The first node in the list.\r\n * @param {boolean} [isStepped=false] If the values should be stepped instead of interpolated linearly.\r\n */\r\n PropertyList.prototype.reset = function (first) {\r\n this.current = first;\r\n this.next = first.next;\r\n var isSimple = this.next && this.next.time >= 1;\r\n if (isSimple) {\r\n this.interpolate = this.isColor ? intColorSimple : intValueSimple;\r\n }\r\n else if (first.isStepped) {\r\n this.interpolate = this.isColor ? intColorStepped : intValueStepped;\r\n }\r\n else {\r\n this.interpolate = this.isColor ? intColorComplex : intValueComplex;\r\n }\r\n this.ease = this.current.ease;\r\n };\r\n return PropertyList;\r\n}());\r\nexports.default = PropertyList;\r\nfunction intValueSimple(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n return (this.next.value - this.current.value) * lerp + this.current.value;\r\n}\r\nfunction intColorSimple(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n var curVal = this.current.value, nextVal = this.next.value;\r\n var r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n var g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n var b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n return ParticleUtils_1.default.combineRGBComponents(r, g, b);\r\n}\r\nfunction intValueComplex(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\r\n return (this.next.value - this.current.value) * lerp + this.current.value;\r\n}\r\nfunction intColorComplex(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n //convert the lerp value to the segment range\r\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\r\n var curVal = this.current.value, nextVal = this.next.value;\r\n var r = (nextVal.r - curVal.r) * lerp + curVal.r;\r\n var g = (nextVal.g - curVal.g) * lerp + curVal.g;\r\n var b = (nextVal.b - curVal.b) * lerp + curVal.b;\r\n return ParticleUtils_1.default.combineRGBComponents(r, g, b);\r\n}\r\nfunction intValueStepped(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (this.next && lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n return this.current.value;\r\n}\r\nfunction intColorStepped(lerp) {\r\n if (this.ease)\r\n lerp = this.ease(lerp);\r\n //make sure we are on the right segment\r\n while (this.next && lerp > this.next.time) {\r\n this.current = this.next;\r\n this.next = this.next.next;\r\n }\r\n var curVal = this.current.value;\r\n return ParticleUtils_1.default.combineRGBComponents(curVal.r, curVal.g, curVal.b);\r\n}\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_1 = require(\"./ParticleUtils\");\r\n/**\r\n * A single node in a PropertyList.\r\n * @memberof PIXI.particles\r\n * @class PropertyNode\r\n * @constructor\r\n * @param {number|string} value The value for this node\r\n * @param {number} time The time for this node, between 0-1\r\n * @param {Function|Array} [ease] Custom ease for this list. Only relevant for the first node.\r\n */\r\nvar PropertyNode = /** @class */ (function () {\r\n function PropertyNode(value, time, ease) {\r\n this.value = typeof value == \"string\" ? ParticleUtils_1.default.hexToRGB(value) : value;\r\n this.time = time;\r\n this.next = null;\r\n this.isStepped = false;\r\n if (ease) {\r\n this.ease = typeof ease == \"function\" ? ease : ParticleUtils_1.default.generateEase(ease);\r\n }\r\n else {\r\n this.ease = null;\r\n }\r\n }\r\n /**\r\n * Creates a list of property values from a data object {list, isStepped} with a list of objects in\r\n * the form {value, time}. Alternatively, the data object can be in the deprecated form of\r\n * {start, end}.\r\n * @method PIXI.particles.PropertyNode.createListFromArray\r\n * @static\r\n * @param {Object} data The data for the list.\r\n * @param {Array} data.list The array of value and time objects.\r\n * @param {boolean} [data.isStepped] If the list is stepped rather than interpolated.\r\n * @param {Function|Array} [data.ease] Custom ease for this list.\r\n * @return {PIXI.particles.PropertyNode} The first node in the list\r\n */\r\n PropertyNode.createList = function (data) {\r\n if (Array.isArray(data.list)) {\r\n var array = data.list;\r\n var node = void 0, first = void 0;\r\n first = node = new PropertyNode(array[0].value, array[0].time, data.ease);\r\n //only set up subsequent nodes if there are a bunch or the 2nd one is different from the first\r\n if (array.length > 2 || (array.length === 2 && array[1].value !== array[0].value)) {\r\n for (var i = 1; i < array.length; ++i) {\r\n node.next = new PropertyNode(array[i].value, array[i].time);\r\n node = node.next;\r\n }\r\n }\r\n first.isStepped = !!data.isStepped;\r\n return first;\r\n }\r\n else {\r\n //Handle deprecated version here\r\n var start = new PropertyNode(data.start, 0);\r\n //only set up a next value if it is different from the starting value\r\n if (data.end !== data.start)\r\n start.next = new PropertyNode(data.end, 1);\r\n return start;\r\n }\r\n };\r\n return PropertyNode;\r\n}());\r\nexports.default = PropertyNode;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar ParticleUtils_js_1 = require(\"./ParticleUtils.js\");\r\nexports.ParticleUtils = ParticleUtils_js_1.default;\r\nvar Particle_js_1 = require(\"./Particle.js\");\r\nexports.Particle = Particle_js_1.default;\r\nvar Emitter_js_1 = require(\"./Emitter.js\");\r\nexports.Emitter = Emitter_js_1.default;\r\nvar PathParticle_js_1 = require(\"./PathParticle.js\");\r\nexports.PathParticle = PathParticle_js_1.default;\r\nvar AnimatedParticle_js_1 = require(\"./AnimatedParticle.js\");\r\nexports.AnimatedParticle = AnimatedParticle_js_1.default;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n// If we're in the browser make sure PIXI is available\r\nif (typeof PIXI === 'undefined') {\r\n throw \"pixi-particles requires pixi.js to be loaded first\";\r\n}\r\n//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not\r\nif (!PIXI.particles) {\r\n PIXI.particles = {};\r\n}\r\n// get the library itself\r\nvar particles = require(\"./particles\");\r\n// insert the library into the particles namespace on PIXI\r\nfor (var prop in particles) {\r\n PIXI.particles[prop] = particles[prop];\r\n}\r\n"],"sourceRoot":"."} \ No newline at end of file diff --git a/docs/examples/flameAndSmoke.html b/docs/examples/flameAndSmoke.html new file mode 100644 index 00000000..437e1b1b --- /dev/null +++ b/docs/examples/flameAndSmoke.html @@ -0,0 +1,96 @@ + + + + + + Flame and Smoke + + + + + + + + + + + + +
+
Click Anywhere
+ + + + \ No newline at end of file diff --git a/docs/examples/flameStepped.html b/docs/examples/flameStepped.html new file mode 100644 index 00000000..f1bbcdbf --- /dev/null +++ b/docs/examples/flameStepped.html @@ -0,0 +1,83 @@ + + + + + + Flame - Stepped for Fallback + + + + + + + + + + + + +
+
Click Anywhere
+ + + + \ No newline at end of file diff --git a/docs/examples/flameUneven.html b/docs/examples/flameUneven.html new file mode 100644 index 00000000..d8c2d9ad --- /dev/null +++ b/docs/examples/flameUneven.html @@ -0,0 +1,79 @@ + + + + + + Flame - Uneven + + + + + + + + + + + + +
+
Click Anywhere
+ + + + \ No newline at end of file diff --git a/docs/examples/index.html b/docs/examples/index.html index 6cc84cff..34c77176 100644 --- a/docs/examples/index.html +++ b/docs/examples/index.html @@ -18,6 +18,9 @@

Emitter Examples

  • Megaman Death
  • Rain
  • Flame
  • +
  • Flame - Stepped for Fallback
  • +
  • Flame And Smoke
  • +
  • Flame - Uneven
  • Gas
  • Bubbles
  • Bubble Spray
  • diff --git a/docs/examples/js/ParticleExample.js b/docs/examples/js/ParticleExample.js index 1ead0138..9cb88b4c 100644 --- a/docs/examples/js/ParticleExample.js +++ b/docs/examples/js/ParticleExample.js @@ -6,8 +6,11 @@ * @constructor * @param {String[]} imagePaths The local path to the image source * @param {Object} config The emitter configuration + * @param {null|"path"|"anim"} [type=null] Particle type to create. + * @param {boolean} [useParticleContainer=false] If a ParticleContainer should be used instead of a Container. + * @param {boolean} [stepColors=false] If the color settings should be manually stepped. */ - var ParticleExample = function(imagePaths, config, type, useParticleContainer) + var ParticleExample = function(imagePaths, config, type, useParticleContainer, stepColors) { var canvas = document.getElementById("stage"); // Basic PIXI Setup @@ -22,13 +25,13 @@ emitter = null, renderer = PIXI.autoDetectRenderer(canvas.width, canvas.height, rendererOptions), bg = null; - + var framerate = document.getElementById("framerate"); var particleCount = document.getElementById("particleCount"); // Calculate the current time var elapsed = Date.now(); - + var updateId; // Update function every frame @@ -40,11 +43,11 @@ var now = Date.now(); if (emitter) emitter.update((now - elapsed) * 0.001); - + framerate.innerHTML = (1000 / (now - elapsed)).toFixed(2); - + elapsed = now; - + if(emitter && particleCount) particleCount.innerHTML = emitter.particleCount; @@ -115,11 +118,13 @@ else emitterContainer = new PIXI.Container(); stage.addChild(emitterContainer); - emitter = new PIXI.particles.Emitter( + window.emitter = emitter = new PIXI.particles.Emitter( emitterContainer, art, config ); + if (stepColors) + emitter.startColor = PIXI.particles.ParticleUtils.createSteppedGradient(config.color.list, stepColors); if(type == "path") emitter.particleConstructor = PIXI.particles.PathParticle; else if(type == "anim") @@ -138,7 +143,7 @@ // Start the update update(); - + //for testing and debugging window.destroyEmitter = function() { @@ -146,11 +151,11 @@ emitter = null; window.destroyEmitter = null; //cancelAnimationFrame(updateId); - + //reset SpriteRenderer's batching to fully release particles for GC if (renderer.plugins && renderer.plugins.sprite && renderer.plugins.sprite.sprites) renderer.plugins.sprite.sprites.length = 0; - + renderer.render(stage); }; }); diff --git a/index.d.ts b/index.d.ts index 21dc61c1..395eaa7d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,8 +1,14 @@ // Typings for pixi-particles 2.1.9, requires Pixi.js typings declare namespace particles { - type TexSrc = string|PIXI.Texture; + type Color = {r:number, g:number, b:number}; + export interface ValueList { + list: {value:number|string, time:number}[], + isStepped?: boolean; + ease?: (lerp:number)=>number|EaseSegment[]; + } + export interface ParticleConstructor { new (emitter:Emitter):Particle; } @@ -39,7 +45,6 @@ declare namespace particles { private _prevEmitterPos:PIXI.Point; private _prevPosIsValid:boolean; private _posChanged:boolean; - private _parentIsPC:boolean; private _parent:PIXI.Container; private _emit:boolean; private _spawnTimer:number; @@ -54,18 +59,14 @@ declare namespace particles { private _completeCallback:()=>void; public particleImages:any[]; - public startAlpha:number; - public endAlpha:number; - public startSpeed:number; - public endSpeed:number; + public startAlpha:PropertyNode; + public startSpeed:PropertyNode; public minimumSpeedMultiplier:number; public acceleration:PIXI.Point; public maxSpeed:number; - public startScale:number; - public endScale:number; + public startScale:PropertyNode; public minimumScaleMultiplier:number; - public startColor:[number, number, number]; - public endColor:[number, number, number]; + public startColor:PropertyNode; public minLifetime:number; public maxLifetime:number; public minStartRotation:number; @@ -90,6 +91,7 @@ declare namespace particles { public addAtBack:boolean; public readonly particleCount:number; public frequency:number; + public spawnChance:number; public particleConstructor:ParticleConstructor; public parent:PIXI.Container; public emit:boolean; @@ -117,12 +119,6 @@ declare namespace particles { } export class Particle extends PIXI.Sprite { - private _sR:number; - private _sG:number; - private _sB:number; - private _eR:number; - private _eG:number; - private _eB:number; private _doAlpha:boolean; private _doScale:boolean; private _doSpeed:boolean; @@ -139,16 +135,12 @@ declare namespace particles { public age:number; public ease:(time:number)=>number; public extraData:any; - public startAlpha:number; - public endAlpha:number; - public startSpeed:number; - public endSpeed:number; + public alphaList:PropertyList; + public speedList:PropertyList; public acceleration:PIXI.Point; public maxSpeed:number; - public startScale:number; - public endScale:number; - public startColor:number[]; - public endColor:number[]; + public scaleList:PropertyList; + public colorList:PropertyList; /** Note that for Particle, the parameter is an array of strings or PIXI.Textures, and an array of Textures is returned. */ public static parseArt(art:any):any; @@ -183,6 +175,7 @@ declare namespace particles { public static hexToRGB(color:string, output?:[number, number, number]):[number, number, number]; public static generateEase(segments:EaseSegment[]):(time:number)=>number; public static getBlendMode(name:string):number; + public static createSteppedGradient(list:{value:string, time:number}, numSteps?:number):PropertyNode; } export class PathParticle extends Particle { @@ -194,6 +187,28 @@ declare namespace particles { public static parseArt(art:TexSrc[]):PIXI.Texture[]; public static parseData(data:{path:string}):any; } + + export class PropertyList { + public current: PropertyNode; + protected next: PropertyNode; + private isColor: boolean; + private ease: Function; + + constructor(isColor?:boolean); + public interpolate(lerp:number):number; + public reset(first:PropertyNode):void; + } + + export class PropertyNode { + public value: number|Color; + public time: number; + public next: PropertyNode; + public isStepped: boolean; + private interpolate: (lerp:number)=>number; + private ease: (lerp:number)=>number; + + public static createList(data:ValueList):PropertyNode; + } } export = particles; \ No newline at end of file diff --git a/jsdoc.conf.json b/jsdoc.conf.json index ae8763bd..a6eb1a16 100644 --- a/jsdoc.conf.json +++ b/jsdoc.conf.json @@ -4,7 +4,7 @@ }, "source": { "include": [ - "./src/" + "./ts-dist/" ], "includePattern": ".+\\.js(doc)?$", "excludePattern": "(^|\\/|\\\\)_" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..bc264916 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6085 @@ +{ + "name": "pixi-particles", + "version": "2.1.9", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@browserify/acorn5-object-spread": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@browserify/acorn5-object-spread/-/acorn5-object-spread-5.0.1.tgz", + "integrity": "sha512-sFCUPzgeEjdq3rinwy4TFXtak2YZdhqpj6MdNusxkdTFr9TXAUEYK4YQSamR8Joqt/yii1drgl5hk8q/AtJDKA==", + "dev": true, + "requires": { + "acorn": "5.4.1" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "@types/pixi.js": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@types/pixi.js/-/pixi.js-4.7.0.tgz", + "integrity": "sha512-3fNAhj/nwEP/w0+LKVezSxe1LO7k2N+zf99Si4ekghYgCQNps4yi2YbFL/ftPkHNKFtdqGpdN3Q/mxJ9EQImkA==", + "dev": true + }, + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "acorn-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", + "integrity": "sha512-efP54n3d1aLfjL2UMdaXa6DsswwzJeI5rqhbFvXMrKiJ6eJFpf+7R0zN7t8IC+XKn2YOAFAv6xbBNgHUkoHWLw==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=", + "dev": true + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", + "integrity": "sha512-Q4Rvn7P6ObyWfc4stqLWHtG1MJ8vVtjgT24Zbu+8UTzxYuZouqZsmNRRTFVMY/Ux0eIKv1d+JWzsInTX+fdHPQ==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.8.0", + "defined": "1.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3", + "umd": "3.0.1" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-13.3.0.tgz", + "integrity": "sha1-tanJAgJD8McORnW+yCI7xifkFc4=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "assert": "1.4.1", + "browser-pack": "6.0.4", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "0.0.1", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "labeled-stream-splicer": "2.0.0", + "module-deps": "4.1.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "0.10.31", + "subarg": "1.0.0", + "syntax-error": "1.4.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.1", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-derequire": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/browserify-derequire/-/browserify-derequire-0.9.4.tgz", + "integrity": "sha1-ZNYeVs/f8LjxdP2MV/i0Az4oeJU=", + "dev": true, + "requires": { + "derequire": "2.0.6", + "through2": "1.1.1" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "dev": true, + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collections": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "integrity": "sha1-HyMCay7zb5J+7MkB6ZxfDUj6M04=", + "dev": true, + "requires": { + "weak-map": "1.0.0" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "typedarray": "0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", + "dev": true, + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.10" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.6", + "randomfill": "1.0.3" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.38" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.0.4.tgz", + "integrity": "sha1-+gccXYdIRoVCSAdCHKSxawsaB2M=", + "dev": true, + "requires": { + "debug": "2.6.9", + "lazy-debug-legacy": "0.0.1", + "object-assign": "4.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", + "dev": true + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "derequire": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/derequire/-/derequire-2.0.6.tgz", + "integrity": "sha1-MaQUu3yhdiOfp4sRZjbvd9UX52g=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "concat-stream": "1.6.0", + "escope": "3.6.0", + "through2": "2.0.3", + "yargs": "6.6.0" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "defined": "1.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + } + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "stream-shift": "1.0.0" + } + }, + "earcut": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.3.tgz", + "integrity": "sha512-AxdCdWUk1zzK/NuZ7e1ljj6IGC+VAdC3Qb7QQDsXpfNrc5IM8tL9nNXUmEGE6jRHTfZ10zhzRhtDmWVsR5pd3A==", + "dev": true + }, + "ecstatic": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.2.0.tgz", + "integrity": "sha512-Goilx/2cfU9vvfQjgtNgc2VmJAD8CasQ6rZDqCd2u4Hsyd/qFET6nBf60jiHodevR3nl3IGzNKtrzPXWP88utQ==", + "dev": true, + "requires": { + "he": "1.1.1", + "mime": "1.6.0", + "minimist": "1.2.0", + "url-join": "2.0.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.9", + "doctrine": "2.1.0", + "escope": "3.6.0", + "espree": "3.5.3", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.17.1", + "is-resolvable": "1.1.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "espree": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + } + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "gh-pages": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-0.11.0.tgz", + "integrity": "sha1-kzE8bcv8dNQmvIminr/2QgrMPBs=", + "dev": true, + "requires": { + "async": "1.5.2", + "commander": "2.9.0", + "globby": "4.1.0", + "graceful-fs": "4.1.2", + "q": "1.4.1", + "q-io": "1.13.2", + "wrench": "1.5.8" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", + "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "6.0.4", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.2.tgz", + "integrity": "sha1-/iI5t1dJcuZ+QfgIgj+b+kqZHjc=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "gulp-header": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", + "integrity": "sha1-yfEP7gYy2B6Tl4nG7PRaFRvzCYs=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.5", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "gulp-if": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", + "dev": true, + "requires": { + "gulp-match": "1.0.3", + "ternary-stream": "2.0.1", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "gulp-preprocess": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-preprocess/-/gulp-preprocess-2.0.0.tgz", + "integrity": "sha1-Bnv2pOG3A9e0XtIEfOfofVl00kE=", + "dev": true, + "requires": { + "lodash": "3.10.1", + "map-stream": "0.1.0", + "preprocess": "3.1.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "gulp-sourcemaps": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.12.1.tgz", + "integrity": "sha1-tDfR89mAzyboEYSCNxjOFa5ll7Y=", + "dev": true, + "requires": { + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "4.0.13", + "convert-source-map": "1.1.3", + "css": "2.2.1", + "debug-fabulous": "0.0.4", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.6.1", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-uglify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-2.1.2.tgz", + "integrity": "sha1-bbhbHQ7mPRgFhZK2WGSdZcLsRUE=", + "dev": true, + "requires": { + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash": "4.17.5", + "make-error-cause": "1.2.2", + "through2": "2.0.3", + "uglify-js": "2.8.29", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + } + } + }, + "http-server": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", + "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "2.0.1", + "ecstatic": "3.2.0", + "http-proxy": "1.16.2", + "opener": "1.4.3", + "optimist": "0.6.1", + "portfinder": "1.0.13", + "union": "0.4.6" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.5", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.7.2", + "concat-stream": "1.5.2", + "is-buffer": "1.1.6", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + } + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-my-json-valid": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", + "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ismobilejs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-0.4.1.tgz", + "integrity": "sha1-Gl8SbHD+05yT2jgPpiy65XI+fcI=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "jaguarjs-jsdoc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jaguarjs-jsdoc/-/jaguarjs-jsdoc-1.1.0.tgz", + "integrity": "sha1-Pjz/ljvRLU5D1STZxgZxTiv6KQE=", + "dev": true, + "requires": { + "taffydb": "2.7.3", + "underscore": "1.8.3" + } + }, + "js-md5": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.4.2.tgz", + "integrity": "sha1-ihIx5gqzkqbTp1221TLsDFlme8M=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "dev": true, + "requires": { + "xmlcreate": "1.0.2" + } + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", + "dev": true, + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "3.5.1", + "catharsis": "0.8.9", + "escape-string-regexp": "1.0.5", + "js2xmlparser": "3.0.0", + "klaw": "2.0.0", + "marked": "0.3.12", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + }, + "dependencies": { + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + } + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazy-debug-legacy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz", + "integrity": "sha1-U3cWwHduTPeePtG2IfdljCkRsbE=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "make-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.3.tgz", + "integrity": "sha512-j3dZCri3cCd23wgPqK/0/KvTN8R+W6fXDqQe8BNLbTpONjbA8SPaRr+q0BQq9bx3Q/+g68/gDIh9FW3by702Tg==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "1.3.3" + } + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "marked": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz", + "integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mimeparse": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "integrity": "sha1-2vsCdSNw/SJgk64xUsJxrwGsJUo=", + "dev": true + }, + "mini-signals": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mini-signals/-/mini-signals-1.2.0.tgz", + "integrity": "sha1-RbCAE8X65RokqhqTXNMXye1yHXQ=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.7.1", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.4" + } + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "outpipe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", + "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", + "dev": true, + "requires": { + "shell-quote": "1.6.1" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-uri": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-uri/-/parse-uri-1.0.0.tgz", + "integrity": "sha1-KHLcwi8aeXrN4Vg9igrClVLdrCA=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pixi-gl-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/pixi-gl-core/-/pixi-gl-core-1.1.4.tgz", + "integrity": "sha1-i0tcQzsx5Bm8N53FZc4bg1qRs3I=", + "dev": true + }, + "pixi.js": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-4.7.0.tgz", + "integrity": "sha1-K5SAdY7q3KqfFDRCrYWSSt9MyTI=", + "dev": true, + "requires": { + "bit-twiddle": "1.0.2", + "earcut": "2.1.3", + "eventemitter3": "2.0.3", + "ismobilejs": "0.4.1", + "object-assign": "4.1.1", + "pixi-gl-core": "1.1.4", + "remove-array-items": "1.0.0", + "resource-loader": "2.1.1" + } + }, + "pixify": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/pixify/-/pixify-1.9.0.tgz", + "integrity": "sha1-YXsUpDANHwYPuy3ciitQKAEN1rI=", + "dev": true, + "requires": { + "browserify": "13.3.0", + "chalk": "1.1.3", + "gulp-header": "1.8.9", + "gulp-if": "2.0.2", + "gulp-preprocess": "2.0.0", + "gulp-sourcemaps": "1.12.1", + "gulp-uglify": "2.1.2", + "minimist": "1.2.0", + "vinyl-buffer": "1.0.1", + "vinyl-fs": "2.4.4", + "vinyl-source-stream": "1.1.2", + "watchify": "3.10.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preprocess": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/preprocess/-/preprocess-3.1.0.tgz", + "integrity": "sha1-pE5c3Vu7WlTwrSiaru2AmV19k4o=", + "dev": true, + "requires": { + "xregexp": "3.1.0" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.6" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "q-io": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.13.2.tgz", + "integrity": "sha1-7qEw1IHdteGqG8WmaFX3OR0G8AM=", + "dev": true, + "requires": { + "collections": "0.2.2", + "mime": "1.6.0", + "mimeparse": "0.1.4", + "q": "1.4.1", + "qs": "1.2.2", + "url2": "0.0.0" + } + }, + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.4", + "set-immediate-shim": "1.0.1" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-array-items": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.0.0.tgz", + "integrity": "sha1-B79CyzMvTPboXq2DteToltIyayE=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resource-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/resource-loader/-/resource-loader-2.1.1.tgz", + "integrity": "sha512-jRMGYUfa4AGk9ib45Wxc93lobhQVoiCUAUkWqsbb/fhGPge97YT1S8aC0xBEQpolMsrdmB3o7SH8VmIEvIDOLA==", + "dev": true, + "requires": { + "mini-signals": "1.2.0", + "parse-uri": "1.0.0" + } + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "sha.js": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.10" + }, + "dependencies": { + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + } + } + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.4" + } + }, + "stream-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "1.3.0" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.5", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "taffydb": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", + "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=", + "dev": true + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "fork-stream": "0.0.4", + "merge-stream": "1.0.1", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.1.tgz", + "integrity": "sha512-bqB1yS6o9TNA9ZC/MJxM0FZzPnZdtHj0xWK/IZ5khzVqdpGul/R/EIiHRgFXlwTD7PSIaYVnGKq1QgMCu2mnqw==", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "dev": true, + "requires": { + "qs": "2.3.3" + }, + "dependencies": { + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, + "url2": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "requires": { + "bl": "1.2.1", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.4", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "dev": true, + "requires": { + "through2": "2.0.3", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchify": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/watchify/-/watchify-3.10.0.tgz", + "integrity": "sha512-SRSumWalHAxciSaEtua1HFqB8L+et5ieHjJRuNssqj4qXz4pJoR6cAeFWni3reXyOY3cVE6b55sJ8WYR43abBQ==", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "browserify": "15.2.0", + "chokidar": "1.7.0", + "defined": "1.0.0", + "outpipe": "1.1.1", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + }, + "browserify": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-15.2.0.tgz", + "integrity": "sha512-IHYyFPm2XjJCL+VV0ZtFv8wn/sAHVOm83q3yfSn8YWbZ9jcybgPKxSDdiuMU+35jUL1914l74RnXXPD9Iyo9yg==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "assert": "1.4.1", + "browser-pack": "6.0.4", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.2.0", + "buffer": "5.0.8", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "1.0.0", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "labeled-stream-splicer": "2.0.0", + "mkdirp": "0.5.1", + "module-deps": "5.0.1", + "os-browserify": "0.3.0", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "subarg": "1.0.0", + "syntax-error": "1.4.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.1", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "buffer": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", + "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8" + } + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "detective": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.0.2.tgz", + "integrity": "sha512-NUsLoezj4wb9o7vpxS9F3L5vcO87ceyRBcl48op06YFNwkyIEY997JpSCA5lDlDuDc6JxOtaL5qfK3muoWxpMA==", + "dev": true, + "requires": { + "@browserify/acorn5-object-spread": "5.0.1", + "acorn": "5.4.1", + "defined": "1.0.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "module-deps": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-5.0.1.tgz", + "integrity": "sha512-sigq/hm/L+Z5IGi1DDl0x2ptkw7S86aFh213QhPLD8v9Opv90IHzKIuWJrRa5bJ77DVKHco2CfIEuThcT/vDJA==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.6.0", + "defined": "1.0.0", + "detective": "5.0.2", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "typedarray": "0.0.6" + } + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "weak-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "integrity": "sha1-tm5Wqd8L0lp2u/G1FNsSkIBhSjc=", + "dev": true + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wrench": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz", + "integrity": "sha1-ejHJf3hpJG12xc8vXJd6HEyOWrU=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", + "dev": true + }, + "xregexp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.0.tgz", + "integrity": "sha1-FNhGHgvdOCJL/uUDmgiY/EL80zY=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + } + } +} diff --git a/package.json b/package.json index e22a9d45..b20f2609 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,9 @@ "clean": "rimraf docs/docs docs/dist .publish", "lint": "eslint src", "prebuild": "npm run lint", - "build": "pixify --name pixi-particles -d dist --external false -p browserify-derequire", + "build": "tsc && pixify --name pixi-particles -s ts-dist -d dist --external false -p browserify-derequire", "postbuild": "ncp dist docs/dist", + "predocs": "ncp node_modules/pixi.js docs/examples/libs/pixi.js", "docs": "jsdoc -c jsdoc.conf.json -R README.md", "start": "npm run build -- --watch", "predocs-live": "npm run build && npm run docs && bower install", @@ -27,23 +28,27 @@ "publish:patch": "npm run version -- patch && npm publish", "publish:minor": "npm run version -- minor && npm publish", "publish:major": "npm run version -- major && npm publish", - "postpublish": "git push && git push --tags && npm run docs-live" + "postpublish": "git push && git push --tags && npm run docs-live", + "examples": "npm run predocs && http-server docs/" }, "peerDependencies": { "pixi.js": "*" }, "devDependencies": { + "@types/pixi.js": "^4.0.0", "browserify-derequire": "^0.9.4", "eslint": "^3.10.2", "gh-pages": "^0.11.0", "jaguarjs-jsdoc": "^1.0.0", "js-md5": "^0.4.1", "jsdoc": "^3.4.0", + "http-server": "*", + "ncp": "^2.0.0", "pixify": "^1.7.0", - "rimraf": "^2.5.4", "pixi.js": "^4.2.2", - "ncp": "^2.0.0", - "semver": "^5.3.0" + "rimraf": "^2.5.4", + "semver": "^5.3.0", + "typescript": "^2.7.0" }, "repository": { "type": "git", @@ -67,4 +72,4 @@ "particles" ], "license": "MIT" -} \ No newline at end of file +} diff --git a/pixi.js.d.ts b/pixi.js.d.ts deleted file mode 100644 index aa8d37c7..00000000 --- a/pixi.js.d.ts +++ /dev/null @@ -1,2989 +0,0 @@ -// Type definitions for Pixi.js 4.3.0 -// Project: https://github.com/pixijs/pixi.js/tree/dev -// Definitions by: clark-stevenson -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -declare module PIXI { - - // from CONST - export var VERSION: typeof CONST.VERSION; - export var PI_2: typeof CONST.PI_2; - export var RAD_TO_DEG: typeof CONST.RAD_TO_DEG; - export var DEG_TO_RAD: typeof CONST.DEG_TO_RAD; - export var RENDERER_TYPE: typeof CONST.RENDERER_TYPE; - export var BLEND_MODES: typeof CONST.BLEND_MODES; - export var DRAW_MODES: typeof CONST.DRAW_MODES; - export var SCALE_MODES: typeof CONST.SCALE_MODES; - export var WRAP_MODES: typeof CONST.WRAP_MODES; - export var TRANSFORM_MODE: typeof CONST.TRANSFORM_MODE; - export var PRECISION: typeof CONST.PRECISION; - export var TEXT_STYLE_CHANGED: typeof CONST.TEXT_STYLE_CHANGED; - export var GC_MODES: typeof CONST.GC_MODES; - export var SHAPES: typeof CONST.SHAPES; - export var TEXT_GRADIENT: typeof CONST.TEXT_GRADIENT; - - export function autoDetectRenderer(width: number, height: number, options?: PIXI.IRendererOptions, noWebGL?: boolean): PIXI.WebGLRenderer | PIXI.CanvasRenderer; - export var loader: PIXI.loaders.Loader; - - ////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////SETTINGS/////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module settings { - export var TARGET_FPMS: number; - export var MIPMAP_TEXTURES: boolean; - export var RESOLUTION: number; - export var FILTER_RESOLUTION: number; - export var SPRITE_MAX_TEXTURES: number; - export var SPRITE_BATCH_SIZE: number; - export var RETINA_PREFIX: RegExp; - export var RENDER_OPTIONS: { - view: HTMLCanvasElement, - antialias: boolean, - forceFXAA: boolean, - autoResize: boolean, - transparent: boolean, - backgroundColor: number, - clearBeforeRender: boolean, - preserveDrawingBuffer: boolean, - roundPixels: boolean - }; - export var TRANSFORM_MODE: number; - export var GC_MODE: number; - export var GC_MAX_IDLE: number; - export var GC_MAX_CHECK_COUNT: number; - export var WRAP_MODE: number; - export var SCALE_MODE: number; - export var PRECISION: string; - export var UPLOADS_PER_FRAME: number; - export var CAN_UPLOAD_SAME_BUFFER: boolean; - } - - ////////////////////////////////////////////////////////////////////////////// - /////////////////////////////ACCESSIBILITY//////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module accessibility { - - // accessibility - export class AccessibilityManager { - - constructor(renderer: CanvasRenderer | WebGLRenderer); - - protected div: HTMLElement; - protected pool: HTMLElement[]; - protected renderId: number; - debug: boolean; - renderer: SystemRenderer; - protected children: IAccessibleTarget[]; - protected isActive: boolean; - - protected activate(): void; - protected deactivate(): void; - protected updateAccessibleObjects(displayObject: DisplayObject): void; - protected update(): void; - protected capHitArea(hitArea: IHitArea): void; - protected addChild(displayObject: DisplayObject): void; - protected _onClick(e: interaction.InteractionEvent): void; - protected _onFocus(e: interaction.InteractionEvent): void; - protected _onFocusOut(e: interaction.InteractionEvent): void; - protected _onKeyDown(e: interaction.InteractionEvent): void; - protected _onMouseMove(): void; - - destroy(): void; - - } - export interface IAccessibleTarget { - - accessible: boolean; - accessibleTitle: string; - accessibleHint: string; - tabIndex: number; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////CORE////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - // const - - export module CONST { - export var VERSION: string; - export var PI_2: number; - export var RAD_TO_DEG: number; - export var DEG_TO_RAD: number; - export var TARGET_FPMS: number; - export var RENDERER_TYPE: { - UNKNOWN: number; - WEBGL: number; - CANVAS: number; - }; - export var BLEND_MODES: { - NORMAL: number; - ADD: number; - MULTIPLY: number; - SCREEN: number; - OVERLAY: number; - DARKEN: number; - LIGHTEN: number; - COLOR_DODGE: number; - COLOR_BURN: number; - HARD_LIGHT: number; - SOFT_LIGHT: number; - DIFFERENCE: number; - EXCLUSION: number; - HUE: number; - SATURATION: number; - COLOR: number; - LUMINOSITY: number; - }; - export var DRAW_MODES: { - POINTS: number; - LINES: number; - LINE_LOOP: number; - LINE_STRIP: number; - TRIANGLES: number; - TRIANGLE_STRIP: number; - TRIANGLE_FAN: number; - }; - export var SCALE_MODES: { - LINEAR: number, - NEAREST: number - }; - export var GC_MODES: { - AUTO: number; - MANUAL: number; - }; - export var WRAP_MODES: { - CLAMP: number; - MIRRORED_REPEAT: number; - REPEAT: number; - }; - export var TRANSFORM_MODE: { - DEFAULT: number; - DYNAMIC: number; - STATIC: number; - }; - export var URL_FILE_EXTENSION: RegExp | string; - export var DATA_URI: RegExp | string; - export var SVG_SIZE: RegExp | string; - export var SHAPES: { - POLY: number; - RECT: number; - CIRC: number; - ELIP: number; - RREC: number; - }; - export var PRECISION: { - LOW: string; - MEDIUM: string; - HIGH: string; - }; - export var TEXT_GRADIENT: { - LINEAR_VERTICAL: number; - LINEAR_HORIZONTAL: number; - }; - export var TEXT_STYLE_CHANGED: string; - - } - - // display - - export interface IDestroyOptions { - children?: boolean; - texture?: boolean; - baseTexture?: boolean; - } - export class Bounds { - - minX: number; - minY: number; - maxX: number; - maxY: number; - rect: Rectangle; - - isEmpty(): boolean; - clear(): void; - - getRectangle(rect?: Rectangle): Rectangle; - addPoint(point: Point): void; - addQuad(vertices: number[]): Bounds; - addFrame(transform: Transform, x0: number, y0: number, x1: number, y1: number): void; - addVertices(transform: Transform, vertices: number[], beginOffset: number, endOffset: number): void; - addBounds(bounds: Bounds): void; - addBoundsMask(bounds: Bounds, mask: Bounds): void; - addBoundsArea(bounds: Bounds, area: Rectangle): void; - - } - export class Container extends DisplayObject { - - // begin extras.getChildByName - getChildByName(name: string): DisplayObject; - // end extras.getChildByName - - children: DisplayObject[]; - width: number; - height: number; - - protected onChildrenChange: (...args: any[]) => void; - addChild(child: T, ...additionalChildren: DisplayObject[]): T; - addChildAt(child: T, index: number): T; - swapChildren(child: DisplayObject, child2: DisplayObject): void; - getChildIndex(child: DisplayObject): number; - setChildIndex(child: DisplayObject, index: number): void; - getChildAt(index: number): DisplayObject; - removeChild(child: DisplayObject): DisplayObject; - removeChildAt(index: number): DisplayObject; - removeChildren(beginIndex?: number, endIndex?: number): DisplayObject[]; - updateTransform(): void; - calculateBounds(): void; - protected _calculateBounds(): void; - protected containerUpdateTransform(): void; - renderWebGL(renderer: WebGLRenderer): void; - renderAdvancedWebGL(renderer: WebGLRenderer): void; - protected _renderWebGL(renderer: WebGLRenderer): void; - protected _renderCanvas(renderer: CanvasRenderer): void; - renderCanvas(renderer: CanvasRenderer): void; - destroy(options?: IDestroyOptions | boolean): void; - - once(event: "added", fn: (displayObject: DisplayObject) => void, context?: any): utils.EventEmitter; - once(event: "removed", fn: (DisplayObject: DisplayObject) => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - on(event: "added", fn: (displayObject: DisplayObject) => void, context?: any): utils.EventEmitter; - on(event: "removed", fn: (DisplayObject: DisplayObject) => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class DisplayObject extends utils.EventEmitter implements interaction.InteractiveTarget { - - // begin extras.cacheAsBitmap - protected _cacheAsBitmap: boolean; - protected _cacheData: boolean; - cacheAsBitmap: boolean; - protected _renderCachedWebGL(renderer: WebGLRenderer): void; - protected _initCachedDisplayObject(renderer: WebGLRenderer): void; - protected _renderCachedCanvas(renderer: CanvasRenderer): void; - protected _initCachedDisplayObjectCanvas(renderer: CanvasRenderer): void; - protected _calculateCachedBounds(): Rectangle; - protected _getCachedLocalBounds(): Rectangle; - protected _destroyCachedDisplayObject(): void; - protected _cacheAsBitmapDestroy(): void; - // end extras.cacheAsBitmap - - // begin extras.getChildByName - name: string; - // end extras.getChildByName - - // begin extras.getGlobalPosition - getGlobalPosition(point?: Point, skipUpdate?: boolean): Point; - // end extras.getGlobalPosition - - // begin accessible target - accessible: boolean; - accessibleTitle: string; - accessibleHint: string; - tabIndex: number; - // end accessible target - - // begin interactive target - interactive: boolean; - buttonMode: boolean; - hitArea: IHitArea; - interactiveChildren: boolean; - defaultCursor: string; - _isRightDown: boolean; - _isLeftDown: boolean; - // end interactive target - - transform: TransformBase; - alpha: number; - visible: boolean; - renderable: boolean; - parent: Container; - worldAlpha: number; - filterArea: Rectangle; - protected _filters: Filter[]; - protected _enabledFilters: Filter[]; - protected _bounds: Bounds; - protected _boundsID: number; - protected _lastBoundsID: number; - protected _boundsRect: Rectangle; - protected _localBoundsRect: Rectangle; - protected _mask: Rectangle; - x: number; - y: number; - worldTransform: Matrix; - localTransform: Matrix; - position: Point; - scale: Point; - pivot: Point; - skew: Point; - rotation: number; - worldVisible: boolean; - mask: PIXI.Graphics | PIXI.Sprite; - filters: Filter[]; - - updateTransform(): void; - protected displayObjectUpdateTransform(): void; - protected _recursivePostUpdateTransform(): void; - getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle; - getLocalBounds(rect?: Rectangle): Rectangle; - toGlobal(position: Point, point?: Point, skipUpdate?: boolean): Point; - toLocal(position: Point, from?: DisplayObject, point?: Point, skipUpdate?: boolean): Point; - protected renderWebGL(renderer: WebGLRenderer): void; - renderCanvas(renderer: CanvasRenderer): void; - setParent(container: Container): Container; - setTransform(x?: number, y?: number, scaleX?: number, scaleY?: number, rotation?: number, skewX?: number, skewY?: number, pivotX?: number, pivotY?: number): DisplayObject; - destroy(): void; - - on(event: string, fn: Function, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - /* - on(event: 'click', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mousedown', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mouseout', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mouseover', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mouseup', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mouseclick', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'mouseupoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'rightclick', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'rightdown', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'rightup', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'rightupoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'tap', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'touchend', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'touchendoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'touchmove', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - on(event: 'touchstart', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - - once(event: 'click', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mousedown', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mouseout', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mouseover', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mouseup', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mouseclick', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'mouseupoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'rightclick', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'rightdown', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'rightup', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'rightupoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'tap', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'touchend', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'touchendoutside', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'touchmove', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - once(event: 'touchstart', fn: (event: interaction.InteractionEvent) => void, context?: any): utils.EventEmitter; - */ - - } - - export class TransformBase { - - static IDENTITY: TransformBase; - - worldTransform: Matrix; - localTransform: Matrix; - protected _worldID: number; - updateLocalTransform(): void; - updateTransform(parentTransform: TransformBase): void; - updateWorldTransform(parentTransform: TransformBase): void; - - } - export class TransformStatic extends TransformBase { - - position: ObservablePoint; - scale: ObservablePoint; - pivot: ObservablePoint; - skew: ObservablePoint; - - protected _rotation: number; - protected _sr: number; - protected _cr: number; - protected _cy: number; - protected _sy: number; - protected _nsx: number; - protected _cx: number; - protected _currentLocalID: number; - - protected onChange(): void; - updateSkew(): void; - updateLocalTransform(): void; - updateTransform(parentTransform: TransformBase): void; - setFromMatrix(matrix: Matrix): void; - - rotation: number; - - } - export class Transform extends TransformBase { - - constructor(); - - position: Point; - scale: Point; - skew: ObservablePoint; - pivot: Point; - - protected _rotation: number; - protected _sr: number; - protected _cr: number; - protected _cy: number; - protected _sy: number; - protected _nsx: number; - protected _cx: number; - - updateSkew(): void; - setFromMatrix(matrix: Matrix): void; - - rotation: number; - - } - - // graphics - - export class GraphicsData { - - constructor(lineWidth: number, lineColor: number, lineAlpha: number, fillColor: number, fillAlpha: number, fill: boolean, shape: IShape | Circle | Rectangle | RoundedRectangle | Ellipse | Polygon); - - lineWidth: number; - lineColor: number; - lineAlpha: number; - protected _lineTint: number; - fillColor: number; - fillAlpha: number; - protected _fillTint: number; - fill: boolean; - protected holes: IShape[]; - shape: IShape | Circle | Rectangle | RoundedRectangle | Ellipse | Polygon; - type: number; - clone(): GraphicsData; - addHole(shape: IShape | Circle | Rectangle | RoundedRectangle | Ellipse | Polygon): void; - destroy(options?: IDestroyOptions | boolean): void; - - } - export class Graphics extends Container { - - fillAlpha: number; - lineWidth: number; - lineColor: number; - protected graphicsData: GraphicsData[]; - tint: number; - protected _prevTint: number; - blendMode: number; - currentPath: GraphicsData; - protected _webGL: any; - isMask: boolean; - boundsPadding: number; - protected _localBounds: Bounds; - dirty: boolean; - fastRectDirty: number; - clearDirty: number; - boundsDirty: number; - protected cachedSpriteDirty: boolean; - protected _spriteRect: Rectangle; - protected _fastRect: boolean; - - static _SPRITE_TEXTURE: Texture; - - clone(): Graphics; - lineStyle(lineWidth?: number, color?: number, alpha?: number): Graphics; - moveTo(x: number, y: number): Graphics; - lineTo(x: number, y: number): Graphics; - quadraticCurveTo(cpX: number, cpY: number, toX: number, toY: number): Graphics; - bezierCurveTo(cpX: number, cpY: number, cpX2: number, cpY2: number, toX: number, toY: number): Graphics; - arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): Graphics; - arc(cx: number, cy: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): Graphics; - beginFill(color: number, alpha?: number): Graphics; - endFill(): Graphics; - drawRect(x: number, y: number, width: number, height: number): Graphics; - drawRoundedRect(x: number, y: number, width: number, height: number, radius: number): Graphics; - drawCircle(x: number, y: number, radius: number): Graphics; - drawEllipse(x: number, y: number, width: number, height: number): Graphics; - drawPolygon(path: number[] | Point[]): Graphics; - clear(): Graphics; - isFastRect(): boolean; - protected _renderCanvas(renderer: CanvasRenderer): void; - protected _calculateBounds(): Rectangle; - protected _renderSpriteRect(renderer: PIXI.SystemRenderer): void; - containsPoint(point: Point): boolean; - updateLocalBounds(): void; - drawShape(shape: IShape | Circle | Rectangle | Ellipse | Polygon | RoundedRectangle): GraphicsData; - generateCanvasTexture(scaleMode?: number, resolution?: number): Texture; - protected closePath(): Graphics; - protected addHole(): Graphics; - destroy(options?: IDestroyOptions | boolean): void; - - } - export class CanvasGraphicsRenderer { - - constructor(renderer: SystemRenderer); - render(graphics: Graphics): void; - protected updateGraphicsTint(graphics: Graphics): void; - protected renderPolygon(points: Point[], close: boolean, context: CanvasRenderingContext2D): void; - destroy(): void; - - } - export class GraphicsRenderer extends ObjectRenderer { - - constructor(renderer: PIXI.CanvasRenderer); - - protected graphicsDataPool: GraphicsData[]; - protected primitiveShader: PrimitiveShader; - gl: WebGLRenderingContext; - - CONTEXT_UID: number; - - destroy(): void; - render(graphics: Graphics): void; - protected updateGraphics(graphics: PIXI.Graphics): void; - getWebGLData(webGL: WebGLRenderingContext, type: number): WebGLGraphicsData; - - } - export class WebGLGraphicsData { - - constructor(gl: WebGLRenderingContext, shader: glCore.GLShader, attribsState: glCore.IAttribState); - - gl: WebGLRenderingContext; - color: number[]; - points: Point[]; - indices: number[]; - buffer: WebGLBuffer; - indexBuffer: WebGLBuffer; - dirty: boolean; - glPoints: number[]; - glIndices: number[]; - shader: glCore.GLShader; - vao: glCore.VertexArrayObject; - - reset(): void; - upload(): void; - destroy(): void; - - } - export class PrimitiveShader extends glCore.GLShader { } - - // math - - export module GroupD8 { - - export var E: number; - export var SE: number; - export var S: number; - export var SW: number; - export var W: number; - export var NW: number; - export var N: number; - export var NE: number; - export var MIRROR_HORIZONTAL: number; - export var MIRROR_VERTICAL: number; - - export function uX(ind: number): number; - export function uY(ind: number): number; - export function vX(ind: number): number; - export function vY(ind: number): number; - export function inv(rotation: number): number; - export function add(rotationSecond: number, rotationFirst: number): number; - export function sub(rotationSecond: number, rotationFirst: number): number; - export function rotate180(rotation: number): number; - export function isSwapWidthHeight(rotation: number): boolean; - export function byDirection(dx: number, dy: number): number; - export function matrixAppendRotationInv(matrix: Matrix, rotation: number, tx: number, ty: number): void; - - } - export class Matrix { - - a: number; - b: number; - c: number; - d: number; - tx: number; - ty: number; - - fromArray(array: number[]): void; - set(a: number, b: number, c: number, d: number, tx: number, ty: number): Matrix; - toArray(transpose?: boolean, out?: number[]): number[]; - apply(pos: Point, newPos?: Point): Point; - applyInverse(pos: Point, newPos?: Point): Point; - translate(x: number, y: number): Matrix; - scale(x: number, y: number): Matrix; - rotate(angle: number): Matrix; - append(matrix: Matrix): Matrix; - setTransform(x: number, y: number, pivotX: number, pivotY: number, scaleX: number, scaleY: number, rotation: number, skewX: number, skewY: number): PIXI.Matrix; - prepend(matrix: Matrix): Matrix; - invert(): Matrix; - identity(): Matrix; - decompose(transform: TransformBase): TransformBase; - clone(): Matrix; - copy(matrix: Matrix): Matrix; - - static IDENTITY: Matrix; - static TEMP_MATRIX: Matrix; - - } - export class ObservablePoint { - - constructor(cb: Function, scope?: any, x?: number, y?: number); - - x: number; - y: number; - cb: () => void; - scope: any; - - set(x?: number, y?: number): void; - copy(point: Point | ObservablePoint): void; - - } - export class Point { - - constructor(x?: number, y?: number); - - x: number; - y: number; - - clone(): Point; - copy(p: Point): void; - equals(p: Point): boolean; - set(x?: number, y?: number): void; - - } - - export interface IShape { - } - export interface IHitArea extends IShape { - - contains(x: number, y: number): boolean; - - } - export class Circle { - - constructor(x?: number, y?: number, radius?: number); - - x: number; - y: number; - radius: number; - type: number; - - clone(): Circle; - contains(x: number, y: number): boolean; - getBounds(): Rectangle; - - } - export class Ellipse { - - constructor(x?: number, y?: number, width?: number, height?: number); - - x: number; - y: number; - width: number; - height: number; - type: number; - - clone(): Ellipse; - contains(x: number, y: number): boolean; - getBounds(): Rectangle; - - } - export class Polygon { - - constructor(points: Point[] | number[]); - constructor(...points: Point[]); - constructor(...points: number[]); - - closed: boolean; - points: number[]; - type: number; - - clone(): Polygon; - contains(x: number, y: number): boolean; - close(): void; - - } - export class Rectangle { - - constructor(x?: number, y?: number, width?: number, height?: number); - - x: number; - y: number; - width: number; - height: number; - type: number; - left: number; - right: number; - top: number; - bottom: number; - - static EMPTY: Rectangle; - - clone(): Rectangle; - copy(rectangle: Rectangle): Rectangle; - contains(x: number, y: number): boolean; - pad(paddingX: number, paddingY: number): void; - fit(rectangle: Rectangle): void; - enlarge(rect: Rectangle): void; - - } - export class RoundedRectangle { - - constructor(x?: number, y?: number, width?: number, height?: number, radius?: number); - - x: number; - y: number; - width: number; - height: number; - radius: number; - type: number; - - clone(): RoundedRectangle; - contains(x: number, y: number): boolean; - - } - - // renderers - - export interface IRendererOptions { - - view?: HTMLCanvasElement; - transparent?: boolean; - autoResize?: boolean; - antialias?: boolean; - resolution?: number; - clearBeforeRender?: boolean; - backgroundColor?: number; - roundPixels?: boolean; - context?: WebGLRenderingContext; - - } - export class SystemRenderer extends utils.EventEmitter { - - constructor(system: string, width?: number, height?: number, options?: IRendererOptions); - - type: number; - width: number; - height: number; - view: HTMLCanvasElement; - resolution: number; - transparent: boolean; - autoResize: boolean; - blendModes: any; // todo? - preserveDrawingBuffer: boolean; - clearBeforeRender: boolean; - roundPixels: boolean; - protected _backgroundColor: number; - protected _backgroundColorRgba: number[]; - protected _backgroundColorString: string; - protected _tempDisplayObjectParent: Container; - protected _lastObjectRendered: DisplayObject; - backgroundColor: number; - - resize(width: number, height: number): void; - generateTexture(displayObject: DisplayObject, scaleMode?: number, resolution?: number): RenderTexture; - render(...args: any[]): void; - destroy(removeView?: boolean): void; - - } - export class CanvasRenderer extends SystemRenderer { - - // plugintarget mixin start - static __plugins: any[]; - static registerPlugin(pluginName: string, ctor: Function): void; - plugins: any; - initPlugins(): void; - destroyPlugins(): void; - // plugintarget mixin end - - constructor(width?: number, height?: number, options?: IRendererOptions); - - rootContext: CanvasRenderingContext2D; - rootResolution: number; - refresh: boolean; - maskManager: CanvasMaskManager; - smoothProperty: string; - extract: extract.CanvasExtract; - - context: CanvasRenderingContext2D; - - render(displayObject: PIXI.DisplayObject, renderTexture?: PIXI.RenderTexture, clear?: boolean, transform?: PIXI.Transform, skipUpdateTransform?: boolean): void - setBlendMode(blendMode: number): void; - destroy(removeView?: boolean): void; - resize(w: number, h: number): void; - clear(clearColor?: string): void; - - on(event: "prerender", fn: () => void, context?: any): utils.EventEmitter; - on(event: "postrender", fn: () => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - once(event: "prerender", fn: () => void, context?: any): utils.EventEmitter; - once(event: "postrender", fn: () => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class CanvasMaskManager { - - constructor(renderer: CanvasRenderer); - - pushMask(maskData: any): void; - protected renderGraphicsShape(graphics: Graphics): void; - popMask(renderer: WebGLRenderer | CanvasRenderer): void; - destroy(): void; - - } - export class CanvasRenderTarget { - - constructor(width: number, height: number, resolution: number); - - canvas: HTMLCanvasElement; - context: CanvasRenderingContext2D; - resolution: number; - - width: number; - height: number; - - clear(): void; - resize(width: number, height: number): void; - destroy(): void; - - } - - export interface IWebGLRendererOptions { - - view?: HTMLCanvasElement; - transparent?: boolean; - autoResize?: boolean; - antialias?: boolean; - forceFXAA?: boolean; - resolution?: number; - clearBeforeRender?: boolean; - preserveDrawingBuffer?: boolean; - roundPixels?: boolean; - - } - export class WebGLRenderer extends SystemRenderer { - - // plugintarget mixin start - static __plugins: any[]; - static registerPlugin(pluginName: string, ctor: Function): void; - plugins: any; - initPlugins(): void; - destroyPlugins(): void; - // plugintarget mixin end - - constructor(width?: number, height?: number, options?: IWebGLRendererOptions); - - protected _contextOptions: { - alpha: boolean; - antiAlias: boolean; - premultipliedAlpha: boolean; - stencil: boolean; - preseveDrawingBuffer: boolean; - }; - protected _backgroundColorRgba: number[]; - maskManager: MaskManager; - stencilManager: StencilManager; - emptyRenderer: ObjectRenderer; - currentRenderer: ObjectRenderer; - gl: WebGLRenderingContext; - CONTEXT_UID: number; - state: WebGLState; - renderingToScreen: boolean; - boundTextures: Texture[]; - filterManager: FilterManager; - textureManager: TextureManager; - extract: extract.WebGLExtract; - protected drawModes: any; - protected _activeShader: Shader; - _activeRenderTarget: RenderTarget; - protected _initContext(): void; - - render(displayObject: PIXI.DisplayObject, renderTexture?: PIXI.RenderTexture, clear?: boolean, transform?: PIXI.Transform, skipUpdateTransform?: boolean): void - setObjectRenderer(objectRenderer: ObjectRenderer): void; - flush(): void; - resize(width: number, height: number): void; - setBlendMode(blendMode: number): void; - clear(clearColor?: number): void; - setTransform(matrix: Matrix): void; - bindRenderTexture(renderTexture: RenderTexture, transform: Transform): WebGLRenderer; - bindRenderTarget(renderTarget: RenderTarget): WebGLRenderer; - bindShader(shader: Shader): WebGLRenderer; - bindTexture(texture: Texture | BaseTexture, location?: number, forceLocation?: boolean): number; - unbindTexture(texture: Texture | BaseTexture): WebGLRenderer; - createVao(): glCore.VertexArrayObject; - bindVao(vao: glCore.VertexArrayObject): WebGLRenderer; - reset(): WebGLRenderer; - handleContextLost: (event: WebGLContextEvent) => void; - handleContextRestored: () => void; - destroy(removeView?: boolean): void; - - on(event: "context", fn: (gl: WebGLRenderingContext) => void, context?: any): utils.EventEmitter; - on(event: "prerender", fn: () => void, context?: any): utils.EventEmitter; - on(event: "postrender", fn: () => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - once(event: "context", fn: (gl: WebGLRenderingContext) => void, context?: any): utils.EventEmitter; - once(event: "prerender", fn: () => void, context?: any): utils.EventEmitter; - once(event: "postrender", fn: () => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class WebGLState { - - constructor(gl: WebGLRenderingContext); - - activeState: number[]; - defaultState: number[]; - stackIndex: number; - stack: number[]; - gl: WebGLRenderingContext; - maxAttribs: number; - attribState: glCore.IAttribState; - nativeVaoExtension: any; - - push(): void; - pop(): void; - setState(state: number[]): void; - setBlend(value: number): void; - setBlendMode(value: number): void; - setDepthTest(value: number): void; - setCullFace(value: number): void; - setFrontFace(value: number): void; - resetAttributes(): void; - resetToDefault(): void; - - } - export class TextureManager { - - constructor(renderer: WebGLRenderer); - - renderer: WebGLRenderer; - gl: WebGLRenderingContext; - protected _managedTextures: WebGLTexture[]; - - bindTexture(): void; - getTexture(): WebGLTexture; - updateTexture(texture: BaseTexture | Texture): WebGLTexture; - destroyTexture(texture: BaseTexture, _skipRemove?: boolean): void; - removeAll(): void; - destroy(): void; - - } - export class TextureGarbageCollector { - - constructor(renderer: WebGLRenderer); - - renderer: WebGLRenderer; - count: number; - checkCount: number; - maxIdle: number; - checkCountMax: number; - mode: number; - - update(): void; - run(): void; - unload(): void; - - } - export abstract class ObjectRenderer extends WebGLManager { - - constructor(renderer: WebGLRenderer); - - start(): void; - stop(): void; - flush(): void; - - render(...args: any[]): void; - - } - export class Quad { - - constructor(gl: WebGLRenderingContext); - - gl: WebGLRenderingContext; - vertices: number[]; - uvs: number[]; - interleaved: number[]; - indices: number[]; - vertexBuffer: WebGLBuffer; - vao: glCore.VertexArrayObject; - initVao(shader: glCore.GLShader): void; - map(targetTextureFrame: Rectangle, destinationFrame: Rectangle): Quad; - upload(): Quad; - destroy(): void; - - } - export class RenderTarget { - - constructor(gl: WebGLRenderingContext, width: number, height: number, scaleMode: number, resolution: number, root?: boolean); - - gl: WebGLRenderingContext; - frameBuffer: glCore.GLFramebuffer; - texture: Texture; - clearColor: number[]; - size: Rectangle; - resolution: number; - projectionMatrix: Matrix; - transform: Matrix; - frame: Rectangle; - defaultFrame: Rectangle; - destinationFrame: Rectangle; - sourceFrame: Rectangle; - stencilBuffer: glCore.GLFramebuffer; - stencilMaskStack: Graphics[]; - filterData: { - index: number, - stack: { - renderTarget: RenderTarget, - filter: any[]; - bounds: Rectangle - }[] - }; - scaleMode: number; - root: boolean; - - clear(clearColor?: number[]): void; - attachStencilBuffer(): void; - setFrame(destinationFrame: Rectangle, sourceFrame: Rectangle): void; - activate(): void; - calculateProjection(destinationFrame: Rectangle, sourceFrame: Rectangle): void; - resize(width: number, height: number): void; - destroy(): void; - - } - - export class BlendModeManager extends WebGLManager { - - constructor(renderer: WebGLRenderer); - - currentBlendMode: number; - - setBlendMode(blendMode: number): boolean; - - } - export class FilterManager extends WebGLManager { - - constructor(renderer: WebGLRenderer); - - gl: WebGLRenderingContext; - quad: Quad; - stack: { - renderTarget: RenderTarget; - sourceFrame: Rectangle; - destinationFrame: Rectangle; - filters: Filter[]; - target: any; - resolution: number; - }[]; - stackIndex: number; - shaderCache: any; - filterData: any; - - pushFilter(target: RenderTarget, filters: Filter[]): void; - popFilter(): void; - applyFilter(shader: glCore.GLShader | Filter, inputTarget: RenderTarget, outputTarget: RenderTarget, clear?: boolean): void; - syncUniforms(shader: glCore.GLShader, filter: Filter): void; - getRenderTarget(clear?: boolean, resolution?: number): RenderTarget; - returnRenderTarget(renderTarget: RenderTarget): RenderTarget; - calculateScreenSpaceMatrix(outputMatrix: Matrix): Matrix; - calculateNormalisedScreenSpaceMatrix(outputMatrix: Matrix): Matrix; - calculateSpriteMatrix(outputMatrix: Matrix, sprite: Sprite): Matrix; - destroy(): void; - emptyPool(): void; - getPotRenderTarget(gl: WebGLRenderingContext, minWidth: number, minHeight: number, resolution: number): RenderTarget; - freePotRenderTarget(renderTarget: RenderTarget): void; - - } - export class StencilMaskStack { - - stencilStack: any[]; - reverse: boolean; - count: number; - - } - export class MaskManager extends WebGLManager { - - scissor: boolean; - scissorData: any; - scissorRenderTarget: RenderTarget; - enableScissor: boolean; - alphaMaskPool: number[]; - alphaMaskIndex: number; - pushMask(target: RenderTarget, maskData: Sprite | Graphics): void; - popMask(target: RenderTarget, maskData: Sprite | Graphics): void; - pushSpriteMask(target: RenderTarget, maskData: Sprite | Graphics): void; - popSpriteMask(): void; - pushStencilMask(maskData: Sprite | Graphics): void; - popStencilMask(): void; - pushScissorMask(target: RenderTarget, maskData: Sprite | Graphics): void; - popScissorMask(): void; - - } - export class StencilManager extends WebGLManager { - - constructor(renderer: WebGLRenderer); - - stencilMaskStack: Graphics[]; - - setMaskStack(stencilMasStack: Graphics[]): void; - pushStencil(graphics: Graphics): void; - popStencil(): void; - destroy(): void; - - } - export class WebGLManager { - - constructor(renderer: WebGLRenderer); - - renderer: WebGLRenderer; - onContextChange(): void; - destroy(): void; - - } - export interface IUniformData { - - type: string; - value: any; - - // name is set by pixi if uniforms were automatically extracted from shader code, but not used anywhere - name?: string; - - } - export class Filter { - - // param uniforms should be an object matching type {[name: string]: IUniformData}; - // left untyped as there's no way to define the type without requiring an index signature or making this class generic - constructor(vertexSrc?: string, fragmentSrc?: string, uniforms?: any); - - vertextSrc: string; - fragmentSrc: string; - protected uniformData: { [name: string]: IUniformData }; - uniforms: { [name: string]: any }; - glShaders: any; - glShaderKey: string; - padding: number; - resolution: number; - blendMode: number; - enabled: boolean; - apply(filterManager: FilterManager, input: RenderTarget, output: RenderTarget, clear?: boolean): void; - - static defaultVertexSrc: string; - static defaultFragmentSrc: string; - - } - export class SpriteMaskFilter extends Filter { - - constructor(sprite: Sprite); - - maskSprite: Sprite; - maskMatrix: Matrix; - apply(filterManager: FilterManager, input: RenderTarget, output: RenderTarget): void; - - } - - // sprites - - export class Sprite extends Container { - - constructor(texture?: Texture); - - protected _anchor: ObservablePoint; - anchor: ObservablePoint; - protected _texture: Texture; - protected _width: number; - protected _height: number; - tint: number; - protected _tint: number; - protected _tintRGB: number; - blendMode: number; - pluginName: string; - protected cachedTint: number; - texture: Texture; - protected textureDirty: boolean; - protected _textureID: number; - protected _transformID: number; - protected vertexTrimmedData: Float32Array; - vertexData: Float32Array; - width: number; - height: number; - - protected _onTextureUpdate(): void; - calculateVertices(): void; - protected _calculateBounds(): void; - protected calculateTrimmedVertices(): void; - protected onAnchorUpdate(): void; - protected _renderWebGL(renderer: WebGLRenderer): void; - protected _renderCanvas(renderer: CanvasRenderer): void; - getLocalBounds(): Rectangle; - containsPoint(point: Point): boolean; - destroy(options?: IDestroyOptions | boolean): void; - - static from(source: number | string | BaseTexture | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement): Sprite; - static fromFrame(frameId: string): Sprite; - static fromImage(imageId: string, crossorigin?: boolean, scaleMode?: number): Sprite; - - } - export class BatchBuffer { - - vertices: ArrayBuffer; - float32View: number[]; - uint32View: number[]; - - destroy(): void; - - } - export class SpriteRenderer extends ObjectRenderer { - - constructor(renderer: PIXI.WebGLRenderer); - - vertSize: number; - vertByteSize: number; - size: number; - buffers: BatchBuffer[]; - indices: number[]; - shaders: Shader[]; - currentIndex: number; - tick: number; - groups: any[]; - sprites: Sprite[]; - vertexBuffers: number[]; - vaos: glCore.VertexArrayObject[]; - vaoMax: number; - vertexCount: number; - - protected onContextChanged: () => void; - protected onPrerender: () => void; - render(sprite: Sprite): void; - flush(): void; - start(): void; - stop(): void; - destroy(): void; - - } - export class CanvasSpriteRenderer extends ObjectRenderer { - - constructor(renderer: WebGLRenderer); - - render(sprite: Sprite): void; - destroy(): void; - - } - export module CanvasTinter { - - export function getTintedTexture(sprite: Sprite, color: number): HTMLCanvasElement; - export function tintWithMultiply(texture: Texture, color: number, canvas: HTMLCanvasElement): void; - export function tintWithOverlay(texture: Texture, color: number, canvas: HTMLCanvasElement): void; - export function tintWithPerPixel(texture: Texture, color: number, canvas: HTMLCanvasElement): void; - export function roundColor(color: number): number; - - export var cacheStepsPerColorChannel: number; - export var convertTintToImage: boolean; - export var canUseMultiply: boolean; - export var tintMethod: Function; - - } - - // text - export interface ITextStyleStyle { - align?: string; - breakWords?: boolean; - dropShadow?: boolean; - dropShadowAngle?: number; - dropShadowBlur?: number; - dropShadowColor?: string | number; - dropShadowDistance?: number; - fill?: string | string[] | number | number[] | CanvasGradient | CanvasPattern; - fillGradientType?: number; - fontFamily?: string | string[]; - fontSize?: number | string; - fontStyle?: string; - fontVariant?: string; - fontWeight?: string; - letterSpacing?: number; - lineHeight?: number; - lineJoin?: string; - miterLimit?: number; - padding?: number; - stroke?: string | number; - strokeThickness?: number; - styleID?: number; - textBaseline?: string; - wordWrap?: boolean; - wordWrapWidth?: number; - } - - export class TextStyle implements ITextStyleStyle { - align: string; - breakWords: boolean; - dropShadow: boolean; - dropShadowAngle: number; - dropShadowBlur: number; - dropShadowColor: string | number; - dropShadowDistance: number; - fill: string | string[] | number | number[] | CanvasGradient | CanvasPattern; - fillGradientType: number; - fontFamily: string | string[]; - fontSize: number | string; - fontStyle: string; - fontVariant: string; - fontWeight: string; - letterSpacing: number; - lineHeight: number; - lineJoin: string; - miterLimit: number; - padding: number; - stroke: string | number; - strokeThickness: number; - styleID: number; - textBaseline: string; - wordWrap: boolean; - wordWrapWidth: number; - constructor(style?: ITextStyleStyle); - public clone(): TextStyle; - public reset(): void; - } - - export class Text extends Sprite { - - static getFontStyle(style: ITextStyleStyle): string; - static calculateFontProperties(style: string): any; - - constructor(text?: string, style?: ITextStyleStyle, canvas?: HTMLCanvasElement); - - canvas: HTMLCanvasElement; - context: CanvasRenderingContext2D; - resolution: number; - protected _text: string; - protected _style: TextStyle; - protected _styleListener: Function; - protected _font: string; - protected localStyleID: number; - - static fontPropertiesCache: any; - static fontPropertiesCanvas: HTMLCanvasElement; - static fontPropertiesContext: CanvasRenderingContext2D; - - width: number; - height: number; - style: TextStyle; - text: string; - - protected updateText(respectDirty?: boolean): void; - protected drawLetterSpacing(text: string, x: number, y: number, isStroke?: boolean): void; - protected updateTexture(): void; - renderWebGL(renderer: WebGLRenderer): void; - protected _renderCanvas(renderer: CanvasRenderer): void; - protected wordWrap(text: string): string; - protected _calculateBounds(): void; - protected _onStyleChange: () => void; - protected _generateFillStyle(style: TextStyle, lines: string[]): string | number | CanvasGradient; - destroy(options?: IDestroyOptions | boolean): void; - dirty: boolean; - - } - - // textures - - export class BaseRenderTexture extends BaseTexture { - - constructor(width?: number, height?: number, scaleMode?: number, resolution?: number); - - height: number; - width: number; - realHeight: number; - realWidth: number; - resolution: number; - scaleMode: number; - hasLoaded: boolean; - protected _glRenderTargets: { [n: number]: WebGLTexture; }; - protected _canvasRenderTarget: { [n: number]: WebGLTexture; }; - valid: boolean; - - resize(width: number, height: number): void; - destroy(): void; - - once(event: "update", fn: (baseRenderTexture: BaseRenderTexture) => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - on(event: "update", fn: (baseRenderTexture: BaseRenderTexture) => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class BaseTexture extends utils.EventEmitter { - - constructor(source?: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, scaleMode?: number, resolution?: number); - - protected uuid: number; - protected touched: number; - resolution: number; - width: number; - height: number; - realWidth: number; - realHeight: number; - scaleMode: number; - hasLoaded: boolean; - isLoading: boolean; - wrapMode: number; - source: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement; - origSource: HTMLImageElement; - imageType: string; - sourceScale: number; - premultipliedAlpha: boolean; - imageUrl: string; - protected isPowerOfTwo: boolean; - mipmap: boolean; - wrap: boolean; - protected _glTextures: any; - protected _enabled: number; - protected _id: number; - - update(): void; - protected _updateImageType(): void; - protected _loadSvgSource(): void; - protected _loadSvgSourceUsingDataUri(dataUri: string): void; - protected _loadSvgSourceUsingXhr(): void; - protected _loadSvgSourceUsingString(svgString: string): void; - protected loadSource(source: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement): void; - protected _sourceLoaded(): void; - destroy(): void; - dispose(): void; - updateSourceImage(newSrc: string): void; - - static fromImage(imageUrl: string, crossorigin?: boolean, scaleMode?: number, sourceScale?: number): BaseTexture; - static fromCanvas(canvas: HTMLCanvasElement, scaleMode?: number): BaseTexture; - - on(event: "update", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - on(event: "loaded", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - on(event: "error", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - on(event: "dispose", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - once(event: "update", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - once(event: "loaded", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - once(event: "error", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - once(event: "dispose", fn: (baseTexture: BaseTexture) => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class RenderTexture extends Texture { - - constructor(baseRenderTexture: BaseRenderTexture, frame?: Rectangle); - - protected legacyRenderer: any; - valid: boolean; - - resize(width: number, height: number, doNotResizeBaseTexture?: boolean): void; - - static create(width?: number, height?: number, scaleMode?: number, resolution?: number): RenderTexture; - - } - export class Texture extends utils.EventEmitter { - - constructor(baseTexture: BaseTexture, frame?: Rectangle, orig?: Rectangle, trim?: Rectangle, rotate?: number); - - noFrame: boolean; - baseTexture: BaseTexture; - protected _frame: Rectangle; - trim: Rectangle; - valid: boolean; - requiresUpdate: boolean; - protected _uvs: TextureUvs; - orig: Rectangle; - protected _updateID: number; - transform: any; - - update(): void; - protected onBaseTextureLoaded(baseTexture: BaseTexture): void; - protected onBaseTextureUpdated(baseTexture: BaseTexture): void; - destroy(destroyBase?: boolean): void; - clone(): Texture; - protected _updateUvs(): void; - - static fromImage(imageUrl: string, crossOrigin?: boolean, scaleMode?: number, sourceScale?: number): Texture; - static fromFrame(frameId: string): Texture; - static fromCanvas(canvas: HTMLCanvasElement, scaleMode?: number): Texture; - static fromVideo(video: HTMLVideoElement | string, scaleMode?: number): Texture; - static fromVideoUrl(videoUrl: string, scaleMode?: number): Texture; - static from(source: number | string | BaseTexture | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement): Texture; - static addTextureToCache(texture: Texture, id: string): void; - static removeTextureFromCache(id: string): Texture; - - frame: Rectangle; - protected _rotate: boolean; - rotate: number; - width: number; - height: number; - - static EMPTY: Texture; - - on(event: "update", fn: (texture: Texture) => void, context?: any): utils.EventEmitter; - on(event: string, fn: Function, context?: any): utils.EventEmitter; - once(event: "update", fn: (texture: Texture) => void, context?: any): utils.EventEmitter; - once(event: string, fn: Function, context?: any): utils.EventEmitter; - off(event: string, fn: Function, context?: any): utils.EventEmitter; - - } - export class TextureUvs { - - x0: number; - y0: number; - x1: number; - y1: number; - x2: number; - y2: number; - x3: number; - y3: number; - - uvsUint32: Uint32Array; - - protected set(frame: Rectangle, baseFrame: Rectangle, rotate: number): void; - - } - export class VideoBaseTexture extends BaseTexture { - - constructor(source: HTMLVideoElement, scaleMode?: number); - - autoUpdate: boolean; - autoPlay: boolean; - protected _isAutoUpdating: boolean; - - update(): void; - protected _onCanPlay(): void; - protected _onPlayStart(): void; - protected _onPlayStop(): void; - destroy(): void; - protected _isSourcePlaying(): boolean; - protected _isSourceReady(): boolean; - - static fromVideo(video: HTMLVideoElement, scaleMode?: number): VideoBaseTexture; - static fromUrl(videoSrc: string | any | string[] | any[]): VideoBaseTexture; - static fromUrls(videoSrc: string | any | string[] | any[]): VideoBaseTexture; - - source: HTMLVideoElement; - protected loadSource(source: HTMLVideoElement): void; - } - - // ticker - - module ticker { - - export var shared: Ticker; - - export class Ticker { - - protected _tick(time: number): void; - protected _emitter: utils.EventEmitter; - protected _requestId: number; - protected _maxElapsedMS: number; - - protected _requestIfNeeded(): void; - protected _cancelIfNeeded(): void; - protected _startIfPossible(): void; - - autoStart: boolean; - deltaTime: number; - elapsedMS: number; - lastTime: number; - speed: number; - started: boolean; - - FPS: number; - minFPS: number; - - add(fn: (deltaTime: number) => void, context?: any): Ticker; - addOnce(fn: (deltaTime: number) => void, context?: any): Ticker; - remove(fn: (deltaTime: number) => void, context?: any): Ticker; - start(): void; - stop(): void; - update(): void; - - } - - } - - // shader - - export class Shader extends glCore.GLShader { } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////EXTRACT/////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module extract { - - export class CanvasExtract { - - protected renderer: CanvasRenderer; - - constructor(renderer: CanvasRenderer); - - image(target?: DisplayObject | RenderTexture): HTMLImageElement; - base64(target?: DisplayObject | RenderTexture): string; - canvas(target?: DisplayObject | RenderTexture): HTMLCanvasElement; - pixels(renderTexture?: DisplayObject | RenderTexture): number[]; - - destroy(): void; - - } - export class WebGLExtract { - protected renderer: WebGLRenderer; - - constructor(renderer: WebGLRenderer); - - image(target?: DisplayObject | RenderTexture): HTMLImageElement; - base64(target?: DisplayObject | RenderTexture): string; - canvas(target?: DisplayObject | RenderTexture): HTMLCanvasElement; - pixels(renderTexture?: DisplayObject | RenderTexture): number[]; - - destroy(): void; - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////EXTRAS//////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module extras { - - export interface IBitmapTextStyle { - - font?: string | { - - name?: string; - size?: number; - - }; - align?: string; - tint?: number; - - } - export class BitmapText extends Container { - - constructor(text: string, style?: IBitmapTextStyle); - - protected _textWidth: number; - protected _textHeight: number; - textWidth: number; - textHeight: number; - protected _glyphs: Sprite[]; - protected _font: string | { - name?: string; - size?: number; - }; - font: string | { - name?: string; - size?: number; - }; - protected _text: string; - maxWidth: number; - maxLineHeight: number; - dirty: boolean; - tint: number; - align: string; - text: string; - anchor: PIXI.Point | number; - - protected updateText(): void; - updateTransform(): void; - getLocalBounds(): Rectangle; - validate(): void; - - static fonts: any; - - } - export class AnimatedSprite extends Sprite { - - constructor(textures: Texture[] | { texture: Texture, time?: number }[]); - - protected _textures: Texture[]; - protected _durations: number[]; - textures: Texture[] | { texture: Texture, time?: number }[]; - animationSpeed: number; - loop: boolean; - onComplete: () => void; - onFrameChange: (currentFrame: number) => void; - protected _currentTime: number; - playing: boolean; - totalFrames: number; - currentFrame: number; - stop(): void; - play(): void; - gotoAndStop(frameNumber: number): void; - gotoAndPlay(frameNumber: number): void; - protected update(deltaTime: number): void; - destroy(): void; - - static fromFrames(frame: string[]): AnimatedSprite; - static fromImages(images: string[]): AnimatedSprite; - - } - export class TextureTransform { - - constructor(texture: Texture, clampMargin?: number); - - protected _texture: Texture; - protected mapCoord: Matrix; - protected uClampFrame: Float32Array; - protected uClampOffset: Float32Array; - protected _lastTextureID: number; - - clampOffset: number; - clampMargin: number; - - texture: Texture; - - update(forceUpdate?: boolean): void; - - } - export class TilingSprite extends Sprite { - - constructor(texture: Texture, width?: number, height?: number); - - tileTransform: TransformStatic; - protected _width: number; - protected _height: number; - protected _canvasPattern: CanvasPattern; - uvTransform: TextureTransform; - uvRespectAnchor: boolean; - - clampMargin: number; - tileScale: Point | ObservablePoint; - tilePosition: Point | ObservablePoint; - - protected _onTextureUpdate(): void; - protected _renderWebGL(renderer: WebGLRenderer): void; - protected _renderCanvas(renderer: CanvasRenderer): void; - protected _calculateBounds(): void; - getLocalBounds(rect?: Rectangle): Rectangle; - containsPoint(point: Point): boolean; - destroy(): void; - - static from(source: number | string | BaseTexture | HTMLCanvasElement | HTMLVideoElement, width?: number, height?: number): TilingSprite; - static fromFrame(frameId: string, width?: number, height?: number): TilingSprite; - // if you remove the next line, the class will break. https://github.com/pixijs/pixi-typescript/issues/96 - static fromImage(imageId: string, crossorigin?: boolean, scaleMode?: number): Sprite; - static fromImage(imageId: string, width?: number, height?: number, crossorigin?: boolean, scaleMode?: number): TilingSprite; - - width: number; - height: number; - - } - export class TilingSpriteRenderer extends ObjectRenderer { - - constructor(renderer: WebGLRenderer); - - render(ts: TilingSprite): void; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////FILTERS/////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module filters { - - export class FXAAFilter extends Filter { } - export class BlurFilter extends Filter { - - constructor(strength?: number, quality?: number, resolution?: number, kernelSize?: number); - - blurXFilter: BlurXFilter; - blurYFilter: BlurYFilter; - resolution: number; - padding: number; - passes: number; - blur: number; - blurX: number; - blurY: number; - quality: number; - - } - export class BlurXFilter extends Filter { - - constructor(strength?: number, quality?: number, resolution?: number, kernelSize?: number); - - protected _quality: number; - - quality: number; - passes: number; - resolution: number; - strength: number; - firstRun: boolean; - blur: number; - - } - export class BlurYFilter extends Filter { - - constructor(strength?: number, quality?: number, resolution?: number, kernelSize?: number); - - protected _quality: number; - - quality: number; - passes: number; - resolution: number; - strength: number; - firstRun: boolean; - blur: number; - - } - export class ColorMatrixFilter extends Filter { - - constructor(); - - protected _loadMatrix(matrix: number[], multiply?: boolean): void; - protected _multiply(out: number[], a: number[], b: number[]): void; - protected _colorMatrix(matrix: number[]): void; - - matrix: number[]; - - brightness(b: number, multiply?: boolean): void; - greyscale(scale: number, multiply?: boolean): void; - blackAndWhite(multiply?: boolean): void; - hue(rotation: number, multiply?: boolean): void; - contrast(amount: number, multiply?: boolean): void; - saturate(amount: number, multiply?: boolean): void; - desaturate(multiply?: boolean): void; - negative(multiply?: boolean): void; - sepia(multiply?: boolean): void; - technicolor(multiply?: boolean): void; - polaroid(multiply?: boolean): void; - toBGR(multiply?: boolean): void; - kodachrome(multiply?: boolean): void; - browni(multiply?: boolean): void; - vintage(multiply?: boolean): void; - colorTone(desaturation: number, toned: number, lightColor: string, darkColor: string, multiply?: boolean): void; - night(intensity: number, multiply?: boolean): void; - predator(amount: number, multiply?: boolean): void; - lsd(multiply?: boolean): void; - reset(): void; - - } - export class DisplacementFilter extends Filter { - - constructor(sprite: Sprite, scale?: number); - - scale: Point; - map: Texture; - - } - export class VoidFilter extends Filter { - glShaderKey: string; - } - - // pixi-filters.d.ts todo - // https://github.com/pixijs/pixi-filters/ - export class NoiseFilter extends Filter { - - noise: number; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////INTERACTION/////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module interaction { - - export interface InteractionEvent { - - stopped: boolean; - target: DisplayObject; - currentTarget: DisplayObject; - type: string; - data: InteractionData; - stopPropagation(): void; - - } - export class InteractionData { - - global: Point; - - protected _target: DisplayObject; - target: DisplayObject; - targetProxy: DisplayObject; - originalEvent: Event; - - getLocalPosition(displayObject: DisplayObject, point?: Point, globalPos?: Point): Point; - - } - export class InteractionManager extends utils.EventEmitter { - - constructor(renderer: SystemRenderer, options?: { autoPreventDefault?: boolean; interactionFrequency?: number; }); - - renderer: SystemRenderer; - autoPreventDefault: boolean; - interactionFrequency: number; - mouse: InteractionData; - pointer: InteractionData; - eventData: { - stopped: boolean; - target: any; - type: any; - data: InteractionData; - stopPropagination(): void; - }; - interactiveDataPool: InteractionData[]; - protected interactionDOMElement: HTMLElement; - protected moveWhenInside: boolean; - protected eventsAdded: boolean; - mouseOverRenderer: boolean; - supportsTouchEvents: boolean; - supportsPointerEvents: boolean; - normalizeTouchEvents: boolean; - normalizeMouseEvents: boolean; - - protected onMouseUp: (event: MouseEvent) => void; - protected processMouseUp: (displayObject: DisplayObject, hit: boolean) => void; - protected onMouseDown: (event: MouseEvent) => void; - protected processMouseDown: (displayObject: DisplayObject, hit: boolean) => void; - protected onMouseMove: (event: MouseEvent) => void; - protected processMouseMove: (displayObject: DisplayObject, hit: boolean) => void; - protected onMouseOut: (event: MouseEvent) => void; - protected processMouseOverOut: (displayObject: DisplayObject, hit: boolean) => void; - protected onMouseOver: (event: MouseEvent) => void; - - protected onPointerUp: (event: PointerEvent) => void; - protected processPointerUp: (displayObject: DisplayObject, hit: boolean) => void; - protected onPointerDown: (event: PointerEvent) => void; - protected processPointerDown: (displayObject: DisplayObject, hit: boolean) => void; - protected onPointerMove: (event: PointerEvent) => void; - protected processPointerMove: (displayObject: DisplayObject, hit: boolean) => void; - protected onPointerOut: (event: PointerEvent) => void; - protected processPointerOut: (displayObject: DisplayObject, hit: boolean) => void; - protected onPointerOver: (event: PointerEvent) => void; - - protected onTouchStart: (event: TouchEvent) => void; - protected processTouchStart: (DisplayObject: DisplayObject, hit: boolean) => void; - protected onTouchEnd: (event: TouchEvent) => void; - protected processTouchEnd: (displayObject: DisplayObject, hit: boolean) => void; - protected onTouchMove: (event: TouchEvent) => void; - protected processTouchMove: (displayObject: DisplayObject, hit: boolean) => void; - defaultCursorStyle: string; - currentCursorStyle: string; - protected _tempPoint: Point; - resolution: number; - protected setTargetElement(element: HTMLElement, resolution: number): void; - protected addEvents(): void; - protected removeEvents(): void; - update(deltaTime: number): void; - protected dispatchEvent(displayObject: DisplayObject, eventString: string, eventData: any): void; - mapPositionToPoint(point: Point, x: number, y: number): void; - protected processInteractive(point: Point, displayObject: DisplayObject, func: (displayObject: DisplayObject, hit: boolean) => void, hitTest: boolean, interactive: boolean): boolean; - protected _startInteractionProcess(): void; - protected _queueAdd(displayObject: DisplayObject, order: number): void; - protected _finishInteractionProcess(func: Function): void; - protected getTouchData(touchEvent: InteractionData): InteractionData; - protected returnTouchData(touchData: InteractionData): void; - protected normalizeToPointerData(Event: Event): void; - - destroy(): void; - - } - export interface InteractiveTarget { - - interactive: boolean; - interactiveChildren: boolean; - hitArea: IHitArea; - buttonMode: boolean; - defaultCursor: string; - - } - export interface InteractiveTargetProxy extends InteractiveTarget { - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////LOADER///////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - // pixi loader extends - // https://github.com/englercj/resource-loader/ - // 2.0.3 - - class MiniSignalBinding { - - constructor(fn: Function, once?: boolean, thisArg?: any); - - protected _fn: Function; - protected _once: boolean; - protected _thisArg: any; - protected _next: MiniSignalBinding; - protected _prev: MiniSignalBinding; - protected _owner: MiniSignal; - - detach(): boolean; - - } - class MiniSignal { - - constructor(); - - protected _head: MiniSignalBinding; - protected _tail: MiniSignalBinding; - - handlers(exists?: boolean): MiniSignalBinding[] | boolean; - handlers(exists?: true): boolean; - handlers(exists?: false): MiniSignalBinding[]; - - has(node: MiniSignalBinding): boolean; - dispatch(): boolean; - add(fn: Function, thisArg?: any): void; - once(fn: Function, thisArg?: any): void; - detach(node: MiniSignalBinding): MiniSignal; - detachAll(): MiniSignal; - - } - - export module loaders { - - export interface ILoaderOptions { - - crossOrigin?: boolean | string; - loadType?: number; - xhrType?: string; - metaData?: any; - loadElement?: HTMLImageElement | HTMLAudioElement | HTMLVideoElement; - skipSource?: boolean; - - } - export interface IResourceDictionary { - - [index: string]: PIXI.loaders.Resource; - - } - export class Loader { - - // pixi overrides here - static addPixiMiddleware(fn: Function): void; - - // below this line is the original non-pixi loader - - static Resource: any; - static async: any; - static base64: any; - - constructor(baseUrl?: string, concurrency?: number); - - baseUrl: string; - progress: number; - loading: boolean; - defaultQueryString: string; - - protected _beforeMiddleware: Function[]; - protected _afterMiddleware: Function[]; - protected _boundLoadResource: (r: Resource, d: Function) => void; - protected _queue: any; - - resources: IResourceDictionary; - - onProgress: MiniSignal; - onError: MiniSignal; - onLoad: MiniSignal; - onStart: MiniSignal; - onComplete: MiniSignal; - - add(...params: any[]): this; - add(name: string, url: string, options?: ILoaderOptions, cb?: Function): this; - add(url: string, options?: ILoaderOptions, cb?: Function): this; - add(obj: any | any[], options?: ILoaderOptions, cb?: Function): this; - - pre(fn: Function): this; - use(fn: Function): this; - reset(): this; - load(cb?: Function): this; - - protected _prepareUrl(url: string): string; - protected _loadResource(resource: Resource, dequeue: Function): void; - protected _onComplete(): void; - protected _onLoad(resource: Resource): void; - - // these are added for spine support - spineAtlas: any; - spineData: any; - textures: ITextureDictionary; - - } - export interface ITextureDictionary { - [index: string]: PIXI.Texture; - } - export class Resource { - - static setExtensionLoadType(extname: string, loadType: number): void; - static setExtensionXhrType(extname: string, xhrType: number): void; - - constructor(name: string, url: string | string[], options?: ILoaderOptions); - - protected _flags: number; - - name: string; - url: string; - data: any; - crossOrigin: boolean | string; - loadType: number; - xhrType: string; - metadata: any; - error: Error; - xhr: XMLHttpRequest; - children: Resource[]; - type: number; - progressChunk: number; - - protected _dequeue: Function; - protected _onLoadBinding: Function; - protected _boundComplete: Function; - protected _boundOnError: Function; - protected _boundOnProgress: Function; - protected _boundXhrOnError: Function; - protected _boundXhrOnAbort: Function; - protected _boundXhrOnLoad: Function; - protected _boundXdrOnTimeout: Function; - - onStart: MiniSignal; - onProgress: MiniSignal; - onComplete: MiniSignal; - onAfterMiddleware: MiniSignal; - - isDataUrl: boolean; - isComplete: boolean; - isLoading: boolean; - complete(): void; - abort(message?: string): void; - load(cb?: Function): void; - - protected _hasFlag(flag: number): boolean; - protected _setFlag(flag: number, value: boolean): void; - protected _loadElement(type: string): void; - protected _loadSourceElement(type: string): void; - protected _loadXhr(): void; - protected _loadXdr(): void; - protected _createSource(type: string, url: string, mime?: string): HTMLSourceElement; - protected _onError(event?: any): void; - protected _onProgress(event?: any): void; - protected _xhrOnError(): void; - protected _xhrOnAbort(): void; - protected _xdrOnTimeout(): void; - protected _xhrOnLoad(): void; - protected _determineCrossOrigin(url: string, loc: any): string; - protected _determineXhrType(): number; - protected _determineLoadType(): number; - protected _getExtension(): string; - protected _getMimeXhrType(type: number): string; - - static STATUS_FLAGS: { - NONE: number; - DATA_URL: number; - COMPLETE: number; - LOADING: number; - }; - - static TYPE: { - UNKNOWN: number; - JSON: number; - XML: number; - IMAGE: number; - AUDIO: number; - VIDEO: number; - TEXT: number; - }; - - static LOAD_TYPE: { - XHR: number; - IMAGE: number; - AUDIO: number; - VIDEO: number; - }; - - static XHR_RESPONSE_TYPE: { - DEFAULT: number; - BUFFER: number; - BLOB: number; - DOCUMENT: number; - JSON: number; - TEXT: number; - }; - - static EMPTY_GIF: string; - - } - } - - ////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////MESH/////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module mesh { - - export class Mesh extends Container { - - constructor(texture: Texture, vertices?: Float32Array, uvs?: Float32Array, indices?: Uint16Array, drawMode?: number); - - protected _texture: Texture; - uvs: Float32Array; - vertices: Float32Array; - indices: Uint16Array; - dirty: number; - indexDirty: number; - dirtyVertex: boolean; - protected _geometryVersion: number; - blendMode: number; - pluginName: string; - canvasPadding: number; - drawMode: number; - texture: Texture; - tintRgb: Float32Array; - protected _glDatas: { [n: number]: any; }; - protected _renderWebGL(renderer: WebGLRenderer): void; - protected _renderCanvas(renderer: CanvasRenderer): void; - protected _onTextureUpdate(): void; - protected _calculateBounds(): void; - containsPoint(point: Point): boolean; - tint: number; - - static DRAW_MODES: { - TRIANGLE_MESH: number; - TRIANGLES: number; - }; - - } - - export class CanvasMeshRenderer { - - constructor(renderer: CanvasRenderer); - - renderer: CanvasRenderer; - - render(mesh: Mesh): void; - protected _renderTriangleMesh(mesh: Mesh): void; - protected _renderTriangles(mesh: Mesh): void; - protected _renderDrawTriangle(mesh: Mesh, index0: number, index1: number, index2: number): void; - protected renderMeshFlat(mesh: Mesh): void; - - destroy(): void; - - } - - export class MeshRenderer extends ObjectRenderer { - - constructor(renderer: WebGLRenderer); - - shader: Shader; - render(mesh: Mesh): void; - - } - - export class Plane extends Mesh { - - constructor(texture: Texture, verticesX?: number, verticesY?: number); - protected _ready: boolean; - verticesX: number; - verticesY: number; - drawMode: number; - - refresh(): void; - - protected _onTexureUpdate(): void; - - } - - export class NineSlicePlane extends Plane { - - constructor(texture: Texture, leftWidth?: number, topHeight?: number, rightWidth?: number, bottomHeight?: number); - - width: number; - height: number; - leftWidth: number; - rightWidth: number; - topHeight: number; - bottomHeight: number; - - protected _leftWidth: number; - protected _rightWidth: number; - protected _topHeight: number; - protected _bottomHeight: number; - protected _height: number; - protected _width: number; - protected _origHeight: number; - protected _origWidth: number; - protected _uvh: number; - protected _uvw: number; - - updateHorizontalVertices(): void; - updateVerticalVertices(): void; - protected drawSegment(context: CanvasRenderingContext2D | WebGLRenderingContext, textureSource: any, w: number, h: number, x1: number, y1: number, x2: number, y2: number): void; - - } - - export class Rope extends Mesh { - - constructor(texture: Texture, points: Point[]); - - points: Point[]; - colors: number[]; - protected _ready: boolean; - refresh(): void; - - protected _onTextureUpdate(): void; - updateTransform(): void; - - } - } - - ////////////////////////////////////////////////////////////////////////////// - /////////////////////////////PARTICLES//////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module particles { - - export interface IParticleContainerProperties { - - scale?: boolean; - position?: boolean; - rotation?: boolean; - uvs?: boolean; - alpha?: boolean; - - } - export class ParticleContainer extends Container { - - constructor(size?: number, properties?: IParticleContainerProperties, batchSize?: number); - - protected _properties: boolean[]; - protected _maxSize: number; - protected _batchSize: number; - protected _glBuffers: { [n: number]: WebGLBuffer; }; - protected _bufferToUpdate: number; - interactiveChildren: boolean; - blendMode: number; - roundPixels: boolean; - baseTexture: BaseTexture; - - setProperties(properties: IParticleContainerProperties): void; - protected onChildrenChange: (smallestChildIndex?: number) => void; - - destroy(options?: IDestroyOptions | boolean): void; - - } - export class ParticleBuffer { - - constructor(gl: WebGLRenderingContext, properties: any, dynamicPropertyFlags: any[], size: number); - - gl: WebGLRenderingContext; - vertSize: number; - vertByteSize: number; - size: number; - dynamicProperties: any[]; - staticProperties: any[]; - staticStride: number; - staticBuffer: any; - staticData: any; - dynamicStride: number; - dynamicBuffer: any; - dynamicData: any; - - destroy(): void; - - } - export interface IParticleRendererProperty { - attribute: number; - size: number; - uploadFunction: (children: PIXI.DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number) => void; - offset: number; - } - export class ParticleRenderer extends ObjectRenderer { - - constructor(renderer: WebGLRenderer); - - shader: glCore.GLShader; - indexBuffer: WebGLBuffer; - properties: IParticleRendererProperty[]; - protected tempMatrix: Matrix; - - start(): void; - generateBuffers(container: ParticleContainer): ParticleBuffer[]; - uploadVertices(children: DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number): void; - uploadPosition(children: DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number): void; - uploadRotation(children: DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number): void; - uploadUvs(children: DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number): void; - uploadAlpha(children: DisplayObject[], startIndex: number, amount: number, array: number[], stride: number, offset: number): void; - destroy(): void; - - indices: Uint16Array; - - } - export interface IParticleShader extends glCore.GLShader { } - - } - - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////PREPARE/////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export module prepare { - - interface addHook { - (item: any, queue: any[]): boolean; - } - interface uploadHook { - (prepare: UploadHookSource, item: any): boolean - } - export abstract class BasePrepare{ - - constructor(renderer: SystemRenderer); - - limiter: CountLimiter | TimeLimiter; - protected renderer: SystemRenderer; - protected uploadHookHelper: UploadHookSource; - protected queue: any[]; - protected addHooks: addHook[]; - protected uploadHooks: uploadHook[]; - protected completes: Function[]; - protected ticking: boolean; - protected delayedTick: () => void; - - upload(item: Function | DisplayObject | BaseTexture | TextStyle | any, done?: () => void): void; - protected tick(): void; - protected prepareItems(): void; - register(addHook?: addHook, uploadHook?: uploadHook): this; - add(item: DisplayObject | any): this; - destroy(): void; - - } - export class CanvasPrepare extends BasePrepare { - - constructor(renderer: CanvasRenderer); - - protected canvas: HTMLCanvasElement; - protected ctx: CanvasRenderingContext2D; - - } - export class WebGLPrepare extends BasePrepare { - - constructor(renderer: WebGLRenderer); - - } - export class CountLimiter { - - constructor(maxItemsPerFrame: number); - - protected maxItemsPerFrame: number; - protected itemsLeft: number; - - } - export class TimeLimiter { - - constructor(maxMilliseconds: number); - - protected maxMilliseconds: number; - protected frameStart: number; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - /////////////////////////////pixi-gl-core///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - // pixi-gl-core https://github.com/pixijs/pixi-gl-core - // sharedArrayBuffer as a type is not available yet. - // need to fully define what an `Attrib` is. - export module glCore { - - export interface IContextOptions { - /** - * Boolean that indicates if the canvas contains an alpha buffer. - */ - alpha?: boolean; - /** - * Boolean that indicates that the drawing buffer has a depth buffer of at least 16 bits. - */ - depth?: boolean; - /** - * Boolean that indicates that the drawing buffer has a stencil buffer of at least 8 bits. - */ - stencil?: boolean; - /** - * Boolean that indicates whether or not to perform anti-aliasing. - */ - antialias?: boolean; - /** - * Boolean that indicates that the page compositor will assume the drawing buffer contains colors with pre-multiplied alpha. - */ - premultipliedAlpha?: boolean; - /** - * If the value is true the buffers will not be cleared and will preserve their values until cleared or overwritten by the author. - */ - preserveDrawingBuffer?: boolean; - /** - * Boolean that indicates if a context will be created if the system performance is low. - */ - failIfMajorPerformanceCaveat?: boolean; - } - export function createContext(view: HTMLCanvasElement, options?: IContextOptions): WebGLRenderingContext; - export function setVertexAttribArrays(gl: WebGLRenderingContext, attribs: IAttrib[], state?: WebGLState): WebGLRenderingContext; - export class GLBuffer { - - static EMPTY_ARRAY_BUFFER: ArrayBuffer; - - constructor(gl: WebGLRenderingContext, type: number, data: ArrayBuffer | ArrayBufferView | any, drawType: number); - - protected _updateID: number; - gl: WebGLRenderingContext; - buffer: WebGLBuffer; - type: number; - drawType: number; - data: ArrayBuffer | ArrayBufferView | any; - - upload(data: ArrayBuffer | ArrayBufferView | any, offset?: number, dontBind?: boolean): void; - bind(): void; - - static createVertexBuffer(gl: WebGLRenderingContext, data: ArrayBuffer | ArrayBufferView | any, drawType: number): GLBuffer; - static createIndexBuffer(gl: WebGLRenderingContext, data: ArrayBuffer | ArrayBufferView | any, drawType: number): GLBuffer; - static create(gl: WebGLRenderingContext, type: number, data: ArrayBuffer | ArrayBufferView | any, drawType: number): GLBuffer; - - destroy(): void; - - } - export class GLFramebuffer { - - constructor(gl: WebGLRenderingContext, width: number, height: number); - - gl: WebGLRenderingContext; - frameBuffer: WebGLFramebuffer; - stencil: WebGLRenderbuffer; - texture: GLTexture; - width: number; - height: number; - - enableTexture(texture: GLTexture): void; - enableStencil(): void; - clear(r: number, g: number, b: number, a: number): void; - bind(): void; - unbind(): void; - resize(width: number, height: number): void; - destroy(): void; - - static createRGBA(gl: WebGLRenderingContext, width: number, height: number, data: ArrayBuffer | ArrayBufferView | any): GLFramebuffer; - static createFloat32(gl: WebGLRenderingContext, width: number, height: number, data: ArrayBuffer | ArrayBufferView | any): GLFramebuffer; - - } - export class GLShader { - - constructor(gl: WebGLRenderingContext, vertexSrc: string | string[], fragmentSrc: string | string[]); - - gl: WebGLRenderingContext; - program: WebGLProgram; - uniforms: any; - attributes: any; - - bind(): void; - destroy(): void; - - } - export class GLTexture { - - constructor(gl: WebGLRenderingContext, width?: number, height?: number, format?: number, type?: number); - - gl: WebGLRenderingContext; - texture: WebGLTexture; - mipmap: boolean; - premultiplyAlpha: boolean; - width: number; - height: number; - format: number; - type: number; - - upload(source: HTMLImageElement | ImageData | HTMLVideoElement | HTMLCanvasElement): void; - uploadData(data: number, width: number, height: number): void; - bind(location?: number): void; - unbind(): void; - minFilter(linear: boolean): void; - magFilter(linear: boolean): void; - enableMipmap(): void; - enableLinearScaling(): void; - enableNearestScaling(): void; - enableWrapClamp(): void; - enableWrapRepeat(): void; - enableWrapMirrorRepeat(): void; - destroy(): void; - - static fromSource(gl: WebGLRenderingContext, source: HTMLImageElement | ImageData | HTMLVideoElement | HTMLCanvasElement, premultipleAlpha?: boolean): GLTexture; - static fromData(gl: WebGLRenderingContext, data: number[], width: number, height: number): GLTexture; - - } - export interface IAttrib { - - attribute: { - location: boolean; - size: number; - }; - normalized: boolean; - stride: number; - start: number; - buffer: ArrayBuffer; - - } - export interface IWebGLRenderingContextAttribute { - - buffer: WebGLBuffer; - attribute: any; - type: number; - normalized: boolean; - stride: number; - start: number; - - } - export interface IAttribState { - tempAttribState: IAttrib[]; - attribState: IAttrib[]; - } - - export class VertexArrayObject { - - static FORCE_NATIVE: boolean; - - constructor(gl: WebGLRenderingContext, state: WebGLState); - - protected nativeVaoExtension: any; - protected nativeState: IAttribState; - protected nativeVao: VertexArrayObject; - gl: WebGLRenderingContext; - attributes: IAttrib[]; - indexBuffer: GLBuffer; - dirty: boolean; - - bind(): VertexArrayObject; - unbind(): VertexArrayObject; - activate(): VertexArrayObject; - addAttribute(buffer: GLBuffer, attribute: IAttrib, type: number, normalized: boolean, stride: number, start: number): VertexArrayObject; - addIndex(buffer: GLBuffer, options?: any): VertexArrayObject; - clear(): VertexArrayObject; - draw(type: number, size: number, start: number): VertexArrayObject; - destroy(): void; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////UTILS////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - - export interface IDecomposedDataUri { - mediaType: string; - subType: string; - encoding: string; - data: any; - } - - export module utils { - - export function uid(): number; - export function hex2rgb(hex: number, out?: number[]): number[]; - export function hex2string(hex: number): string; - export function rgb2hex(rgb: Number[]): number; - export function canUseNewCanvasBlendModes(): boolean; - export function getResolutionOfUrl(url: string, defaultValue?: number): number; - export function getSvgSize(svgString: string): any; - export function decomposeDataUri(dataUri: string): IDecomposedDataUri; - export function getUrlFileExtension(url: string): string; - export function sayHello(type: string): void; - export function skipHello(): void; - export function isWebGLSupported(): boolean; - export function sign(n: number): number; - export function removeItems(arr: T[], startIdx: number, removeCount: number): void; - export var TextureCache: any; - export var BaseTextureCache: any; - - //https://github.com/kaimallea/isMobile - export module isMobile { - export var apple: { - phone: boolean; - ipod: boolean; - tablet: boolean; - device: boolean; - }; - export var android: { - phone: boolean; - tablet: boolean; - device: boolean; - } - export var amazon: { - phone: boolean; - table: boolean; - device: boolean; - } - export var windows: { - phone: boolean; - tablet: boolean; - device: boolean; - } - export var seven_inch: boolean; - export var other: { - blackberry_10: boolean; - blackberry: boolean; - opera: boolean; - firefox: boolean; - chrome: boolean; - device: boolean; - } - export var any: boolean; - export var phone: boolean; - export var tablet: boolean; - } - - // https://github.com/primus/eventemitter3 - export class EventEmitter { - - listeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - on(event: string, fn: Function, context?: any): EventEmitter; - once(event: string, fn: Function, context?: any): EventEmitter; - removeListener(event: string, fn: Function, context?: any, once?: boolean): EventEmitter; - removeAllListeners(event: string): EventEmitter; - eventNames(): string[]; - - off(event: string, fn: Function, context?: any, once?: boolean): EventEmitter; - addListener(event: string, fn: Function, context?: any): EventEmitter; - - } - - } - - ////////////////////////////////////////////////////////////////////////////// - /////////////////////////////depreciation///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - // not sure how to handle blendmodes scalemodes basetexturecache - module core { - - /** - * @class - * @private - * @name SpriteBatch - * @memberof PIXI - * @see PIXI.ParticleContainer - * @throws {ReferenceError} SpriteBatch does not exist any more, please use the new ParticleContainer instead. - * @deprecated since version 3.0.0 - */ - type SpriteBatch = ParticleContainer; - - /** - * @class - * @private - * @name AssetLoader - * @memberof PIXI - * @see PIXI.loaders.Loader - * @throws {ReferenceError} The loader system was overhauled in pixi v3, please see the new PIXI.loaders.Loader class. - * @deprecated since version 3.0.0 - */ - type AssetLoader = loaders.Loader; - - /** - * @class - * @private - * @name Stage - * @memberof PIXI - * @see PIXI.Container - * @deprecated since version 3.0.0 - */ - type Stage = Container; - - /** - * @class - * @private - * @name DisplayObjectContainer - * @memberof PIXI - * @see PIXI.Container - * @deprecated since version 3.0.0 - */ - type DisplayObjectContainer = Container; - - /** - * @class - * @private - * @name Strip - * @memberof PIXI - * @see PIXI.mesh.Mesh - * @deprecated since version 3.0.0 - */ - type Strip = mesh.Mesh; - - /** - * @class - * @private - * @name Rope - * @memberof PIXI - * @see PIXI.mesh.Rope - * @deprecated since version 3.0.0 - */ - type Rope = mesh.Rope; - - /** - * @class - * @private - * @name ParticleContainer - * @memberof PIXI - * @see PIXI.particles.ParticleContainer - * @deprecated since version 4.0.0 - */ - type ParticleContainer = particles.ParticleContainer; - - /** - * @class - * @private - * @name MovieClip - * @memberof PIXI - * @see PIXI.extras.MovieClip - * @deprecated since version 3.0.0 - */ - type MovieClip = extras.AnimatedSprite - - /** - * @class - * @private - * @name TilingSprite - * @memberof PIXI - * @see PIXI.extras.TilingSprite - * @deprecated since version 3.0.0 - */ - type TilingSprite = extras.TilingSprite; - - /** - * @class - * @private - * @name BitmapText - * @memberof PIXI - * @see PIXI.extras.BitmapText - * @deprecated since version 3.0.0 - */ - type BitmapText = extras.BitmapText; - - /** - * @namespace - * @private - * @name math - * @memberof PIXI - * @see PIXI - * @deprecated since version 3.0.6 - */ - type math = any; - - /** - * @class - * @private - * @name PIXI.AbstractFilter - * @see PIXI.Filter - * @deprecated since version 3.0.6 - */ - type AbstractFilter = Filter; - - /** - * @class - * @private - * @name PIXI.TransformManual - * @see PIXI.TransformBase - * @deprecated since version 4.0.0 - */ - type TransformManual = TransformBase; - - /** - * @static - * @constant - * @name PIXI.TARGET_FPMS - * @see PIXI.settings.TARGET_FPMS - * @deprecated since version 4.2.0 - */ - type TARGET_FPMS = number; - - /** - * @static - * @constant - * @name PIXI.FILTER_RESOLUTION - * @see PIXI.settings.FILTER_RESOLUTION - * @deprecated since version 4.2.0 - */ - type FILTER_RESOLUTION = number; - - /** - * @static - * @constant - * @name PIXI.RESOLUTION - * @see PIXI.settings.RESOLUTION - * @deprecated since version 4.2.0 - */ - type RESOLUTION = number; - - /** - * @static - * @constant - * @name PIXI.MIPMAP_TEXTURES - * @see PIXI.settings.MIPMAP_TEXTURES - * @deprecated since version 4.2.0 - */ - type MIPMAP_TEXTURES = any; - - /** - * @static - * @constant - * @name PIXI.SPRITE_BATCH_SIZE - * @see PIXI.settings.SPRITE_BATCH_SIZE - * @deprecated since version 4.2.0 - */ - type SPRITE_BATCH_SIZE = number; - - /** - * @static - * @constant - * @name PIXI.SPRITE_MAX_TEXTURES - * @see PIXI.settings.SPRITE_MAX_TEXTURES - * @deprecated since version 4.2.0 - */ - type SPRITE_MAX_TEXTURES = number; - - /** - * @static - * @constant - * @name PIXI.RETINA_PREFIX - * @see PIXI.settings.RETINA_PREFIX - * @deprecated since version 4.2.0 - */ - type RETINA_PREFIX = RegExp | string; - - /** - * @static - * @constant - * @name PIXI.DEFAULT_RENDER_OPTIONS - * @see PIXI.settings.RENDER_OPTIONS - * @deprecated since version 4.2.0 - */ - type DEFAULT_RENDER_OPTIONS = number; - - } - - export module extras { - - /** - * @class - * @name MovieClip - * @memberof PIXI.extras - * @see PIXI.extras.AnimatedSprite - * @deprecated since version 4.2.0 - */ - type MovieClip = extras.AnimatedSprite; - - } - -} - -declare module pixi { - export var gl: typeof PIXI.glCore; -} - -declare module "pixi.js" { - export = PIXI; -} diff --git a/src/AnimatedParticle.js b/src/AnimatedParticle.js deleted file mode 100644 index 3cccd85f..00000000 --- a/src/AnimatedParticle.js +++ /dev/null @@ -1,216 +0,0 @@ -"use strict"; - -var ParticleUtils = require("./ParticleUtils"), - Particle = require("./Particle"), - Texture = PIXI.Texture; - -/** - * An individual particle image with an animation. Art data passed to the emitter must be - * formatted in a particular way for AnimatedParticle to be able to handle it: - * - * { - * //framerate is required. It is the animation speed of the particle in frames per - * //second. - * //A value of "matchLife" causes the animation to match the lifetime of an individual - * //particle, instead of at a constant framerate. This causes the animation to play - * //through one time, completing when the particle expires. - * framerate: 6, - * //loop is optional, and defaults to false. - * loop: true, - * //textures is required, and can be an array of any (non-zero) length. - * textures: [ - * //each entry represents a single texture that should be used for one or more - * //frames. Any strings will be converted to Textures with Texture.fromImage(). - * //Instances of PIXI.Texture will be used directly. - * "animFrame1.png", - * //entries can be an object with a 'count' property, telling AnimatedParticle to - * //use that texture for 'count' frames sequentially. - * { - * texture: "animFrame2.png", - * count: 3 - * }, - * "animFrame3.png" - * ] - * } - * - * @memberof PIXI.particles - * @class AnimatedParticle - * @extends PIXI.particles.Particle - * @constructor - * @param {PIXI.particles.Emitter} emitter The emitter that controls this AnimatedParticle. - */ -var AnimatedParticle = function(emitter) -{ - Particle.call(this, emitter); - - /** - * Texture array used as each frame of animation, similarly to how MovieClip works. - * @property {Array} textures - * @private - */ - this.textures = null; - - /** - * Duration of the animation, in seconds. - * @property {Number} duration - * @private - */ - this.duration = 0; - - /** - * Animation framerate, in frames per second. - * @property {Number} framerate - * @private - */ - this.framerate = 0; - - /** - * Animation time elapsed, in seconds. - * @property {Number} elapsed - * @private - */ - this.elapsed = 0; - - /** - * If this particle animation should loop. - * @property {Boolean} loop - * @private - */ - this.loop = false; -}; - -// Reference to the super class -var s = Particle.prototype; -// Reference to the prototype -var p = AnimatedParticle.prototype = Object.create(s); - -/** - * Initializes the particle for use, based on the properties that have to - * have been set already on the particle. - * @method PIXI.particles.AnimatedParticle#init - */ -p.init = function() -{ - this.Particle_init(); - - this.elapsed = 0; - - //if the animation needs to match the particle's life, then cacluate variables - if(this.framerate < 0) - { - this.duration = this.maxLife; - this.framerate = this.textures.length / this.duration; - } -}; - -/** - * Sets the textures for the particle. - * @method PIXI.particles.AnimatedParticle#applyArt - * @param {Array} art An array of PIXI.Texture objects for this animated particle. - */ -p.applyArt = function(art) -{ - this.textures = art.textures; - this.framerate = art.framerate; - this.duration = art.duration; - this.loop = art.loop; -}; - -/** - * Updates the particle. - * @method PIXI.particles.AnimatedParticle#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - */ -p.update = function(delta) -{ - //only animate the particle if it is still alive - if(this.Particle_update(delta) >= 0) - { - this.elapsed += delta; - if(this.elapsed > this.duration) - { - //loop elapsed back around - if(this.loop) - this.elapsed = this.elapsed % this.duration; - //subtract a small amount to prevent attempting to go past the end of the animation - else - this.elapsed = this.duration - 0.000001; - } - var frame = (this.elapsed * this.framerate + 0.0000001) | 0; - this.texture = this.textures[frame] || ParticleUtils.EMPTY_TEXTURE; - } -}; - -p.Particle_destroy = Particle.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.AnimatedParticle#destroy - */ -p.destroy = function() -{ - this.Particle_destroy(); - this.textures = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. - * @method PIXI.particles.AnimatedParticle.parseArt - * @static - * @param {Array} art The array of art data, properly formatted for AnimatedParticle. - * @return {Array} The art, after any needed modifications. - */ -AnimatedParticle.parseArt = function(art) -{ - var i, data, output = [], j, textures, tex, outTextures; - for(i = 0; i < art.length; ++i) - { - data = art[i]; - art[i] = output = {}; - output.textures = outTextures = []; - textures = data.textures; - for(j = 0; j < textures.length; ++j) - { - tex = textures[j]; - if(typeof tex == "string") - outTextures.push(Texture.fromImage(tex)); - else if(tex instanceof Texture) - outTextures.push(tex); - //assume an object with extra data determining duplicate frame data - else - { - var dupe = tex.count || 1; - if(typeof tex.texture == "string") - tex = Texture.fromImage(tex.texture); - else// if(tex.texture instanceof Texture) - tex = tex.texture; - for(; dupe > 0; --dupe) - { - outTextures.push(tex); - } - } - } - - //use these values to signify that the animation should match the particle life time. - if(data.framerate == "matchLife") - { - //-1 means that it should be calculated - output.framerate = -1; - output.duration = 0; - output.loop = false; - } - else - { - //determine if the animation should loop - output.loop = !!data.loop; - //get the framerate, default to 60 - output.framerate = data.framerate > 0 ? data.framerate : 60; - //determine the duration - output.duration = outTextures.length / output.framerate; - } - } - - return art; -}; - -module.exports = AnimatedParticle; \ No newline at end of file diff --git a/src/AnimatedParticle.ts b/src/AnimatedParticle.ts new file mode 100644 index 00000000..d524b5df --- /dev/null +++ b/src/AnimatedParticle.ts @@ -0,0 +1,236 @@ +"use strict"; + +import ParticleUtils from "./ParticleUtils"; +import Particle from "./Particle"; +import Emitter from "./Emitter"; +import Texture = PIXI.Texture; + +export interface ParsedAnimatedParticleArt +{ + textures: PIXI.Texture[]; + duration: number; + framerate: number; + loop: boolean; +} + +export interface AnimatedParticleArt +{ + framerate: "matchLife"|number; + loop?: boolean; + textures: (string|PIXI.Texture|{texture:string|PIXI.Texture,count:number})[]; +} + +/** + * An individual particle image with an animation. Art data passed to the emitter must be + * formatted in a particular way for AnimatedParticle to be able to handle it: + * + * { + * //framerate is required. It is the animation speed of the particle in frames per + * //second. + * //A value of "matchLife" causes the animation to match the lifetime of an individual + * //particle, instead of at a constant framerate. This causes the animation to play + * //through one time, completing when the particle expires. + * framerate: 6, + * //loop is optional, and defaults to false. + * loop: true, + * //textures is required, and can be an array of any (non-zero) length. + * textures: [ + * //each entry represents a single texture that should be used for one or more + * //frames. Any strings will be converted to Textures with Texture.fromImage(). + * //Instances of PIXI.Texture will be used directly. + * "animFrame1.png", + * //entries can be an object with a 'count' property, telling AnimatedParticle to + * //use that texture for 'count' frames sequentially. + * { + * texture: "animFrame2.png", + * count: 3 + * }, + * "animFrame3.png" + * ] + * } + * + * @memberof PIXI.particles + * @class AnimatedParticle + * @extends PIXI.particles.Particle + * @constructor + * @param {PIXI.particles.Emitter} emitter The emitter that controls this AnimatedParticle. + */ +export default class AnimatedParticle extends Particle +{ + /** + * Texture array used as each frame of animation, similarly to how MovieClip works. + * @property {Array} textures + * @private + */ + private textures: PIXI.Texture[]; + + /** + * Duration of the animation, in seconds. + * @property {Number} duration + * @private + */ + private duration: number; + + /** + * Animation framerate, in frames per second. + * @property {Number} framerate + * @private + */ + private framerate: number; + + /** + * Animation time elapsed, in seconds. + * @property {Number} elapsed + * @private + */ + private elapsed: number; + + /** + * If this particle animation should loop. + * @property {Boolean} loop + * @private + */ + private loop: boolean; + + constructor(emitter: Emitter) + { + super(emitter); + + this.textures = null; + this.duration = 0; + this.framerate = 0; + this.elapsed = 0; + this.loop = false; + } + + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.AnimatedParticle#init + */ + public init() + { + this.Particle_init(); + + this.elapsed = 0; + + //if the animation needs to match the particle's life, then cacluate variables + if(this.framerate < 0) + { + this.duration = this.maxLife; + this.framerate = this.textures.length / this.duration; + } + } + + /** + * Sets the textures for the particle. + * @method PIXI.particles.AnimatedParticle#applyArt + * @param {Array} art An array of PIXI.Texture objects for this animated particle. + */ + public applyArt(art: ParsedAnimatedParticleArt) + { + this.textures = art.textures; + this.framerate = art.framerate; + this.duration = art.duration; + this.loop = art.loop; + } + + /** + * Updates the particle. + * @method PIXI.particles.AnimatedParticle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + public update(delta: number): number + { + const lerp = this.Particle_update(delta); + //only animate the particle if it is still alive + if(lerp >= 0) + { + this.elapsed += delta; + if(this.elapsed > this.duration) + { + //loop elapsed back around + if(this.loop) + this.elapsed = this.elapsed % this.duration; + //subtract a small amount to prevent attempting to go past the end of the animation + else + this.elapsed = this.duration - 0.000001; + } + let frame = (this.elapsed * this.framerate + 0.0000001) | 0; + this.texture = this.textures[frame] || PIXI.Texture.EMPTY; + } + return lerp; + } + + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.AnimatedParticle#destroy + */ + public destroy() + { + this.Particle_destroy(); + this.textures = null; + } + + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. + * @method PIXI.particles.AnimatedParticle.parseArt + * @static + * @param {Array} art The array of art data, properly formatted for AnimatedParticle. + * @return {Array} The art, after any needed modifications. + */ + public static parseArt(art: AnimatedParticleArt[]) + { + let data, output: any, textures, tex, outTextures; + let outArr:ParsedAnimatedParticleArt[] = []; + for(let i = 0; i < art.length; ++i) + { + data = art[i]; + outArr[i] = output = {} as ParsedAnimatedParticleArt; + output.textures = outTextures = []; + textures = data.textures; + for(let j = 0; j < textures.length; ++j) + { + tex = textures[j]; + if(typeof tex == "string") + outTextures.push(Texture.fromImage(tex)); + else if(tex instanceof Texture) + outTextures.push(tex); + //assume an object with extra data determining duplicate frame data + else + { + let dupe = tex.count || 1; + if(typeof tex.texture == "string") + tex = Texture.fromImage(tex.texture); + else// if(tex.texture instanceof Texture) + tex = tex.texture; + for(; dupe > 0; --dupe) + { + outTextures.push(tex); + } + } + } + + //use these values to signify that the animation should match the particle life time. + if(data.framerate == "matchLife") + { + //-1 means that it should be calculated + output.framerate = -1; + output.duration = 0; + output.loop = false; + } + else + { + //determine if the animation should loop + output.loop = !!data.loop; + //get the framerate, default to 60 + output.framerate = data.framerate > 0 ? data.framerate : 60; + //determine the duration + output.duration = outTextures.length / output.framerate; + } + } + + return outArr; + } +} \ No newline at end of file diff --git a/src/Emitter.js b/src/Emitter.js deleted file mode 100644 index 1f64a70b..00000000 --- a/src/Emitter.js +++ /dev/null @@ -1,1234 +0,0 @@ -"use strict"; - -var ParticleUtils = require("./ParticleUtils"), - Particle = require("./Particle"), - ParticleContainer = PIXI.particles.ParticleContainer || PIXI.ParticleContainer, - ticker = PIXI.ticker.shared; - -/** - * A particle emitter. - * @memberof PIXI.particles - * @class Emitter - * @constructor - * @param {PIXI.Container} particleParent The container to add the - * particles to. - * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use - * for the particles. Strings will be turned - * into textures via Texture.fromImage(). - * @param {Object} [config] A configuration object containing settings for the emitter. - * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter - * will start disabled. - * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter - * will automatically call update via the PIXI shared ticker. - */ -var Emitter = function(particleParent, particleImages, config) -{ - /** - * The constructor used to create new particles. The default is - * the built in particle class. - * @property {Function} _particleConstructor - * @private - */ - this._particleConstructor = Particle; - //properties for individual particles - /** - * An array of PIXI Texture objects. - * @property {Array} particleImages - */ - this.particleImages = null; - /** - * The starting alpha of all particles. - * @property {Number} startAlpha - * @default 1 - */ - this.startAlpha = 1; - /** - * The ending alpha of all particles. - * @property {Number} endAlpha - * @default 1 - */ - this.endAlpha = 1; - /** - * The starting speed of all particles. - * @property {Number} startSpeed - * @default 0 - */ - this.startSpeed = 0; - /** - * The ending speed of all particles. - * @property {Number} endSpeed - * @default 0 - */ - this.endSpeed = 0; - /** - * A minimum multiplier for the speed of a particle at both start and - * end. A value between minimumSpeedMultiplier and 1 is randomly generated - * and multiplied with startSpeed and endSpeed to provide the actual - * startSpeed and endSpeed for each particle. - * @property {Number} minimumSpeedMultiplier - * @default 1 - */ - this.minimumSpeedMultiplier = 1; - /** - * Acceleration to apply to particles. Using this disables - * any interpolation of particle speed. If the particles do - * not have a rotation speed, then they will be rotated to - * match the direction of travel. - * @property {PIXI.Point} acceleration - * @default null - */ - this.acceleration = null; - /** - * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN - * will disable the maximum speed. - * @property {Number} maxSpeed - * @default NaN - */ - this.maxSpeed = NaN; - /** - * The starting scale of all particles. - * @property {Number} startScale - * @default 1 - */ - this.startScale = 1; - /** - * The ending scale of all particles. - * @property {Number} endScale - * @default 1 - */ - this.endScale = 1; - /** - * A minimum multiplier for the scale of a particle at both start and - * end. A value between minimumScaleMultiplier and 1 is randomly generated - * and multiplied with startScale and endScale to provide the actual - * startScale and endScale for each particle. - * @property {Number} minimumScaleMultiplier - * @default 1 - */ - this.minimumScaleMultiplier = 1; - /** - * The starting color of all particles, as red, green, and blue uints from 0-255. - * @property {Array} startColor - */ - this.startColor = null; - /** - * The ending color of all particles, as red, green, and blue uints from 0-255. - * @property {Array} endColor - */ - this.endColor = null; - /** - * The minimum lifetime for a particle, in seconds. - * @property {Number} minLifetime - */ - this.minLifetime = 0; - /** - * The maximum lifetime for a particle, in seconds. - * @property {Number} maxLifetime - */ - this.maxLifetime = 0; - /** - * The minimum start rotation for a particle, in degrees. This value - * is ignored if the spawn type is "burst" or "arc". - * @property {Number} minStartRotation - */ - this.minStartRotation = 0; - /** - * The maximum start rotation for a particle, in degrees. This value - * is ignored if the spawn type is "burst" or "arc". - * @property {Number} maxStartRotation - */ - this.maxStartRotation = 0; - /** - * If no particle rotation should occur. Starting rotation will still - * affect the direction in which particles move. If the rotation speed - * is set, then this will be ignored. - * @property {Boolean} maxStartRotation - */ - this.noRotation = false; - /** - * The minimum rotation speed for a particle, in degrees per second. - * This only visually spins the particle, it does not change direction - * of movement. - * @property {Number} minRotationSpeed - */ - this.minRotationSpeed = 0; - /** - * The maximum rotation speed for a particle, in degrees per second. - * This only visually spins the particle, it does not change direction - * of movement. - * @property {Number} maxRotationSpeed - */ - this.maxRotationSpeed = 0; - /** - * The blend mode for all particles, as named by PIXI.blendModes. - * @property {int} particleBlendMode - */ - this.particleBlendMode = 0; - /** - * An easing function for nonlinear interpolation of values. Accepts a single - * parameter of time as a value from 0-1, inclusive. Expected outputs are values - * from 0-1, inclusive. - * @property {Function} customEase - */ - this.customEase = null; - /** - * Extra data for use in custom particles. The emitter doesn't look inside, but - * passes it on to the particle to use in init(). - * @property {Object} extraData - */ - this.extraData = null; - //properties for spawning particles - /** - * Time between particle spawns in seconds. - * @property {Number} _frequency - * @private - */ - this._frequency = 1; - /** - * Maximum number of particles to keep alive at a time. If this limit - * is reached, no more particles will spawn until some have died. - * @property {int} maxParticles - * @default 1000 - */ - this.maxParticles = 1000; - /** - * The amount of time in seconds to emit for before setting emit to false. - * A value of -1 is an unlimited amount of time. - * @property {Number} emitterLifetime - * @default -1 - */ - this.emitterLifetime = -1; - /** - * Position at which to spawn particles, relative to the emitter's owner's origin. - * For example, the flames of a rocket travelling right might have a spawnPos - * of {x:-50, y:0}. - * to spawn at the rear of the rocket. - * To change this, use updateSpawnPos(). - * @property {PIXI.Point} spawnPos - * @readOnly - */ - this.spawnPos = null; - /** - * How the particles will be spawned. Valid types are "point", "rectangle", - * "circle", "burst", "ring". - * @property {String} spawnType - * @readOnly - */ - this.spawnType = null; - /** - * A reference to the emitter function specific to the spawn type. - * @property {Function} _spawnFunc - * @private - */ - this._spawnFunc = null; - /** - * A rectangle relative to spawnPos to spawn particles inside if the spawn type is "rect". - * @property {PIXI.Rectangle} spawnRect - */ - this.spawnRect = null; - /** - * A circle relative to spawnPos to spawn particles inside if the spawn type is "circle". - * @property {PIXI.Circle} spawnCircle - */ - this.spawnCircle = null; - /** - * Number of particles to spawn each wave in a burst. - * @property {int} particlesPerWave - * @default 1 - */ - this.particlesPerWave = 1; - /** - * Spacing between particles in a burst. 0 gives a random angle for each particle. - * @property {Number} particleSpacing - * @default 0 - */ - this.particleSpacing = 0; - /** - * Angle at which to start spawning particles in a burst. - * @property {Number} angleStart - * @default 0 - */ - this.angleStart = 0; - /** - * Rotation of the emitter or emitter's owner in degrees. This is added to - * the calculated spawn angle. - * To change this, use rotate(). - * @property {Number} rotation - * @default 0 - * @readOnly - */ - this.rotation = 0; - /** - * The world position of the emitter's owner, to add spawnPos to when - * spawning particles. To change this, use updateOwnerPos(). - * @property {PIXI.Point} ownerPos - * @default {x:0, y:0} - * @readOnly - */ - this.ownerPos = null; - /** - * The origin + spawnPos in the previous update, so that the spawn position - * can be interpolated to space out particles better. - * @property {PIXI.Point} _prevEmitterPos - * @private - */ - this._prevEmitterPos = null; - /** - * If _prevEmitterPos is valid, to prevent interpolation on the first update - * @property {Boolean} _prevPosIsValid - * @private - * @default false - */ - this._prevPosIsValid = false; - /** - * If either ownerPos or spawnPos has changed since the previous update. - * @property {Boolean} _posChanged - * @private - */ - this._posChanged = false; - /** - * If the parent is a ParticleContainer from Pixi V3 - * @property {Boolean} _parentIsPC - * @private - */ - this._parentIsPC = false; - /** - * The container to add particles to. - * @property {PIXI.Container} _parent - * @private - */ - this._parent = null; - /** - * If particles should be added at the back of the display list instead of the front. - * @property {Boolean} addAtBack - */ - this.addAtBack = false; - /** - * The current number of active particles. - * @property {Number} particleCount - * @readOnly - */ - this.particleCount = 0; - /** - * If particles should be emitted during update() calls. Setting this to false - * stops new particles from being created, but allows existing ones to die out. - * @property {Boolean} _emit - * @private - */ - this._emit = false; - /** - * The timer for when to spawn particles in seconds, where numbers less - * than 0 mean that particles should be spawned. - * @property {Number} _spawnTimer - * @private - */ - this._spawnTimer = 0; - /** - * The life of the emitter in seconds. - * @property {Number} _emitterLife - * @private - */ - this._emitterLife = -1; - /** - * The particles that are active and on the display list. This is the first particle in a - * linked list. - * @property {Particle} _activeParticlesFirst - * @private - */ - this._activeParticlesFirst = null; - /** - * The particles that are active and on the display list. This is the last particle in a - * linked list. - * @property {Particle} _activeParticlesLast - * @private - */ - this._activeParticlesLast = null; - /** - * The particles that are not currently being used. This is the first particle in a - * linked list. - * @property {Particle} _poolFirst - * @private - */ - this._poolFirst = null; - /** - * The original config object that this emitter was initialized with. - * @property {Object} _origConfig - * @private - */ - this._origConfig = null; - /** - * The original particle image data that this emitter was initialized with. - * @property {PIXI.Texture|Array|String} _origArt - * @private - */ - this._origArt = null; - /** - * If the update function is called automatically from the shared ticker. - * Setting this to false requires calling the update function manually. - * @property {Boolean} _autoUpdate - * @private - */ - this._autoUpdate = false; - /** - * If the emitter should destroy itself when all particles have died out. This is set by - * playOnceAndDestroy(); - * @property {Boolean} _destroyWhenComplete - * @private - */ - this._destroyWhenComplete = false; - /** - * A callback for when all particles have died out. This is set by - * playOnceAndDestroy() or playOnce(); - * @property {Function} _completeCallback - * @private - */ - this._completeCallback = null; - - //set the initial parent - this.parent = particleParent; - - if(particleImages && config) - this.init(particleImages, config); - - //save often used functions on the instance instead of the prototype for better speed - this.recycle = this.recycle; - this.update = this.update; - this.rotate = this.rotate; - this.updateSpawnPos = this.updateSpawnPos; - this.updateOwnerPos = this.updateOwnerPos; -}; - -// Reference to the prototype -var p = Emitter.prototype = {}; - -var helperPoint = new PIXI.Point(); - -/** - * Time between particle spawns in seconds. If this value is not a number greater than 0, - * it will be set to 1 (particle per second) to prevent infinite loops. - * @member {Number} PIXI.particles.Emitter#frequency - */ -Object.defineProperty(p, "frequency", -{ - get: function() { return this._frequency; }, - set: function(value) - { - //do some error checking to prevent infinite loops - if(typeof value == "number" && value > 0) - this._frequency = value; - else - this._frequency = 1; - } -}); - -/** - * The constructor used to create new particles. The default is - * the built in Particle class. Setting this will dump any active or - * pooled particles, if the emitter has already been used. - * @member {Function} PIXI.particles.Emitter#particleConstructor - */ -Object.defineProperty(p, "particleConstructor", -{ - get: function() { return this._particleConstructor; }, - set: function(value) - { - if(value != this._particleConstructor) - { - this._particleConstructor = value; - //clean up existing particles - this.cleanup(); - //scrap all the particles - for (var particle = this._poolFirst; particle; particle = particle.next) - { - particle.destroy(); - } - this._poolFirst = null; - //re-initialize the emitter so that the new constructor can do anything it needs to - if(this._origConfig && this._origArt) - this.init(this._origArt, this._origConfig); - } - } -}); - -/** -* The container to add particles to. Settings this will dump any active particles. -* @member {PIXI.Container} PIXI.particles.Emitter#parent -*/ -Object.defineProperty(p, "parent", -{ - get: function() { return this._parent; }, - set: function(value) - { - //if our previous parent was a ParticleContainer, then we need to remove - //pooled particles from it - if (this._parentIsPC) { - for (var particle = this._poolFirst; particle; particle = particle.next) - { - if(particle.parent) - particle.parent.removeChild(particle); - } - } - this.cleanup(); - this._parent = value; - this._parentIsPC = ParticleContainer && value && value instanceof ParticleContainer; - } -}); - -/** - * Sets up the emitter based on the config settings. - * @method PIXI.particles.Emitter#init - * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles. - * @param {Object} config A configuration object containing settings for the emitter. - */ -p.init = function(art, config) -{ - if(!art || !config) - return; - //clean up any existing particles - this.cleanup(); - - //store the original config and particle images, in case we need to re-initialize - //when the particle constructor is changed - this._origConfig = config; - this._origArt = art; - - //set up the array of data, also ensuring that it is an array - art = Array.isArray(art) ? art.slice() : [art]; - //run the art through the particle class's parsing function - var partClass = this._particleConstructor; - this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art; - /////////////////////////// - // Particle Properties // - /////////////////////////// - //set up the alpha - if (config.alpha) - { - this.startAlpha = config.alpha.start; - this.endAlpha = config.alpha.end; - } - else - this.startAlpha = this.endAlpha = 1; - //set up the speed - if (config.speed) - { - this.startSpeed = config.speed.start; - this.endSpeed = config.speed.end; - this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1; - } - else - { - this.minimumSpeedMultiplier = 1; - this.startSpeed = this.endSpeed = 0; - } - //set up acceleration - var acceleration = config.acceleration; - if(acceleration && (acceleration.x || acceleration.y)) - { - this.endSpeed = this.startSpeed; - this.acceleration = new PIXI.Point(acceleration.x, acceleration.y); - this.maxSpeed = config.maxSpeed || NaN; - } - else - this.acceleration = new PIXI.Point(); - //set up the scale - if (config.scale) - { - this.startScale = config.scale.start; - this.endScale = config.scale.end; - this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1; - } - else - this.startScale = this.endScale = this.minimumScaleMultiplier = 1; - //set up the color - if (config.color) - { - this.startColor = ParticleUtils.hexToRGB(config.color.start); - //if it's just one color, only use the start color - if (config.color.start != config.color.end) - { - this.endColor = ParticleUtils.hexToRGB(config.color.end); - } - else - this.endColor = null; - } - //set up the start rotation - if (config.startRotation) - { - this.minStartRotation = config.startRotation.min; - this.maxStartRotation = config.startRotation.max; - } - else - this.minStartRotation = this.maxStartRotation = 0; - if (config.noRotation && - (this.minStartRotation || this.maxStartRotation)) - { - this.noRotation = !!config.noRotation; - } - else - this.noRotation = false; - //set up the rotation speed - if (config.rotationSpeed) - { - this.minRotationSpeed = config.rotationSpeed.min; - this.maxRotationSpeed = config.rotationSpeed.max; - } - else - this.minRotationSpeed = this.maxRotationSpeed = 0; - //set up the lifetime - this.minLifetime = config.lifetime.min; - this.maxLifetime = config.lifetime.max; - //get the blend mode - this.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode); - //use the custom ease if provided - if (config.ease) - { - this.customEase = typeof config.ease == "function" ? - config.ease : - ParticleUtils.generateEase(config.ease); - } - else - this.customEase = null; - //set up the extra data, running it through the particle class's parseData function. - if(partClass.parseData) - this.extraData = partClass.parseData(config.extraData); - else - this.extraData = config.extraData || null; - ////////////////////////// - // Emitter Properties // - ////////////////////////// - //reset spawn type specific settings - this.spawnRect = this.spawnCircle = null; - this.particlesPerWave = 1; - this.particleSpacing = 0; - this.angleStart = 0; - var spawnCircle; - //determine the spawn function to use - switch(config.spawnType) - { - case "rect": - this.spawnType = "rect"; - this._spawnFunc = this._spawnRect; - var spawnRect = config.spawnRect; - this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h); - break; - case "circle": - this.spawnType = "circle"; - this._spawnFunc = this._spawnCircle; - spawnCircle = config.spawnCircle; - this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); - break; - case "ring": - this.spawnType = "ring"; - this._spawnFunc = this._spawnRing; - spawnCircle = config.spawnCircle; - this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r); - this.spawnCircle.minRadius = spawnCircle.minR; - break; - case "burst": - this.spawnType = "burst"; - this._spawnFunc = this._spawnBurst; - this.particlesPerWave = config.particlesPerWave; - this.particleSpacing = config.particleSpacing; - this.angleStart = config.angleStart ? config.angleStart : 0; - break; - case "point": - this.spawnType = "point"; - this._spawnFunc = this._spawnPoint; - break; - default: - this.spawnType = "point"; - this._spawnFunc = this._spawnPoint; - break; - } - //set the spawning frequency - this.frequency = config.frequency; - //set the emitter lifetime - this.emitterLifetime = config.emitterLifetime || -1; - //set the max particles - this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000; - //determine if we should add the particle at the back of the list or not - this.addAtBack = !!config.addAtBack; - //reset the emitter position and rotation variables - this.rotation = 0; - this.ownerPos = new PIXI.Point(); - this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y); - this._prevEmitterPos = this.spawnPos.clone(); - //previous emitter position is invalid and should not be used for interpolation - this._prevPosIsValid = false; - //start emitting - this._spawnTimer = 0; - this.emit = config.emit === undefined ? true : !!config.emit; - this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate; -}; - -/** - * Recycles an individual particle. - * @method PIXI.particles.Emitter#recycle - * @param {Particle} particle The particle to recycle. - * @private - */ -p.recycle = function(particle) -{ - if(particle.next) - particle.next.prev = particle.prev; - if(particle.prev) - particle.prev.next = particle.next; - if(particle == this._activeParticlesLast) - this._activeParticlesLast = particle.prev; - if(particle == this._activeParticlesFirst) - this._activeParticlesFirst = particle.next; - //add to pool - particle.prev = null; - particle.next = this._poolFirst; - this._poolFirst = particle; - //remove child from display, or make it invisible if it is in a ParticleContainer - if(this._parentIsPC) - { - particle.alpha = 0; - particle.visible = false; - } - else - { - if(particle.parent) - particle.parent.removeChild(particle); - } - //decrease count - --this.particleCount; -}; - -/** - * Sets the rotation of the emitter to a new value. - * @method PIXI.particles.Emitter#rotate - * @param {Number} newRot The new rotation, in degrees. - */ -p.rotate = function(newRot) -{ - if (this.rotation == newRot) return; - //caclulate the difference in rotation for rotating spawnPos - var diff = newRot - this.rotation; - this.rotation = newRot; - //rotate spawnPos - ParticleUtils.rotatePoint(diff, this.spawnPos); - //mark the position as having changed - this._posChanged = true; -}; - -/** - * Changes the spawn position of the emitter. - * @method PIXI.particles.Emitter#updateSpawnPos - * @param {Number} x The new x value of the spawn position for the emitter. - * @param {Number} y The new y value of the spawn position for the emitter. - */ -p.updateSpawnPos = function(x, y) -{ - this._posChanged = true; - this.spawnPos.x = x; - this.spawnPos.y = y; -}; - -/** - * Changes the position of the emitter's owner. You should call this if you are adding - * particles to the world container that your emitter's owner is moving around in. - * @method PIXI.particles.Emitter#updateOwnerPos - * @param {Number} x The new x value of the emitter's owner. - * @param {Number} y The new y value of the emitter's owner. - */ -p.updateOwnerPos = function(x, y) -{ - this._posChanged = true; - this.ownerPos.x = x; - this.ownerPos.y = y; -}; - -/** - * Prevents emitter position interpolation in the next update. - * This should be used if you made a major position change of your emitter's owner - * that was not normal movement. - * @method PIXI.particles.Emitter#resetPositionTracking - */ -p.resetPositionTracking = function() -{ - this._prevPosIsValid = false; -}; - -/** - * If particles should be emitted during update() calls. Setting this to false - * stops new particles from being created, but allows existing ones to die out. - * @member {Boolean} PIXI.particles.Emitter#emit - */ -Object.defineProperty(p, "emit", -{ - get: function() { return this._emit; }, - set: function(value) - { - this._emit = !!value; - this._emitterLife = this.emitterLifetime; - } -}); - -/** - * If the update function is called automatically from the shared ticker. - * Setting this to false requires calling the update function manually. - * @member {Boolean} PIXI.particles.Emitter#autoUpdate - */ -Object.defineProperty(p, "autoUpdate", -{ - get: function() { return this._autoUpdate; }, - set: function(value) - { - if (this._autoUpdate && !value) - { - ticker.remove(this.update, this); - } - else if (!this._autoUpdate && value) - { - ticker.add(this.update, this); - } - this._autoUpdate = !!value; - } -}); - -/** - * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself - * when particle emission is complete. - * @method PIXI.particles.Emitter#playOnceAndDestroy - * @param {Function} [callback] Callback for when emission is complete (all particles have died off) - */ -p.playOnceAndDestroy = function(callback) -{ - this.autoUpdate = true; - this.emit = true; - this._destroyWhenComplete = true; - this._completeCallback = callback; -}; - -/** - * Starts emitting particles, sets autoUpdate to true, and optionally calls a callback - * when particle emission is complete. - * @method PIXI.particles.Emitter#playOnce - * @param {Function} [callback] Callback for when emission is complete (all particles have died off) - */ -p.playOnce = function(callback) -{ - this.autoUpdate = true; - this.emit = true; - this._completeCallback = callback; -}; - -/** - * Updates all particles spawned by this emitter and emits new ones. - * @method PIXI.particles.Emitter#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - */ -p.update = function(delta) -{ - if (this._autoUpdate) - { - delta = delta / PIXI.settings.TARGET_FPMS / 1000; - } - - //if we don't have a parent to add particles to, then don't do anything. - //this also works as a isDestroyed check - if (!this._parent) return; - //update existing particles - var i, particle, next; - for (particle = this._activeParticlesFirst; particle; particle = next) - { - next = particle.next; - particle.update(delta); - } - var prevX, prevY; - //if the previous position is valid, store these for later interpolation - if(this._prevPosIsValid) - { - prevX = this._prevEmitterPos.x; - prevY = this._prevEmitterPos.y; - } - //store current position of the emitter as local variables - var curX = this.ownerPos.x + this.spawnPos.x; - var curY = this.ownerPos.y + this.spawnPos.y; - //spawn new particles - if (this._emit) - { - //decrease spawn timer - this._spawnTimer -= delta; - //while _spawnTimer < 0, we have particles to spawn - while(this._spawnTimer <= 0) - { - //determine if the emitter should stop spawning - if(this._emitterLife > 0) - { - this._emitterLife -= this._frequency; - if(this._emitterLife <= 0) - { - this._spawnTimer = 0; - this._emitterLife = 0; - this.emit = false; - break; - } - } - //determine if we have hit the particle limit - if(this.particleCount >= this.maxParticles) - { - this._spawnTimer += this._frequency; - continue; - } - //determine the particle lifetime - var lifetime; - if (this.minLifetime == this.maxLifetime) - lifetime = this.minLifetime; - else - lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime; - //only make the particle if it wouldn't immediately destroy itself - if(-this._spawnTimer < lifetime) - { - //If the position has changed and this isn't the first spawn, - //interpolate the spawn position - var emitPosX, emitPosY; - if (this._prevPosIsValid && this._posChanged) - { - //1 - _spawnTimer / delta, but _spawnTimer is negative - var lerp = 1 + this._spawnTimer / delta; - emitPosX = (curX - prevX) * lerp + prevX; - emitPosY = (curY - prevY) * lerp + prevY; - } - else//otherwise just set to the spawn position - { - emitPosX = curX; - emitPosY = curY; - } - //create enough particles to fill the wave (non-burst types have a wave of 1) - i = 0; - for(var len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) - { - //create particle - var p, rand; - if(this._poolFirst) - { - p = this._poolFirst; - this._poolFirst = this._poolFirst.next; - p.next = null; - } - else - { - p = new this.particleConstructor(this); - } - - //set a random texture if we have more than one - if(this.particleImages.length > 1) - { - p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]); - } - else - { - //if they are actually the same texture, a standard particle - //will quit early from the texture setting in setTexture(). - p.applyArt(this.particleImages[0]); - } - //set up the start and end values - p.startAlpha = this.startAlpha; - p.endAlpha = this.endAlpha; - if(this.minimumSpeedMultiplier != 1) - { - rand = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier; - p.startSpeed = this.startSpeed * rand; - p.endSpeed = this.endSpeed * rand; - } - else - { - p.startSpeed = this.startSpeed; - p.endSpeed = this.endSpeed; - } - p.acceleration.x = this.acceleration.x; - p.acceleration.y = this.acceleration.y; - p.maxSpeed = this.maxSpeed; - if(this.minimumScaleMultiplier != 1) - { - rand = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier; - p.startScale = this.startScale * rand; - p.endScale = this.endScale * rand; - } - else - { - p.startScale = this.startScale; - p.endScale = this.endScale; - } - p.startColor = this.startColor; - p.endColor = this.endColor; - //randomize the rotation speed - if(this.minRotationSpeed == this.maxRotationSpeed) - p.rotationSpeed = this.minRotationSpeed; - else - p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed; - p.noRotation = this.noRotation; - //set up the lifetime - p.maxLife = lifetime; - //set the blend mode - p.blendMode = this.particleBlendMode; - //set the custom ease, if any - p.ease = this.customEase; - //set the extra data, if any - p.extraData = this.extraData; - //call the proper function to handle rotation and position of particle - this._spawnFunc(p, emitPosX, emitPosY, i); - //initialize particle - p.init(); - //update the particle by the time passed, so the particles are spread out properly - p.update(-this._spawnTimer);//we want a positive delta, because a negative delta messes things up - //add the particle to the display list - if(!this._parentIsPC || !p.parent) - { - if (this.addAtBack) - this._parent.addChildAt(p, 0); - else - this._parent.addChild(p); - } - else - { - //kind of hacky, but performance friendly - //shuffle children to correct place - var children = this._parent.children; - //avoid using splice if possible - if(children[0] == p) - children.shift(); - else if(children[children.length-1] == p) - children.pop(); - else - { - var index = children.indexOf(p); - children.splice(index, 1); - } - if(this.addAtBack) - children.unshift(p); - else - children.push(p); - } - //add particle to list of active particles - if(this._activeParticlesLast) - { - this._activeParticlesLast.next = p; - p.prev = this._activeParticlesLast; - this._activeParticlesLast = p; - } - else - { - this._activeParticlesLast = this._activeParticlesFirst = p; - } - ++this.particleCount; - } - } - //increase timer and continue on to any other particles that need to be created - this._spawnTimer += this._frequency; - } - } - //if the position changed before this update, then keep track of that - if(this._posChanged) - { - this._prevEmitterPos.x = curX; - this._prevEmitterPos.y = curY; - this._prevPosIsValid = true; - this._posChanged = false; - } - - //if we are all done and should destroy ourselves, take care of that - if (!this._emit && !this._activeParticlesFirst) - { - if (this._completeCallback) - { - this._completeCallback(); - } - if (this._destroyWhenComplete) - { - this.destroy(); - } - } -}; - -/** - * Positions a particle for a point type emitter. - * @method PIXI.particles.Emitter#_spawnPoint - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnPoint = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on - //starting particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; - //drop the particle at the emitter's position - p.position.x = emitPosX; - p.position.y = emitPosY; -}; - -/** - * Positions a particle for a rectangle type emitter. - * @method PIXI.particles.Emitter#_spawnRect - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnRect = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; - //place the particle at a random point in the rectangle - helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x; - helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y; - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a circle type emitter. - * @method PIXI.particles.Emitter#_spawnCircle - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnCircle = function(p, emitPosX, emitPosY) -{ - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + - this.minStartRotation + this.rotation; - //place the particle at a random radius in the circle - helperPoint.x = Math.random() * this.spawnCircle.radius; - helperPoint.y = 0; - //rotate the point to a random angle in the circle - ParticleUtils.rotatePoint(Math.random() * 360, helperPoint); - //offset by the circle's center - helperPoint.x += this.spawnCircle.x; - helperPoint.y += this.spawnCircle.y; - //rotate the point by the emitter's rotation - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - //set the position, offset by the emitter's position - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a ring type emitter. - * @method PIXI.particles.Emitter#_spawnRing - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. Not used for this function. - */ -p._spawnRing = function(p, emitPosX, emitPosY) -{ - var spawnCircle = this.spawnCircle; - //set the initial rotation/direction of the particle based on starting - //particle angle and rotation of emitter - if (this.minStartRotation == this.maxStartRotation) - p.rotation = this.minStartRotation + this.rotation; - else - p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + - this.minStartRotation + this.rotation; - //place the particle at a random radius in the ring - if(spawnCircle.minRadius == spawnCircle.radius) - { - helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) + - spawnCircle.minRadius; - } - else - helperPoint.x = spawnCircle.radius; - helperPoint.y = 0; - //rotate the point to a random angle in the circle - var angle = Math.random() * 360; - p.rotation += angle; - ParticleUtils.rotatePoint(angle, helperPoint); - //offset by the circle's center - helperPoint.x += this.spawnCircle.x; - helperPoint.y += this.spawnCircle.y; - //rotate the point by the emitter's rotation - if(this.rotation !== 0) - ParticleUtils.rotatePoint(this.rotation, helperPoint); - //set the position, offset by the emitter's position - p.position.x = emitPosX + helperPoint.x; - p.position.y = emitPosY + helperPoint.y; -}; - -/** - * Positions a particle for a burst type emitter. - * @method PIXI.particles.Emitter#_spawnBurst - * @private - * @param {Particle} p The particle to position and rotate. - * @param {Number} emitPosX The emitter's x position - * @param {Number} emitPosY The emitter's y position - * @param {int} i The particle number in the current wave. - */ -p._spawnBurst = function(p, emitPosX, emitPosY, i) -{ - //set the initial rotation/direction of the particle based on spawn - //angle and rotation of emitter - if(this.particleSpacing === 0) - p.rotation = Math.random() * 360; - else - p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation; - //drop the particle at the emitter's position - p.position.x = emitPosX; - p.position.y = emitPosY; -}; - -/** - * Kills all active particles immediately. - * @method PIXI.particles.Emitter#cleanup - */ -p.cleanup = function() -{ - var particle, next; - for (particle = this._activeParticlesFirst; particle; particle = next) - { - next = particle.next; - this.recycle(particle); - if(particle.parent) - particle.parent.removeChild(particle); - } - this._activeParticlesFirst = this._activeParticlesLast = null; - this.particleCount = 0; -}; - -/** - * Destroys the emitter and all of its particles. - * @method PIXI.particles.Emitter#destroy - */ -p.destroy = function() -{ - //make sure we aren't still listening to any tickers - this.autoUpdate = false; - //puts all active particles in the pool, and removes them from the particle parent - this.cleanup(); - //wipe the pool clean - var next; - for (var particle = this._poolFirst; particle; particle = next) - { - //store next value so we don't lose it in our destroy call - next = particle.next; - particle.destroy(); - } - this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos = - this.startColor = this.endColor = this.customEase = this._completeCallback = null; -}; - -module.exports = Emitter; \ No newline at end of file diff --git a/src/Emitter.ts b/src/Emitter.ts new file mode 100644 index 00000000..11b5cfcd --- /dev/null +++ b/src/Emitter.ts @@ -0,0 +1,1217 @@ +"use strict"; + +import ParticleUtils, {Color, SimpleEase} from "./ParticleUtils"; +import Particle from "./Particle"; +import PropertyNode from "./PropertyNode"; +import ParticleContainer = PIXI.particles.ParticleContainer; +import ticker = PIXI.ticker.shared; + +export interface ParticleConstructor { + new (emitter:Emitter):Particle; +} + +const helperPoint = new PIXI.Point(); + +/** + * A particle emitter. + * @memberof PIXI.particles + * @class Emitter + * @constructor + * @param {PIXI.Container} particleParent The container to add the + * particles to. + * @param {Array|PIXI.Texture|String} [particleImages] A texture or array of textures to use + * for the particles. Strings will be turned + * into textures via Texture.fromImage(). + * @param {Object} [config] A configuration object containing settings for the emitter. + * @param {Boolean} [config.emit=true] If config.emit is explicitly passed as false, the Emitter + * will start disabled. + * @param {Boolean} [config.autoUpdate=false] If config.emit is explicitly passed as true, the Emitter + * will automatically call update via the PIXI shared ticker. + */ +export default class Emitter +{ + /** + * The constructor used to create new particles. The default is + * the built in particle class. + * @property {Function} _particleConstructor + * @private + */ + protected _particleConstructor: typeof Particle; + //properties for individual particles + /** + * An array of PIXI Texture objects. + * @property {Array} particleImages + */ + public particleImages: any[]; + /** + * The first node in the list of alpha values for all particles. + * @property {PIXI.particles.PropertyNode} startAlpha + */ + public startAlpha: PropertyNode; + /** + * The first node in the list of speed values of all particles. + * @property {Number} startSpeed + */ + public startSpeed: PropertyNode; + /** + * A minimum multiplier for the speed of a particle at all stages of its life. A value between + * minimumSpeedMultiplier and 1 is randomly generated for each particle. + * @property {Number} minimumSpeedMultiplier + * @default 1 + */ + public minimumSpeedMultiplier: number; + /** + * Acceleration to apply to particles. Using this disables + * any interpolation of particle speed. If the particles do + * not have a rotation speed, then they will be rotated to + * match the direction of travel. + * @property {PIXI.Point} acceleration + * @default null + */ + public acceleration: PIXI.Point; + /** + * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN + * will disable the maximum speed. + * @property {Number} maxSpeed + * @default NaN + */ + public maxSpeed: number; + /** + * The first node in the list of scale values of all particles. + * @property {PIXI.particles.PropertyNode} startScale + */ + public startScale: PropertyNode; + /** + * A minimum multiplier for the scale of a particle at all stages of its life. A value between + * minimumScaleMultiplier and 1 is randomly generated for each particle. + * @property {Number} minimumScaleMultiplier + * @default 1 + */ + public minimumScaleMultiplier: number; + /** + * The first node in the list of color values of all particles, as red, green, and blue + * uints from 0-255. + * @property {PIXI.particles.PropertyNode} startColor + */ + public startColor: PropertyNode; + /** + * The minimum lifetime for a particle, in seconds. + * @property {Number} minLifetime + */ + public minLifetime: number; + /** + * The maximum lifetime for a particle, in seconds. + * @property {Number} maxLifetime + */ + public maxLifetime: number; + /** + * The minimum start rotation for a particle, in degrees. This value + * is ignored if the spawn type is "burst" or "arc". + * @property {Number} minStartRotation + */ + public minStartRotation: number; + /** + * The maximum start rotation for a particle, in degrees. This value + * is ignored if the spawn type is "burst" or "arc". + * @property {Number} maxStartRotation + */ + public maxStartRotation: number; + /** + * If no particle rotation should occur. Starting rotation will still + * affect the direction in which particles move. If the rotation speed + * is set, then this will be ignored. + * @property {Boolean} maxStartRotation + */ + public noRotation: boolean; + /** + * The minimum rotation speed for a particle, in degrees per second. + * This only visually spins the particle, it does not change direction + * of movement. + * @property {Number} minRotationSpeed + */ + public minRotationSpeed: number; + /** + * The maximum rotation speed for a particle, in degrees per second. + * This only visually spins the particle, it does not change direction + * of movement. + * @property {Number} maxRotationSpeed + */ + public maxRotationSpeed: number; + /** + * The blend mode for all particles, as named by PIXI.blendModes. + * @property {int} particleBlendMode + */ + public particleBlendMode: number; + /** + * An easing function for nonlinear interpolation of values. Accepts a single + * parameter of time as a value from 0-1, inclusive. Expected outputs are values + * from 0-1, inclusive. + * @property {Function} customEase + */ + public customEase: SimpleEase; + /** + * Extra data for use in custom particles. The emitter doesn't look inside, but + * passes it on to the particle to use in init(). + * @property {Object} extraData + */ + public extraData: any; + //properties for spawning particles + /** + * Time between particle spawns in seconds. + * @property {Number} _frequency + * @private + */ + protected _frequency: number; + /** + * Chance that a particle will be spawned on each opportunity to spawn one. + * 0 is 0%, 1 is 100%. + * @property {Number} spawnChance + */ + public spawnChance: number; + /** + * Maximum number of particles to keep alive at a time. If this limit + * is reached, no more particles will spawn until some have died. + * @property {int} maxParticles + * @default 1000 + */ + public maxParticles: number; + /** + * The amount of time in seconds to emit for before setting emit to false. + * A value of -1 is an unlimited amount of time. + * @property {Number} emitterLifetime + * @default -1 + */ + public emitterLifetime: number; + /** + * Position at which to spawn particles, relative to the emitter's owner's origin. + * For example, the flames of a rocket travelling right might have a spawnPos + * of {x:-50, y:0}. + * to spawn at the rear of the rocket. + * To change this, use updateSpawnPos(). + * @property {PIXI.Point} spawnPos + * @readOnly + */ + public spawnPos: PIXI.Point; + /** + * How the particles will be spawned. Valid types are "point", "rectangle", + * "circle", "burst", "ring". + * @property {String} spawnType + * @readOnly + */ + public spawnType: string; + /** + * A reference to the emitter function specific to the spawn type. + * @property {Function} _spawnFunc + * @private + */ + private _spawnFunc: (p: Particle, emitPosX: number, emitPosY: number, i?: number) => void; + /** + * A rectangle relative to spawnPos to spawn particles inside if the spawn type is "rect". + * @property {PIXI.Rectangle} spawnRect + */ + public spawnRect: PIXI.Rectangle; + /** + * A circle relative to spawnPos to spawn particles inside if the spawn type is "circle". + * @property {PIXI.Circle} spawnCircle + */ + public spawnCircle: PIXI.Circle & {minRadius: number}; + /** + * Number of particles to spawn time that the frequency allows for particles to spawn. + * @property {int} particlesPerWave + * @default 1 + */ + public particlesPerWave: number; + /** + * Spacing between particles in a burst. 0 gives a random angle for each particle. + * @property {Number} particleSpacing + * @default 0 + */ + public particleSpacing: number; + /** + * Angle at which to start spawning particles in a burst. + * @property {Number} angleStart + * @default 0 + */ + public angleStart: number; + /** + * Rotation of the emitter or emitter's owner in degrees. This is added to + * the calculated spawn angle. + * To change this, use rotate(). + * @property {Number} rotation + * @default 0 + * @readOnly + */ + public rotation: number; + /** + * The world position of the emitter's owner, to add spawnPos to when + * spawning particles. To change this, use updateOwnerPos(). + * @property {PIXI.Point} ownerPos + * @default {x:0, y:0} + * @readOnly + */ + public ownerPos: PIXI.Point; + /** + * The origin + spawnPos in the previous update, so that the spawn position + * can be interpolated to space out particles better. + * @property {PIXI.Point} _prevEmitterPos + * @private + */ + protected _prevEmitterPos: PIXI.Point; + /** + * If _prevEmitterPos is valid, to prevent interpolation on the first update + * @property {Boolean} _prevPosIsValid + * @private + * @default false + */ + protected _prevPosIsValid: boolean; + /** + * If either ownerPos or spawnPos has changed since the previous update. + * @property {Boolean} _posChanged + * @private + */ + protected _posChanged: boolean; + /** + * The container to add particles to. + * @property {PIXI.Container} _parent + * @private + */ + protected _parent: PIXI.Container; + /** + * If particles should be added at the back of the display list instead of the front. + * @property {Boolean} addAtBack + */ + public addAtBack: boolean; + /** + * The current number of active particles. + * @property {Number} particleCount + * @readOnly + */ + public particleCount: number; + /** + * If particles should be emitted during update() calls. Setting this to false + * stops new particles from being created, but allows existing ones to die out. + * @property {Boolean} _emit + * @private + */ + protected _emit: boolean; + /** + * The timer for when to spawn particles in seconds, where numbers less + * than 0 mean that particles should be spawned. + * @property {Number} _spawnTimer + * @private + */ + protected _spawnTimer: number; + /** + * The life of the emitter in seconds. + * @property {Number} _emitterLife + * @private + */ + protected _emitterLife: number; + /** + * The particles that are active and on the display list. This is the first particle in a + * linked list. + * @property {Particle} _activeParticlesFirst + * @private + */ + protected _activeParticlesFirst: Particle; + /** + * The particles that are active and on the display list. This is the last particle in a + * linked list. + * @property {Particle} _activeParticlesLast + * @private + */ + protected _activeParticlesLast: Particle; + /** + * The particles that are not currently being used. This is the first particle in a + * linked list. + * @property {Particle} _poolFirst + * @private + */ + protected _poolFirst: Particle; + /** + * The original config object that this emitter was initialized with. + * @property {Object} _origConfig + * @private + */ + protected _origConfig: any; + /** + * The original particle image data that this emitter was initialized with. + * @property {PIXI.Texture|Array|String} _origArt + * @private + */ + protected _origArt: any; + /** + * If the update function is called automatically from the shared ticker. + * Setting this to false requires calling the update function manually. + * @property {Boolean} _autoUpdate + * @private + */ + protected _autoUpdate: boolean; + /** + * If the emitter should destroy itself when all particles have died out. This is set by + * playOnceAndDestroy(); + * @property {Boolean} _destroyWhenComplete + * @private + */ + protected _destroyWhenComplete: boolean; + /** + * A callback for when all particles have died out. This is set by + * playOnceAndDestroy() or playOnce(); + * @property {Function} _completeCallback + * @private + */ + protected _completeCallback: () => void; + + constructor(particleParent: PIXI.Container, particleImages: any, config: any) + { + this._particleConstructor = Particle; + //properties for individual particles + this.particleImages = null; + this.startAlpha = null; + this.startSpeed = null; + this.minimumSpeedMultiplier = 1; + this.acceleration = null; + this.maxSpeed = NaN; + this.startScale = null; + this.minimumScaleMultiplier = 1; + this.startColor = null; + this.minLifetime = 0; + this.maxLifetime = 0; + this.minStartRotation = 0; + this.maxStartRotation = 0; + this.noRotation = false; + this.minRotationSpeed = 0; + this.maxRotationSpeed = 0; + this.particleBlendMode = 0; + this.customEase = null; + this.extraData = null; + //properties for spawning particles + this._frequency = 1; + this.spawnChance = 1; + this.maxParticles = 1000; + this.emitterLifetime = -1; + this.spawnPos = null; + this.spawnType = null; + this._spawnFunc = null; + this.spawnRect = null; + this.spawnCircle = null; + this.particlesPerWave = 1; + this.particleSpacing = 0; + this.angleStart = 0; + //emitter properties + this.rotation = 0; + this.ownerPos = null; + this._prevEmitterPos = null; + this._prevPosIsValid = false; + this._posChanged = false; + this._parent = null; + this.addAtBack = false; + this.particleCount = 0; + this._emit = false; + this._spawnTimer = 0; + this._emitterLife = -1; + this._activeParticlesFirst = null; + this._activeParticlesLast = null; + this._poolFirst = null; + this._origConfig = null; + this._origArt = null; + this._autoUpdate = false; + this._destroyWhenComplete = false; + this._completeCallback = null; + + //set the initial parent + this.parent = particleParent; + + if(particleImages && config) + this.init(particleImages, config); + + //save often used functions on the instance instead of the prototype for better speed + this.recycle = this.recycle; + this.update = this.update; + this.rotate = this.rotate; + this.updateSpawnPos = this.updateSpawnPos; + this.updateOwnerPos = this.updateOwnerPos; + } + + /** + * Time between particle spawns in seconds. If this value is not a number greater than 0, + * it will be set to 1 (particle per second) to prevent infinite loops. + * @member {Number} PIXI.particles.Emitter#frequency + */ + public get frequency() { return this._frequency; } + public set frequency(value) + { + //do some error checking to prevent infinite loops + if(typeof value == "number" && value > 0) + this._frequency = value; + else + this._frequency = 1; + } + /** + * The constructor used to create new particles. The default is + * the built in Particle class. Setting this will dump any active or + * pooled particles, if the emitter has already been used. + * @member {Function} PIXI.particles.Emitter#particleConstructor + */ + public get particleConstructor() { return this._particleConstructor; } + public set particleConstructor(value) + { + if(value != this._particleConstructor) + { + this._particleConstructor = value; + //clean up existing particles + this.cleanup(); + //scrap all the particles + for (let particle = this._poolFirst; particle; particle = particle.next) + { + particle.destroy(); + } + this._poolFirst = null; + //re-initialize the emitter so that the new constructor can do anything it needs to + if(this._origConfig && this._origArt) + this.init(this._origArt, this._origConfig); + } + } + + /** + * The container to add particles to. Settings this will dump any active particles. + * @member {PIXI.Container} PIXI.particles.Emitter#parent + */ + public get parent() { return this._parent; } + public set parent(value) + { + this.cleanup(); + this._parent = value; + } + + /** + * Sets up the emitter based on the config settings. + * @method PIXI.particles.Emitter#init + * @param {Array|PIXI.Texture} art A texture or array of textures to use for the particles. + * @param {Object} config A configuration object containing settings for the emitter. + */ + public init(art: any, config: any) + { + if(!art || !config) + return; + //clean up any existing particles + this.cleanup(); + + //store the original config and particle images, in case we need to re-initialize + //when the particle constructor is changed + this._origConfig = config; + this._origArt = art; + + //set up the array of data, also ensuring that it is an array + art = Array.isArray(art) ? art.slice() : [art]; + //run the art through the particle class's parsing function + const partClass = this._particleConstructor; + this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art; + /////////////////////////// + // Particle Properties // + /////////////////////////// + //set up the alpha + if (config.alpha) + { + this.startAlpha = PropertyNode.createList(config.alpha); + } + else + this.startAlpha = new PropertyNode(1, 0); + //set up the speed + if (config.speed) + { + this.startSpeed = PropertyNode.createList(config.speed); + this.minimumSpeedMultiplier = config.speed.minimumSpeedMultiplier || 1; + } + else + { + this.minimumSpeedMultiplier = 1; + this.startSpeed = new PropertyNode(0, 0); + } + //set up acceleration + let acceleration = config.acceleration; + if(acceleration && (acceleration.x || acceleration.y)) + { + //make sure we disable speed interpolation + this.startSpeed.next = null; + this.acceleration = new PIXI.Point(acceleration.x, acceleration.y); + this.maxSpeed = config.maxSpeed || NaN; + } + else + this.acceleration = new PIXI.Point(); + //set up the scale + if (config.scale) + { + this.startScale = PropertyNode.createList(config.scale); + this.minimumScaleMultiplier = config.scale.minimumScaleMultiplier || 1; + } + else + { + this.startScale = new PropertyNode(1, 0); + this.minimumScaleMultiplier = 1; + } + //set up the color + if (config.color) + { + this.startColor = PropertyNode.createList(config.color); + } + else + { + this.startColor = new PropertyNode({r:0xFF, g:0xFF, b:0xFF}, 0); + } + //set up the start rotation + if (config.startRotation) + { + this.minStartRotation = config.startRotation.min; + this.maxStartRotation = config.startRotation.max; + } + else + this.minStartRotation = this.maxStartRotation = 0; + if (config.noRotation && + (this.minStartRotation || this.maxStartRotation)) + { + this.noRotation = !!config.noRotation; + } + else + this.noRotation = false; + //set up the rotation speed + if (config.rotationSpeed) + { + this.minRotationSpeed = config.rotationSpeed.min; + this.maxRotationSpeed = config.rotationSpeed.max; + } + else + this.minRotationSpeed = this.maxRotationSpeed = 0; + //set up the lifetime + this.minLifetime = config.lifetime.min; + this.maxLifetime = config.lifetime.max; + //get the blend mode + this.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode); + //use the custom ease if provided + if (config.ease) + { + this.customEase = typeof config.ease == "function" ? + config.ease : + ParticleUtils.generateEase(config.ease); + } + else + this.customEase = null; + //set up the extra data, running it through the particle class's parseData function. + if(partClass.parseData) + this.extraData = partClass.parseData(config.extraData); + else + this.extraData = config.extraData || null; + ////////////////////////// + // Emitter Properties // + ////////////////////////// + //reset spawn type specific settings + this.spawnRect = this.spawnCircle = null; + this.particlesPerWave = 1; + if (config.particlesPerWave && config.particlesPerWave > 1) + this.particlesPerWave = config.particlesPerWave; + this.particleSpacing = 0; + this.angleStart = 0; + let spawnCircle; + //determine the spawn function to use + switch(config.spawnType) + { + case "rect": + this.spawnType = "rect"; + this._spawnFunc = this._spawnRect; + let spawnRect = config.spawnRect; + this.spawnRect = new PIXI.Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h); + break; + case "circle": + this.spawnType = "circle"; + this._spawnFunc = this._spawnCircle; + spawnCircle = config.spawnCircle; + this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r) as any; + break; + case "ring": + this.spawnType = "ring"; + this._spawnFunc = this._spawnRing; + spawnCircle = config.spawnCircle; + this.spawnCircle = new PIXI.Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r) as any; + this.spawnCircle.minRadius = spawnCircle.minR; + break; + case "burst": + this.spawnType = "burst"; + this._spawnFunc = this._spawnBurst; + this.particleSpacing = config.particleSpacing; + this.angleStart = config.angleStart ? config.angleStart : 0; + break; + case "point": + this.spawnType = "point"; + this._spawnFunc = this._spawnPoint; + break; + default: + this.spawnType = "point"; + this._spawnFunc = this._spawnPoint; + break; + } + //set the spawning frequency + this.frequency = config.frequency; + this.spawnChance = (typeof config.spawnChance === 'number' && config.spawnChance > 0) ? config.spawnChance : 1; + //set the emitter lifetime + this.emitterLifetime = config.emitterLifetime || -1; + //set the max particles + this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000; + //determine if we should add the particle at the back of the list or not + this.addAtBack = !!config.addAtBack; + //reset the emitter position and rotation variables + this.rotation = 0; + this.ownerPos = new PIXI.Point(); + this.spawnPos = new PIXI.Point(config.pos.x, config.pos.y); + this._prevEmitterPos = this.spawnPos.clone(); + //previous emitter position is invalid and should not be used for interpolation + this._prevPosIsValid = false; + //start emitting + this._spawnTimer = 0; + this.emit = config.emit === undefined ? true : !!config.emit; + this.autoUpdate = config.autoUpdate === undefined ? false : !!config.autoUpdate; + } + + /** + * Recycles an individual particle. + * @method PIXI.particles.Emitter#recycle + * @param {Particle} particle The particle to recycle. + * @private + */ + public recycle(particle: Particle) + { + if(particle.next) + particle.next.prev = particle.prev; + if(particle.prev) + particle.prev.next = particle.next; + if(particle == this._activeParticlesLast) + this._activeParticlesLast = particle.prev; + if(particle == this._activeParticlesFirst) + this._activeParticlesFirst = particle.next; + //add to pool + particle.prev = null; + particle.next = this._poolFirst; + this._poolFirst = particle; + //remove child from display, or make it invisible if it is in a ParticleContainer + if(particle.parent) + particle.parent.removeChild(particle); + //decrease count + --this.particleCount; + } + + /** + * Sets the rotation of the emitter to a new value. + * @method PIXI.particles.Emitter#rotate + * @param {Number} newRot The new rotation, in degrees. + */ + public rotate(newRot: number) + { + if (this.rotation == newRot) return; + //caclulate the difference in rotation for rotating spawnPos + let diff = newRot - this.rotation; + this.rotation = newRot; + //rotate spawnPos + ParticleUtils.rotatePoint(diff, this.spawnPos); + //mark the position as having changed + this._posChanged = true; + } + + /** + * Changes the spawn position of the emitter. + * @method PIXI.particles.Emitter#updateSpawnPos + * @param {Number} x The new x value of the spawn position for the emitter. + * @param {Number} y The new y value of the spawn position for the emitter. + */ + public updateSpawnPos(x: number, y: number) + { + this._posChanged = true; + this.spawnPos.x = x; + this.spawnPos.y = y; + } + + /** + * Changes the position of the emitter's owner. You should call this if you are adding + * particles to the world container that your emitter's owner is moving around in. + * @method PIXI.particles.Emitter#updateOwnerPos + * @param {Number} x The new x value of the emitter's owner. + * @param {Number} y The new y value of the emitter's owner. + */ + public updateOwnerPos(x: number, y: number) + { + this._posChanged = true; + this.ownerPos.x = x; + this.ownerPos.y = y; + } + + /** + * Prevents emitter position interpolation in the next update. + * This should be used if you made a major position change of your emitter's owner + * that was not normal movement. + * @method PIXI.particles.Emitter#resetPositionTracking + */ + public resetPositionTracking() + { + this._prevPosIsValid = false; + } + + /** + * If particles should be emitted during update() calls. Setting this to false + * stops new particles from being created, but allows existing ones to die out. + * @member {Boolean} PIXI.particles.Emitter#emit + */ + public get emit() { return this._emit; }; + public set emit(value) + { + this._emit = !!value; + this._emitterLife = this.emitterLifetime; + } + + /** + * If the update function is called automatically from the shared ticker. + * Setting this to false requires calling the update function manually. + * @member {Boolean} PIXI.particles.Emitter#autoUpdate + */ + public get autoUpdate() { return this._autoUpdate; } + public set autoUpdate(value) + { + if (this._autoUpdate && !value) + { + ticker.remove(this.update, this); + } + else if (!this._autoUpdate && value) + { + ticker.add(this.update, this); + } + this._autoUpdate = !!value; + } + + /** + * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself + * when particle emission is complete. + * @method PIXI.particles.Emitter#playOnceAndDestroy + * @param {Function} [callback] Callback for when emission is complete (all particles have died off) + */ + public playOnceAndDestroy(callback?: () => void) + { + this.autoUpdate = true; + this.emit = true; + this._destroyWhenComplete = true; + this._completeCallback = callback; + } + + /** + * Starts emitting particles and optionally calls a callback when particle emission is complete. + * @method PIXI.particles.Emitter#playOnce + * @param {Function} [callback] Callback for when emission is complete (all particles have died off) + */ + public playOnce(callback?: () => void) + { + this.emit = true; + this._completeCallback = callback; + } + + /** + * Updates all particles spawned by this emitter and emits new ones. + * @method PIXI.particles.Emitter#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + public update(delta: number) + { + if (this._autoUpdate) + { + delta = delta / PIXI.settings.TARGET_FPMS / 1000; + } + + //if we don't have a parent to add particles to, then don't do anything. + //this also works as a isDestroyed check + if (!this._parent) return; + //update existing particles + let i, particle, next; + for (particle = this._activeParticlesFirst; particle; particle = next) + { + next = particle.next; + particle.update(delta); + } + let prevX, prevY; + //if the previous position is valid, store these for later interpolation + if(this._prevPosIsValid) + { + prevX = this._prevEmitterPos.x; + prevY = this._prevEmitterPos.y; + } + //store current position of the emitter as local variables + let curX = this.ownerPos.x + this.spawnPos.x; + let curY = this.ownerPos.y + this.spawnPos.y; + //spawn new particles + if (this._emit) + { + //decrease spawn timer + this._spawnTimer -= delta; + //while _spawnTimer < 0, we have particles to spawn + while(this._spawnTimer <= 0) + { + //determine if the emitter should stop spawning + if(this._emitterLife > 0) + { + this._emitterLife -= this._frequency; + if(this._emitterLife <= 0) + { + this._spawnTimer = 0; + this._emitterLife = 0; + this.emit = false; + break; + } + } + //determine if we have hit the particle limit + if(this.particleCount >= this.maxParticles) + { + this._spawnTimer += this._frequency; + continue; + } + //determine the particle lifetime + let lifetime; + if (this.minLifetime == this.maxLifetime) + lifetime = this.minLifetime; + else + lifetime = Math.random() * (this.maxLifetime - this.minLifetime) + this.minLifetime; + //only make the particle if it wouldn't immediately destroy itself + if(-this._spawnTimer < lifetime) + { + //If the position has changed and this isn't the first spawn, + //interpolate the spawn position + let emitPosX, emitPosY; + if (this._prevPosIsValid && this._posChanged) + { + //1 - _spawnTimer / delta, but _spawnTimer is negative + let lerp = 1 + this._spawnTimer / delta; + emitPosX = (curX - prevX) * lerp + prevX; + emitPosY = (curY - prevY) * lerp + prevY; + } + else//otherwise just set to the spawn position + { + emitPosX = curX; + emitPosY = curY; + } + //create enough particles to fill the wave (non-burst types have a wave of 1) + i = 0; + for(let len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i) + { + //see if we actually spawn one + if (this.spawnChance < 1 && Math.random() >= this.spawnChance) + continue; + //create particle + let p; + if(this._poolFirst) + { + p = this._poolFirst; + this._poolFirst = this._poolFirst.next; + p.next = null; + } + else + { + p = new this.particleConstructor(this); + } + + //set a random texture if we have more than one + if(this.particleImages.length > 1) + { + p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]); + } + else + { + //if they are actually the same texture, a standard particle + //will quit early from the texture setting in setTexture(). + p.applyArt(this.particleImages[0]); + } + //set up the start and end values + p.alphaList.reset(this.startAlpha); + if(this.minimumSpeedMultiplier != 1) + { + p.speedMultiplier = Math.random() * (1 - this.minimumSpeedMultiplier) + this.minimumSpeedMultiplier; + } + p.speedList.reset(this.startSpeed); + p.acceleration.x = this.acceleration.x; + p.acceleration.y = this.acceleration.y; + p.maxSpeed = this.maxSpeed; + if(this.minimumScaleMultiplier != 1) + { + p.scaleMultiplier = Math.random() * (1 - this.minimumScaleMultiplier) + this.minimumScaleMultiplier; + } + p.scaleList.reset(this.startScale); + p.colorList.reset(this.startColor); + //randomize the rotation speed + if(this.minRotationSpeed == this.maxRotationSpeed) + p.rotationSpeed = this.minRotationSpeed; + else + p.rotationSpeed = Math.random() * (this.maxRotationSpeed - this.minRotationSpeed) + this.minRotationSpeed; + p.noRotation = this.noRotation; + //set up the lifetime + p.maxLife = lifetime; + //set the blend mode + p.blendMode = this.particleBlendMode; + //set the custom ease, if any + p.ease = this.customEase; + //set the extra data, if any + p.extraData = this.extraData; + //call the proper function to handle rotation and position of particle + this._spawnFunc(p, emitPosX, emitPosY, i); + //initialize particle + p.init(); + //update the particle by the time passed, so the particles are spread out properly + p.update(-this._spawnTimer);//we want a positive delta, because a negative delta messes things up + //add the particle to the display list + if(!p.parent) + { + if (this.addAtBack) + this._parent.addChildAt(p, 0); + else + this._parent.addChild(p); + } + else + { + //kind of hacky, but performance friendly + //shuffle children to correct place + let children = this._parent.children; + //avoid using splice if possible + if(children[0] == p) + children.shift(); + else if(children[children.length-1] == p) + children.pop(); + else + { + let index = children.indexOf(p); + children.splice(index, 1); + } + if(this.addAtBack) + children.unshift(p); + else + children.push(p); + } + //add particle to list of active particles + if(this._activeParticlesLast) + { + this._activeParticlesLast.next = p; + p.prev = this._activeParticlesLast; + this._activeParticlesLast = p; + } + else + { + this._activeParticlesLast = this._activeParticlesFirst = p; + } + ++this.particleCount; + } + } + //increase timer and continue on to any other particles that need to be created + this._spawnTimer += this._frequency; + } + } + //if the position changed before this update, then keep track of that + if(this._posChanged) + { + this._prevEmitterPos.x = curX; + this._prevEmitterPos.y = curY; + this._prevPosIsValid = true; + this._posChanged = false; + } + + //if we are all done and should destroy ourselves, take care of that + if (!this._emit && !this._activeParticlesFirst) + { + if (this._completeCallback) + { + this._completeCallback(); + } + if (this._destroyWhenComplete) + { + this.destroy(); + } + } + } + + /** + * Positions a particle for a point type emitter. + * @method PIXI.particles.Emitter#_spawnPoint + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + protected _spawnPoint(p: Particle, emitPosX: number, emitPosY: number) + { + //set the initial rotation/direction of the particle based on + //starting particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; + //drop the particle at the emitter's position + p.position.x = emitPosX; + p.position.y = emitPosY; + } + + /** + * Positions a particle for a rectangle type emitter. + * @method PIXI.particles.Emitter#_spawnRect + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + protected _spawnRect(p: Particle, emitPosX: number, emitPosY: number) + { + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + this.minStartRotation + this.rotation; + //place the particle at a random point in the rectangle + helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x; + helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y; + if(this.rotation !== 0) + ParticleUtils.rotatePoint(this.rotation, helperPoint); + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + } + + /** + * Positions a particle for a circle type emitter. + * @method PIXI.particles.Emitter#_spawnCircle + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + protected _spawnCircle(p: Particle, emitPosX: number, emitPosY: number) + { + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + + this.minStartRotation + this.rotation; + //place the particle at a random radius in the circle + helperPoint.x = Math.random() * this.spawnCircle.radius; + helperPoint.y = 0; + //rotate the point to a random angle in the circle + ParticleUtils.rotatePoint(Math.random() * 360, helperPoint); + //offset by the circle's center + helperPoint.x += this.spawnCircle.x; + helperPoint.y += this.spawnCircle.y; + //rotate the point by the emitter's rotation + if(this.rotation !== 0) + ParticleUtils.rotatePoint(this.rotation, helperPoint); + //set the position, offset by the emitter's position + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + } + + /** + * Positions a particle for a ring type emitter. + * @method PIXI.particles.Emitter#_spawnRing + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. Not used for this function. + */ + protected _spawnRing(p: Particle, emitPosX: number, emitPosY: number) + { + let spawnCircle = this.spawnCircle; + //set the initial rotation/direction of the particle based on starting + //particle angle and rotation of emitter + if (this.minStartRotation == this.maxStartRotation) + p.rotation = this.minStartRotation + this.rotation; + else + p.rotation = Math.random() * (this.maxStartRotation - this.minStartRotation) + + this.minStartRotation + this.rotation; + //place the particle at a random radius in the ring + if(spawnCircle.minRadius == spawnCircle.radius) + { + helperPoint.x = Math.random() * (spawnCircle.radius - spawnCircle.minRadius) + + spawnCircle.minRadius; + } + else + helperPoint.x = spawnCircle.radius; + helperPoint.y = 0; + //rotate the point to a random angle in the circle + let angle = Math.random() * 360; + p.rotation += angle; + ParticleUtils.rotatePoint(angle, helperPoint); + //offset by the circle's center + helperPoint.x += this.spawnCircle.x; + helperPoint.y += this.spawnCircle.y; + //rotate the point by the emitter's rotation + if(this.rotation !== 0) + ParticleUtils.rotatePoint(this.rotation, helperPoint); + //set the position, offset by the emitter's position + p.position.x = emitPosX + helperPoint.x; + p.position.y = emitPosY + helperPoint.y; + } + + /** + * Positions a particle for a burst type emitter. + * @method PIXI.particles.Emitter#_spawnBurst + * @private + * @param {Particle} p The particle to position and rotate. + * @param {Number} emitPosX The emitter's x position + * @param {Number} emitPosY The emitter's y position + * @param {int} i The particle number in the current wave. + */ + public _spawnBurst(p: Particle, emitPosX: number, emitPosY: number, i: number) + { + //set the initial rotation/direction of the particle based on spawn + //angle and rotation of emitter + if(this.particleSpacing === 0) + p.rotation = Math.random() * 360; + else + p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation; + //drop the particle at the emitter's position + p.position.x = emitPosX; + p.position.y = emitPosY; + } + + /** + * Kills all active particles immediately. + * @method PIXI.particles.Emitter#cleanup + */ + public cleanup() + { + let particle, next; + for (particle = this._activeParticlesFirst; particle; particle = next) + { + next = particle.next; + this.recycle(particle); + if(particle.parent) + particle.parent.removeChild(particle); + } + this._activeParticlesFirst = this._activeParticlesLast = null; + this.particleCount = 0; + } + + /** + * Destroys the emitter and all of its particles. + * @method PIXI.particles.Emitter#destroy + */ + public destroy() + { + //make sure we aren't still listening to any tickers + this.autoUpdate = false; + //puts all active particles in the pool, and removes them from the particle parent + this.cleanup(); + //wipe the pool clean + let next; + for (let particle = this._poolFirst; particle; particle = next) + { + //store next value so we don't lose it in our destroy call + next = particle.next; + particle.destroy(); + } + this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos = + this.startColor = this.startScale = this.startAlpha = this.startSpeed = + this.customEase = this._completeCallback = null; + } +} diff --git a/src/Particle.js b/src/Particle.js deleted file mode 100644 index 9ce49cbe..00000000 --- a/src/Particle.js +++ /dev/null @@ -1,468 +0,0 @@ -var ParticleUtils = require("./ParticleUtils"); -var Sprite = PIXI.Sprite; - -/** - * An individual particle image. You shouldn't have to deal with these. - * @memberof PIXI.particles - * @class Particle - * @extends PIXI.Sprite - * @constructor - * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle. - */ -var Particle = function(emitter) -{ - //start off the sprite with a blank texture, since we are going to replace it - //later when the particle is initialized. - Sprite.call(this); - - /** - * The emitter that controls this particle. - * @property {Emitter} emitter - */ - this.emitter = emitter; - //particles should be centered - this.anchor.x = this.anchor.y = 0.5; - /** - * The velocity of the particle. Speed may change, but the angle also - * contained in velocity is constant. - * @property {PIXI.Point} velocity - */ - this.velocity = new PIXI.Point(); - /** - * The maximum lifetime of this particle, in seconds. - * @property {Number} maxLife - */ - this.maxLife = 0; - /** - * The current age of the particle, in seconds. - * @property {Number} age - */ - this.age = 0; - /** - * A simple easing function to be applied to all properties that - * are being interpolated. - * @property {Function} ease - */ - this.ease = null; - /** - * Extra data that the emitter passes along for custom particles. - * @property {Object} extraData - */ - this.extraData = null; - /** - * The alpha of the particle at the start of its life. - * @property {Number} startAlpha - */ - this.startAlpha = 0; - /** - * The alpha of the particle at the end of its life. - * @property {Number} endAlpha - */ - this.endAlpha = 0; - /** - * The speed of the particle at the start of its life. - * @property {Number} startSpeed - */ - this.startSpeed = 0; - /** - * The speed of the particle at the end of its life. - * @property {Number} endSpeed - */ - this.endSpeed = 0; - /** - * Acceleration to apply to the particle. - * @property {PIXI.Point} accleration - */ - this.acceleration = new PIXI.Point(); - /** - * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN - * will disable the maximum speed. - * @property {Number} maxSpeed - * @default NaN - */ - this.maxSpeed = NaN; - /** - * The scale of the particle at the start of its life. - * @property {Number} startScale - */ - this.startScale = 0; - /** - * The scale of the particle at the start of its life. - * @property {Number} endScale - */ - this.endScale = 0; - /** - * The tint of the particle at the start of its life. - * @property {Array} startColor - */ - this.startColor = null; - /** - * The red tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sR - * @private - */ - this._sR = 0; - /** - * The green tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sG - * @private - */ - this._sG = 0; - /** - * The blue tint of the particle at the start of its life. - * This is pulled from startColor in init(). - * @property {uint} _sB - * @private - */ - this._sB = 0; - /** - * The tint of the particle at the start of its life. - * @property {Array} endColor - */ - this.endColor = null; - /** - * The red tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _eR - * @private - */ - this._eR = 0; - /** - * The green tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _sG - * @private - */ - this._eG = 0; - /** - * The blue tint of the particle at the end of its life. - * This is pulled from endColor in init(). - * @property {uint} _sB - * @private - */ - this._eB = 0; - /** - * If alpha should be interpolated at all. - * @property {Boolean} _doAlpha - * @private - */ - this._doAlpha = false; - /** - * If scale should be interpolated at all. - * @property {Boolean} _doScale - * @private - */ - this._doScale = false; - /** - * If speed should be interpolated at all. - * @property {Boolean} _doSpeed - * @private - */ - this._doSpeed = false; - /** - * If acceleration should be handled at all. _doSpeed is mutually exclusive with this, - * and _doSpeed gets priority. - * @property {Boolean} _doAcceleration - * @private - */ - this._doAcceleration = false; - /** - * If color should be interpolated at all. - * @property {Boolean} _doColor - * @private - */ - this._doColor = false; - /** - * If normal movement should be handled. Subclasses wishing to override movement - * can set this to false in init(). - * @property {Boolean} _doNormalMovement - * @private - */ - this._doNormalMovement = false; - /** - * One divided by the max life of the particle, saved for slightly faster math. - * @property {Number} _oneOverLife - * @private - */ - this._oneOverLife = 0; - - /** - * Reference to the next particle in the list. - * @property {Particle} next - * @private - */ - this.next = null; - - /** - * Reference to the previous particle in the list. - * @property {Particle} prev - * @private - */ - this.prev = null; - - //save often used functions on the instance instead of the prototype for better speed - this.init = this.init; - this.Particle_init = this.Particle_init; - this.update = this.update; - this.Particle_update = this.Particle_update; - this.applyArt = this.applyArt; - this.kill = this.kill; -}; - -// Reference to the prototype -var p = Particle.prototype = Object.create(Sprite.prototype); - -/** - * Initializes the particle for use, based on the properties that have to - * have been set already on the particle. - * @method PIXI.particles.Particle#init - */ -/** - * A reference to init, so that subclasses can access it without the penalty of Function.call() - * @method PIXI.particles.Particle#Particle_init - * @protected - */ -p.init = p.Particle_init = function() -{ - //reset the age - this.age = 0; - //set up the velocity based on the start speed and rotation - this.velocity.x = this.startSpeed; - this.velocity.y = 0; - ParticleUtils.rotatePoint(this.rotation, this.velocity); - if (this.noRotation) - { - this.rotation = 0; - } - else - { - //convert rotation to Radians from Degrees - this.rotation *= ParticleUtils.DEG_TO_RADS; - } - //convert rotation speed to Radians from Degrees - this.rotationSpeed *= ParticleUtils.DEG_TO_RADS; - //set alpha to inital alpha - this.alpha = this.startAlpha; - //set scale to initial scale - this.scale.x = this.scale.y = this.startScale; - //determine start and end color values - if (this.startColor) - { - this._sR = this.startColor[0]; - this._sG = this.startColor[1]; - this._sB = this.startColor[2]; - if(this.endColor) - { - this._eR = this.endColor[0]; - this._eG = this.endColor[1]; - this._eB = this.endColor[2]; - } - } - //figure out what we need to interpolate - this._doAlpha = this.startAlpha != this.endAlpha; - this._doSpeed = this.startSpeed != this.endSpeed; - this._doScale = this.startScale != this.endScale; - this._doColor = !!this.endColor; - this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0; - //_doNormalMovement can be cancelled by subclasses - this._doNormalMovement = this._doSpeed || this.startSpeed !== 0 || this._doAcceleration; - //save our lerp helper - this._oneOverLife = 1 / this.maxLife; - //set the inital color - this.tint = ParticleUtils.combineRGBComponents(this._sR, this._sG, this._sB); - //ensure visibility - this.visible = true; -}; - -/** - * Sets the texture for the particle. This can be overridden to allow - * for an animated particle. - * @method PIXI.particles.Particle#applyArt - * @param {PIXI.Texture} art The texture to set. - */ -p.applyArt = function(art) -{ - this.texture = art || ParticleUtils.EMPTY_TEXTURE; -}; - -/** - * Updates the particle. - * @method PIXI.particles.Particle#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle - * properties. A value of -1 means the particle died of old age instead. - */ -/** - * A reference to update so that subclasses can access the original without the overhead - * of Function.call(). - * @method PIXI.particles.Particle#Particle_update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle - * properties. A value of -1 means the particle died of old age instead. - * @protected - */ -p.update = p.Particle_update = function(delta) -{ - //increase age - this.age += delta; - //recycle particle if it is too old - if(this.age >= this.maxLife) - { - this.kill(); - return -1; - } - - //determine our interpolation value - var lerp = this.age * this._oneOverLife;//lifetime / maxLife; - if (this.ease) - { - if(this.ease.length == 4) - { - //the t, b, c, d parameters that some tween libraries use - //(time, initial value, end value, duration) - lerp = this.ease(lerp, 0, 1, 1); - } - else - { - //the simplified version that we like that takes - //one parameter, time from 0-1. TweenJS eases provide this usage. - lerp = this.ease(lerp); - } - } - - //interpolate alpha - if (this._doAlpha) - this.alpha = (this.endAlpha - this.startAlpha) * lerp + this.startAlpha; - //interpolate scale - if (this._doScale) - { - var scale = (this.endScale - this.startScale) * lerp + this.startScale; - this.scale.x = this.scale.y = scale; - } - //handle movement - if(this._doNormalMovement) - { - //interpolate speed - if (this._doSpeed) - { - var speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed; - ParticleUtils.normalize(this.velocity); - ParticleUtils.scaleBy(this.velocity, speed); - } - else if(this._doAcceleration) - { - this.velocity.x += this.acceleration.x * delta; - this.velocity.y += this.acceleration.y * delta; - if (this.maxSpeed) - { - var currentSpeed = ParticleUtils.length(this.velocity); - //if we are going faster than we should, clamp at the max speed - //DO NOT recalculate vector length - if (currentSpeed > this.maxSpeed) - { - ParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed); - } - } - } - //adjust position based on velocity - this.position.x += this.velocity.x * delta; - this.position.y += this.velocity.y * delta; - } - //interpolate color - if (this._doColor) - { - var r = (this._eR - this._sR) * lerp + this._sR; - var g = (this._eG - this._sG) * lerp + this._sG; - var b = (this._eB - this._sB) * lerp + this._sB; - this.tint = ParticleUtils.combineRGBComponents(r, g, b); - } - //update rotation - if(this.rotationSpeed !== 0) - { - this.rotation += this.rotationSpeed * delta; - } - else if(this.acceleration && !this.noRotation) - { - this.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2; - } - return lerp; -}; - -/** - * Kills the particle, removing it from the display list - * and telling the emitter to recycle it. - * @method PIXI.particles.Particle#kill - */ -p.kill = function() -{ - this.emitter.recycle(this); -}; - -p.Sprite_Destroy = Sprite.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.Particle#destroy - */ -p.destroy = function() -{ - if (this.parent) - this.parent.removeChild(this); - if (this.Sprite_Destroy) - this.Sprite_Destroy(); - this.emitter = this.velocity = this.startColor = this.endColor = this.ease = - this.next = this.prev = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. - * @method PIXI.particles.Particle.parseArt - * @static - * @param {Array} art The array of art data. For Particle, it should be an array of Textures. - * Any strings in the array will be converted to Textures via - * Texture.fromImage(). - * @return {Array} The art, after any needed modifications. - */ -Particle.parseArt = function(art) -{ - //convert any strings to Textures. - var i; - for(i = art.length; i >= 0; --i) - { - if(typeof art[i] == "string") - art[i] = PIXI.Texture.fromImage(art[i]); - } - //particles from different base textures will be slower in WebGL than if they - //were from one spritesheet - if(ParticleUtils.verbose) - { - for(i = art.length - 1; i > 0; --i) - { - if(art[i].baseTexture != art[i - 1].baseTexture) - { - if (window.console) - console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL"); - break; - } - } - } - - return art; -}; - -/** - * Parses extra emitter data to ensure it is set up for this particle class. - * Particle does nothing to the extra data. - * @method PIXI.particles.Particle.parseData - * @static - * @param {Object} extraData The extra data from the particle config. - * @return {Object} The parsed extra data. - */ -Particle.parseData = function(extraData) -{ - return extraData; -}; - -module.exports = Particle; \ No newline at end of file diff --git a/src/Particle.ts b/src/Particle.ts new file mode 100644 index 00000000..69bd51a5 --- /dev/null +++ b/src/Particle.ts @@ -0,0 +1,509 @@ +import Emitter from "./Emitter"; +import ParticleUtils, {SimpleEase, Color} from "./ParticleUtils"; +import PropertyList from "./PropertyList"; +import Sprite = PIXI.Sprite; + +/** + * An individual particle image. You shouldn't have to deal with these. + * @memberof PIXI.particles + * @class Particle + * @extends PIXI.Sprite + * @constructor + * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle. + */ +export default class Particle extends Sprite +{ + /** + * The emitter that controls this particle. + * @property {Emitter} emitter + */ + public emitter: Emitter; + /** + * The velocity of the particle. Speed may change, but the angle also + * contained in velocity is constant. + * @property {PIXI.Point} velocity + */ + public velocity: PIXI.Point; + /** + * The maximum lifetime of this particle, in seconds. + * @property {Number} maxLife + */ + public maxLife: number; + /** + * The current age of the particle, in seconds. + * @property {Number} age + */ + public age: number; + /** + * A simple easing function to be applied to all properties that + * are being interpolated. + * @property {Function} ease + */ + public ease: SimpleEase; + /** + * Extra data that the emitter passes along for custom particles. + * @property {Object} extraData + */ + public extraData: any; + /** + * The alpha of the particle throughout its life. + * @property {PIXI.particles.PropertyList} alphaList + */ + public alphaList: PropertyList; + /** + * The speed of the particle throughout its life. + * @property {PIXI.particles.PropertyList} speedList + */ + public speedList: PropertyList; + /** + * A multiplier from 0-1 applied to the speed of the particle at all times. + * @property {number} speedMultiplier + */ + public speedMultiplier: number; + /** + * Acceleration to apply to the particle. + * @property {PIXI.Point} accleration + */ + public acceleration: PIXI.Point; + /** + * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN + * will disable the maximum speed. + * @property {Number} maxSpeed + * @default NaN + */ + public maxSpeed: number; + /** + * Speed at which the particle rotates, in radians per second. + * @property {Number} rotationSpeed + */ + public rotationSpeed: number; + /** + * If particle rotation is locked, preventing rotation from occurring due + * to directional changes. + * @property {Number} noRotation + */ + public noRotation: boolean; + /** + * The scale of the particle throughout its life. + * @property {PIXI.particles.PropertyList} scaleList + */ + public scaleList: PropertyList; + /** + * A multiplier from 0-1 applied to the scale of the particle at all times. + * @property {number} scaleMultiplier + */ + public scaleMultiplier: number; + /** + * The tint of the particle throughout its life. + * @property {PIXI.particles.PropertyList} colorList + */ + public colorList: PropertyList; + /** + * A reference to init, so that subclasses can access it without the penalty of Function.call() + * @method PIXI.particles.Particle#Particle_init + * @protected + */ + protected Particle_init: () => void; + /** + * A reference to update so that subclasses can access the original without the overhead + * of Function.call(). + * @method PIXI.particles.Particle#Particle_update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle + * properties. A value of -1 means the particle died of old age instead. + * @protected + */ + protected Particle_update: (delta: number) => number; + protected Particle_destroy: () => void; + protected Sprite_destroy: () => void; + /** + * If alpha should be interpolated at all. + * @property {Boolean} _doAlpha + * @private + */ + protected _doAlpha: boolean; + /** + * If scale should be interpolated at all. + * @property {Boolean} _doScale + * @private + */ + protected _doScale: boolean; + /** + * If speed should be interpolated at all. + * @property {Boolean} _doSpeed + * @private + */ + protected _doSpeed: boolean; + /** + * If acceleration should be handled at all. _doSpeed is mutually exclusive with this, + * and _doSpeed gets priority. + * @property {Boolean} _doAcceleration + * @private + */ + protected _doAcceleration: boolean; + /** + * If color should be interpolated at all. + * @property {Boolean} _doColor + * @private + */ + protected _doColor: boolean; + /** + * If normal movement should be handled. Subclasses wishing to override movement + * can set this to false in init(). + * @property {Boolean} _doNormalMovement + * @private + */ + protected _doNormalMovement: boolean; + /** + * One divided by the max life of the particle, saved for slightly faster math. + * @property {Number} _oneOverLife + * @private + */ + private _oneOverLife: number; + /** + * Reference to the next particle in the list. + * @property {Particle} next + * @private + */ + public next: Particle; + + /** + * Reference to the previous particle in the list. + * @property {Particle} prev + * @private + */ + public prev: Particle; + + constructor(emitter: Emitter) + { + //start off the sprite with a blank texture, since we are going to replace it + //later when the particle is initialized. + super(); + this.emitter = emitter; + //particles should be centered + this.anchor.x = this.anchor.y = 0.5; + this.velocity = new PIXI.Point(); + this.maxLife = 0; + this.age = 0; + this.ease = null; + this.extraData = null; + this.alphaList = new PropertyList(); + this.speedList = new PropertyList(); + this.speedMultiplier = 1; + /** + * Acceleration to apply to the particle. + * @property {PIXI.Point} accleration + */ + this.acceleration = new PIXI.Point(); + /** + * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN + * will disable the maximum speed. + * @property {Number} maxSpeed + * @default NaN + */ + this.maxSpeed = NaN; + /** + * The scale of the particle throughout its life. + * @property {PIXI.particles.PropertyList} scaleList + */ + this.scaleList = new PropertyList(); + /** + * A multiplier from 0-1 applied to the scale of the particle at all times. + * @property {number} scaleMultiplier + */ + this.scaleMultiplier = 1; + /** + * The tint of the particle throughout its life. + * @property {PIXI.particles.PropertyList} colorList + */ + this.colorList = new PropertyList(true); + /** + * If alpha should be interpolated at all. + * @property {Boolean} _doAlpha + * @private + */ + this._doAlpha = false; + /** + * If scale should be interpolated at all. + * @property {Boolean} _doScale + * @private + */ + this._doScale = false; + /** + * If speed should be interpolated at all. + * @property {Boolean} _doSpeed + * @private + */ + this._doSpeed = false; + /** + * If acceleration should be handled at all. _doSpeed is mutually exclusive with this, + * and _doSpeed gets priority. + * @property {Boolean} _doAcceleration + * @private + */ + this._doAcceleration = false; + /** + * If color should be interpolated at all. + * @property {Boolean} _doColor + * @private + */ + this._doColor = false; + /** + * If normal movement should be handled. Subclasses wishing to override movement + * can set this to false in init(). + * @property {Boolean} _doNormalMovement + * @private + */ + this._doNormalMovement = false; + /** + * One divided by the max life of the particle, saved for slightly faster math. + * @property {Number} _oneOverLife + * @private + */ + this._oneOverLife = 0; + + /** + * Reference to the next particle in the list. + * @property {Particle} next + * @private + */ + this.next = null; + + /** + * Reference to the previous particle in the list. + * @property {Particle} prev + * @private + */ + this.prev = null; + + //save often used functions on the instance instead of the prototype for better speed + this.init = this.init; + this.Particle_init = Particle.prototype.init; + this.update = this.update; + this.Particle_update = Particle.prototype.update; + this.Sprite_destroy = super.destroy; + this.Particle_destroy = Particle.prototype.destroy; + this.applyArt = this.applyArt; + this.kill = this.kill; + } + + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.Particle#init + */ + public init() + { + //reset the age + this.age = 0; + //set up the velocity based on the start speed and rotation + this.velocity.x = this.speedList.current.value * this.speedMultiplier; + this.velocity.y = 0; + ParticleUtils.rotatePoint(this.rotation, this.velocity); + if (this.noRotation) + { + this.rotation = 0; + } + else + { + //convert rotation to Radians from Degrees + this.rotation *= ParticleUtils.DEG_TO_RADS; + } + //convert rotation speed to Radians from Degrees + this.rotationSpeed *= ParticleUtils.DEG_TO_RADS; + //set alpha to inital alpha + this.alpha = this.alphaList.current.value; + //set scale to initial scale + this.scale.x = this.scale.y = this.scaleList.current.value; + //figure out what we need to interpolate + this._doAlpha = !!this.alphaList.current.next; + this._doSpeed = !!this.speedList.current.next; + this._doScale = !!this.scaleList.current.next; + this._doColor = !!this.colorList.current.next; + this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0; + //_doNormalMovement can be cancelled by subclasses + this._doNormalMovement = this._doSpeed || this.speedList.current.value !== 0 || this._doAcceleration; + //save our lerp helper + this._oneOverLife = 1 / this.maxLife; + //set the inital color + let color = this.colorList.current.value; + this.tint = ParticleUtils.combineRGBComponents(color.r, color.g, color.b); + //ensure visibility + this.visible = true; + } + + /** + * Sets the texture for the particle. This can be overridden to allow + * for an animated particle. + * @method PIXI.particles.Particle#applyArt + * @param {PIXI.Texture} art The texture to set. + */ + public applyArt(art: any) + { + this.texture = art || PIXI.Texture.EMPTY; + } + + /** + * Updates the particle. + * @method PIXI.particles.Particle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + * @return {Number} The standard interpolation multiplier (0-1) used for all relevant particle + * properties. A value of -1 means the particle died of old age instead. + */ + public update(delta: number): number + { + //increase age + this.age += delta; + //recycle particle if it is too old + if(this.age >= this.maxLife) + { + this.kill(); + return -1; + } + + //determine our interpolation value + let lerp = this.age * this._oneOverLife;//lifetime / maxLife; + if (this.ease) + { + if(this.ease.length == 4) + { + //the t, b, c, d parameters that some tween libraries use + //(time, initial value, end value, duration) + lerp = (this.ease as any)(lerp, 0, 1, 1); + } + else + { + //the simplified version that we like that takes + //one parameter, time from 0-1. TweenJS eases provide this usage. + lerp = this.ease(lerp); + } + } + + //interpolate alpha + if (this._doAlpha) + this.alpha = this.alphaList.interpolate(lerp); + //interpolate scale + if (this._doScale) + { + let scale = this.scaleList.interpolate(lerp) * this.scaleMultiplier; + this.scale.x = this.scale.y = scale; + } + //handle movement + if(this._doNormalMovement) + { + //interpolate speed + if (this._doSpeed) + { + let speed = this.speedList.interpolate(lerp) * this.speedMultiplier; + ParticleUtils.normalize(this.velocity); + ParticleUtils.scaleBy(this.velocity, speed); + } + else if(this._doAcceleration) + { + this.velocity.x += this.acceleration.x * delta; + this.velocity.y += this.acceleration.y * delta; + if (this.maxSpeed) + { + let currentSpeed = ParticleUtils.length(this.velocity); + //if we are going faster than we should, clamp at the max speed + //DO NOT recalculate vector length + if (currentSpeed > this.maxSpeed) + { + ParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed); + } + } + } + //adjust position based on velocity + this.position.x += this.velocity.x * delta; + this.position.y += this.velocity.y * delta; + } + //interpolate color + if (this._doColor) + { + this.tint = this.colorList.interpolate(lerp); + } + //update rotation + if(this.rotationSpeed !== 0) + { + this.rotation += this.rotationSpeed * delta; + } + else if(this.acceleration && !this.noRotation) + { + this.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2; + } + return lerp; + } + + /** + * Kills the particle, removing it from the display list + * and telling the emitter to recycle it. + * @method PIXI.particles.Particle#kill + */ + public kill() + { + this.emitter.recycle(this); + } + + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.Particle#destroy + */ + public destroy() + { + if (this.parent) + this.parent.removeChild(this); + this.Sprite_destroy(); + this.emitter = this.velocity = this.colorList = this.scaleList = this.alphaList = + this.speedList = this.ease = this.next = this.prev = null; + } + + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. + * @method PIXI.particles.Particle.parseArt + * @static + * @param {Array} art The array of art data. For Particle, it should be an array of Textures. + * Any strings in the array will be converted to Textures via + * Texture.fromImage(). + * @return {Array} The art, after any needed modifications. + */ + public static parseArt(art:any[]): any[] + { + //convert any strings to Textures. + let i; + for(i = art.length; i >= 0; --i) + { + if(typeof art[i] == "string") + art[i] = PIXI.Texture.fromImage(art[i]); + } + //particles from different base textures will be slower in WebGL than if they + //were from one spritesheet + if(ParticleUtils.verbose) + { + for(i = art.length - 1; i > 0; --i) + { + if(art[i].baseTexture != art[i - 1].baseTexture) + { + if (window.console) + console.warn("PixiParticles: using particle textures from different images may hinder performance in WebGL"); + break; + } + } + } + + return art; + } + + /** + * Parses extra emitter data to ensure it is set up for this particle class. + * Particle does nothing to the extra data. + * @method PIXI.particles.Particle.parseData + * @static + * @param {Object} extraData The extra data from the particle config. + * @return {Object} The parsed extra data. + */ + public static parseData(extraData: any): any + { + return extraData; + } +} \ No newline at end of file diff --git a/src/ParticleUtils.js b/src/ParticleUtils.js deleted file mode 100644 index 411cc617..00000000 --- a/src/ParticleUtils.js +++ /dev/null @@ -1,181 +0,0 @@ -"use strict"; - -var BLEND_MODES = PIXI.BLEND_MODES || PIXI.blendModes; -var Texture = PIXI.Texture; - -/** - * Contains helper functions for particles and emitters to use. - * @memberof PIXI.particles - * @class ParticleUtils - * @static - */ -var ParticleUtils = {}; - -/** - * If errors and warnings should be logged within the library. - * @name PIXI.particles.ParticleUtils.verbose - * @default false - * @static - */ -ParticleUtils.verbose = false; - -var DEG_TO_RADS = ParticleUtils.DEG_TO_RADS = Math.PI / 180; - -var empty = ParticleUtils.EMPTY_TEXTURE = Texture.EMPTY; -//prevent any events from being used on the empty texture, as well as destruction of it -//v4 of Pixi does this, but doing it again won't hurt -empty.on = empty.destroy = empty.once = empty.emit = function() {}; - -/** - * Rotates a point by a given angle. - * @method PIXI.particles.ParticleUtils.rotatePoint - * @param {Number} angle The angle to rotate by in degrees - * @param {PIXI.Point} p The point to rotate around 0,0. - * @static - */ -ParticleUtils.rotatePoint = function(angle, p) -{ - if(!angle) return; - angle *= DEG_TO_RADS; - var s = Math.sin(angle); - var c = Math.cos(angle); - var xnew = p.x * c - p.y * s; - var ynew = p.x * s + p.y * c; - p.x = xnew; - p.y = ynew; -}; - -/** - * Combines separate color components (0-255) into a single uint color. - * @method PIXI.particles.ParticleUtils.combineRGBComponents - * @param {uint} r The red value of the color - * @param {uint} g The green value of the color - * @param {uint} b The blue value of the color - * @return {uint} The color in the form of 0xRRGGBB - * @static - */ -ParticleUtils.combineRGBComponents = function(r, g, b/*, a*/) -{ - return /*a << 24 |*/ r << 16 | g << 8 | b; -}; - -/** - * Reduces the point to a length of 1. - * @method PIXI.particles.ParticleUtils.normalize - * @static - * @param {PIXI.Point} point The point to normalize - */ -ParticleUtils.normalize = function(point) -{ - var oneOverLen = 1 / ParticleUtils.length(point); - point.x *= oneOverLen; - point.y *= oneOverLen; -}; - -/** - * Multiplies the x and y values of this point by a value. - * @method PIXI.particles.ParticleUtils.scaleBy - * @static - * @param {PIXI.Point} point The point to scaleBy - * @param value {Number} The value to scale by. - */ -ParticleUtils.scaleBy = function(point, value) -{ - point.x *= value; - point.y *= value; -}; - -/** - * Returns the length (or magnitude) of this point. - * @method PIXI.particles.ParticleUtils.length - * @static - * @param {PIXI.Point} point The point to measure length - * @return The length of this point. - */ -ParticleUtils.length = function(point) -{ - return Math.sqrt(point.x * point.x + point.y * point.y); -}; - -/** - * Converts a hex string from "#AARRGGBB", "#RRGGBB", "0xAARRGGBB", "0xRRGGBB", - * "AARRGGBB", or "RRGGBB" to an array of ints of 0-255 or Numbers from 0-1, as - * [r, g, b, (a)]. - * @method PIXI.particles.ParticleUtils.hexToRGB - * @param {String} color The input color string. - * @param {Array} output An array to put the output in. If omitted, a new array is created. - * @return The array of numeric color values. - * @static - */ -ParticleUtils.hexToRGB = function(color, output) -{ - if (output) - output.length = 0; - else - output = []; - if (color.charAt(0) == "#") - color = color.substr(1); - else if (color.indexOf("0x") === 0) - color = color.substr(2); - var alpha; - if (color.length == 8) - { - alpha = color.substr(0, 2); - color = color.substr(2); - } - output.push(parseInt(color.substr(0, 2), 16));//Red - output.push(parseInt(color.substr(2, 2), 16));//Green - output.push(parseInt(color.substr(4, 2), 16));//Blue - if (alpha) - output.push(parseInt(alpha, 16)); - return output; -}; - -/** - * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated - * by the related tool at http://www.greensock.com/customease/. - * @method PIXI.particles.ParticleUtils.generateEase - * @param {Array} segments An array of segments, as created by - * http://www.greensock.com/customease/. - * @return {Function} A function that calculates the percentage of change at - * a given point in time (0-1 inclusive). - * @static - */ -ParticleUtils.generateEase = function(segments) -{ - var qty = segments.length; - var oneOverQty = 1 / qty; - /* - * Calculates the percentage of change at a given point in time (0-1 inclusive). - * @param {Number} time The time of the ease, 0-1 inclusive. - * @return {Number} The percentage of the change, 0-1 inclusive (unless your - * ease goes outside those bounds). - */ - var simpleEase = function(time) - { - var t, s; - var i = (qty * time) | 0;//do a quick floor operation - t = (time - (i * oneOverQty)) * qty; - s = segments[i] || segments[qty - 1]; - return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s))); - }; - return simpleEase; -}; - -/** - * Gets a blend mode, ensuring that it is valid. - * @method PIXI.particles.ParticleUtils.getBlendMode - * @param {String} name The name of the blend mode to get. - * @return {int} The blend mode as specified in the PIXI.blendModes enumeration. - * @static - */ -ParticleUtils.getBlendMode = function(name) -{ - if (!name) return BLEND_MODES.NORMAL; - name = name.toUpperCase(); - while (name.indexOf(" ") >= 0) - name = name.replace(" ", "_"); - return BLEND_MODES[name] || BLEND_MODES.NORMAL; -}; - -module.exports = ParticleUtils; \ No newline at end of file diff --git a/src/ParticleUtils.ts b/src/ParticleUtils.ts new file mode 100644 index 00000000..c6e013f3 --- /dev/null +++ b/src/ParticleUtils.ts @@ -0,0 +1,232 @@ +"use strict"; + +import BLEND_MODES = PIXI.BLEND_MODES; +import PropertyNode, {ValueStep} from './PropertyNode'; + +export interface Color { + r: number, + g: number, + b: number, + a?: number +} + +export interface EaseSegment { + cp:number; + s:number; + e:number; +} + +export type SimpleEase = (time:number) => number; + +/** + * Contains helper functions for particles and emitters to use. + * @memberof PIXI.particles + * @class ParticleUtils + * @static + */ +const ParticleUtils = { + /** + * If errors and warnings should be logged within the library. + * @name PIXI.particles.ParticleUtils.verbose + * @default false + * @static + */ + verbose: false, + + DEG_TO_RADS: Math.PI / 180, + + /** + * Rotates a point by a given angle. + * @method PIXI.particles.ParticleUtils.rotatePoint + * @param {Number} angle The angle to rotate by in degrees + * @param {PIXI.Point} p The point to rotate around 0,0. + * @static + */ + rotatePoint(angle:number, p:PIXI.Point): void + { + if (!angle) return; + angle *= ParticleUtils.DEG_TO_RADS; + const s = Math.sin(angle); + const c = Math.cos(angle); + const xnew = p.x * c - p.y * s; + const ynew = p.x * s + p.y * c; + p.x = xnew; + p.y = ynew; + }, + + /** + * Combines separate color components (0-255) into a single uint color. + * @method PIXI.particles.ParticleUtils.combineRGBComponents + * @param {uint} r The red value of the color + * @param {uint} g The green value of the color + * @param {uint} b The blue value of the color + * @return {uint} The color in the form of 0xRRGGBB + * @static + */ + combineRGBComponents(r:number, g:number, b:number/*, a*/): number + { + return /*a << 24 |*/ r << 16 | g << 8 | b; + }, + + /** + * Reduces the point to a length of 1. + * @method PIXI.particles.ParticleUtils.normalize + * @static + * @param {PIXI.Point} point The point to normalize + */ + normalize(point:PIXI.Point): void + { + let oneOverLen = 1 / ParticleUtils.length(point); + point.x *= oneOverLen; + point.y *= oneOverLen; + }, + + /** + * Multiplies the x and y values of this point by a value. + * @method PIXI.particles.ParticleUtils.scaleBy + * @static + * @param {PIXI.Point} point The point to scaleBy + * @param {number} value The value to scale by. + */ + scaleBy(point:PIXI.Point, value:number): void + { + point.x *= value; + point.y *= value; + }, + + /** + * Returns the length (or magnitude) of this point. + * @method PIXI.particles.ParticleUtils.length + * @static + * @param {PIXI.Point} point The point to measure length + * @return The length of this point. + */ + length(point:PIXI.Point): number + { + return Math.sqrt(point.x * point.x + point.y * point.y); + }, + + /** + * Converts a hex string from "#AARRGGBB", "#RRGGBB", "0xAARRGGBB", "0xRRGGBB", + * "AARRGGBB", or "RRGGBB" to an object of ints of 0-255, as + * {r, g, b, (a)}. + * @method PIXI.particles.ParticleUtils.hexToRGB + * @param {string} color The input color string. + * @param {Object} [output] An object to put the output in. If omitted, a new object is created. + * @return The object with r, g, and b properties, possibly with an a property. + * @static + */ + hexToRGB(color:string, output?:Color): Color + { + if (!output) + output = {} as Color; + if (color.charAt(0) == "#") + color = color.substr(1); + else if (color.indexOf("0x") === 0) + color = color.substr(2); + let alpha; + if (color.length == 8) + { + alpha = color.substr(0, 2); + color = color.substr(2); + } + output.r = parseInt(color.substr(0, 2), 16);//Red + output.g = parseInt(color.substr(2, 2), 16);//Green + output.b = parseInt(color.substr(4, 2), 16);//Blue + if (alpha) + output.a = parseInt(alpha, 16); + return output; + }, + + /** + * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated + * by the related tool at http://www.greensock.com/customease/. + * @method PIXI.particles.ParticleUtils.generateEase + * @param {Array} segments An array of segments, as created by + * http://www.greensock.com/customease/. + * @return {Function} A function that calculates the percentage of change at + * a given point in time (0-1 inclusive). + * @static + */ + generateEase(segments:EaseSegment[]): SimpleEase + { + const qty = segments.length; + const oneOverQty = 1 / qty; + /* + * Calculates the percentage of change at a given point in time (0-1 inclusive). + * @param {Number} time The time of the ease, 0-1 inclusive. + * @return {Number} The percentage of the change, 0-1 inclusive (unless your + * ease goes outside those bounds). + */ + return function(time:number) + { + let t: number, s: EaseSegment; + let i = (qty * time) | 0;//do a quick floor operation + t = (time - (i * oneOverQty)) * qty; + s = segments[i] || segments[qty - 1]; + return (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s))); + }; + }, + + /** + * Gets a blend mode, ensuring that it is valid. + * @method PIXI.particles.ParticleUtils.getBlendMode + * @param {string} name The name of the blend mode to get. + * @return {int} The blend mode as specified in the PIXI.BLEND_MODES enumeration. + * @static + */ + getBlendMode(name:string): number + { + if (!name) return BLEND_MODES.NORMAL; + name = name.toUpperCase(); + while (name.indexOf(" ") >= 0) + name = name.replace(" ", "_"); + return (BLEND_MODES as any)[name] || BLEND_MODES.NORMAL; + }, + + /** + * Converts a list of {value, time} objects starting at time 0 and ending at time 1 into an evenly + * spaced stepped list of PropertyNodes for color values. This is primarily to handle conversion of + * linear gradients to fewer colors, allowing for some optimization for Canvas2d fallbacks. + * @method PIXI.particles.ParticleUtils.createSteppedGradient + * @param {Array} list The list of data to convert. + * @param {number} [numSteps=10] The number of steps to use. + * @return {PIXI.particles.PropertyNode} The blend mode as specified in the PIXI.blendModes enumeration. + * @static + */ + createSteppedGradient(list:ValueStep[], numSteps:number = 10) { + if (typeof numSteps !== 'number' || numSteps <= 0) + numSteps = 10; + let first = new PropertyNode(list[0].value as string, list[0].time); + first.isStepped = true; + let currentNode = first; + let current = list[0]; + let nextIndex = 1; + let next = list[nextIndex]; + for (let i = 1; i < numSteps; ++i) + { + let lerp = i / numSteps; + //ensure we are on the right segment, if multiple + while (lerp > next.time) + { + current = next; + next = list[++nextIndex]; + } + //convert the lerp value to the segment range + lerp = (lerp - current.time) / (next.time - current.time); + let curVal = ParticleUtils.hexToRGB(current.value as string); + let nextVal = ParticleUtils.hexToRGB(next.value as string); + let output:Color = {} as Color; + output.r = (nextVal.r - curVal.r) * lerp + curVal.r; + output.g = (nextVal.g - curVal.g) * lerp + curVal.g; + output.b = (nextVal.b - curVal.b) * lerp + curVal.b; + currentNode.next = new PropertyNode(output, i / numSteps); + currentNode = currentNode.next; + } + //we don't need to have a PropertyNode for time of 1, because in a stepped version at that point + //the particle has died of old age + return first; + } +}; + +export default ParticleUtils; \ No newline at end of file diff --git a/src/PathParticle.js b/src/PathParticle.js deleted file mode 100644 index fa8c1bb0..00000000 --- a/src/PathParticle.js +++ /dev/null @@ -1,230 +0,0 @@ -"use strict"; - -var ParticleUtils = require("./ParticleUtils"), - Particle = require("./Particle"); - -/** - * An particle that follows a path defined by an algebraic expression, e.g. "sin(x)" or - * "5x + 3". - * To use this class, the particle config must have a "path" string in the - * "extraData" parameter. This string should have "x" in it to represent movement (from the - * speed settings of the particle). It may have numbers, parentheses, the four basic - * operations, and the following Math functions or properties (without the preceding "Math."): - * "pow", "sqrt", "abs", "floor", "round", "ceil", "E", "PI", "sin", "cos", "tan", "asin", - * "acos", "atan", "atan2", "log". - * The overall movement of the particle and the expression value become x and y positions for - * the particle, respectively. The final position is rotated by the spawn rotation/angle of - * the particle. - * - * Some example paths: - * - * "sin(x/10) * 20" // A sine wave path. - * "cos(x/100) * 30" // Particles curve counterclockwise (for medium speed/low lifetime particles) - * "pow(x/10, 2) / 2" // Particles curve clockwise (remember, +y is down). - * - * @memberof PIXI.particles - * @class PathParticle - * @extends PIXI.particles.Particle - * @constructor - * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle. - */ -var PathParticle = function(emitter) -{ - Particle.call(this, emitter); - /** - * The function representing the path the particle should take. - * @property {Function} path - */ - this.path = null; - /** - * The initial rotation in degrees of the particle, because the direction of the path - * is based on that. - * @property {Number} initialRotation - */ - this.initialRotation = 0; - /** - * The initial position of the particle, as all path movement is added to that. - * @property {PIXI.Point} initialPosition - */ - this.initialPosition = new PIXI.Point(); - /** - * Total single directional movement, due to speed. - * @property {Number} movement - */ - this.movement = 0; -}; - -// Reference to the super class -var s = Particle.prototype; -// Reference to the prototype -var p = PathParticle.prototype = Object.create(s); - -/** - * A helper point for math things. - * @property {Function} helperPoint - * @private - * @static - */ -var helperPoint = new PIXI.Point(); - -/** - * Initializes the particle for use, based on the properties that have to - * have been set already on the particle. - * @method PIXI.particles.PathParticle#init - */ -p.init = function() -{ - //get initial rotation before it is converted to radians - this.initialRotation = this.rotation; - //standard init - this.Particle_init(); - - //set the path for the particle - this.path = this.extraData.path; - //cancel the normal movement behavior - this._doNormalMovement = !this.path; - //reset movement - this.movement = 0; - //grab position - this.initialPosition.x = this.position.x; - this.initialPosition.y = this.position.y; -}; - -//a hand picked list of Math functions (and a couple properties) that are allowable. -//they should be used without the preceding "Math." -var MATH_FUNCS = -[ - "pow", - "sqrt", - "abs", - "floor", - "round", - "ceil", - "E", - "PI", - "sin", - "cos", - "tan", - "asin", - "acos", - "atan", - "atan2", - "log" -]; -//Allow the 4 basic operations, parentheses and all numbers/decimals, as well -//as 'x', for the variable usage. -var WHITELISTER = "[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]"; -//add the math functions to the regex string. -for(var index = MATH_FUNCS.length - 1; index >= 0; --index) -{ - WHITELISTER += "|" + MATH_FUNCS[index]; -} -//create an actual regular expression object from the string -WHITELISTER = new RegExp(WHITELISTER, "g"); - -/** - * Parses a string into a function for path following. - * This involves whitelisting the string for safety, inserting "Math." to math function - * names, and using `new Function()` to generate a function. - * @method PIXI.particles.PathParticle~parsePath - * @private - * @static - * @param {String} pathString The string to parse. - * @return {Function} The path function - takes x, outputs y. - */ -var parsePath = function(pathString) -{ - var matches = pathString.match(WHITELISTER); - for(var i = matches.length - 1; i >= 0; --i) - { - if(MATH_FUNCS.indexOf(matches[i]) >= 0) - matches[i] = "Math." + matches[i]; - } - pathString = matches.join(""); - return new Function("x", "return "+ pathString + ";"); -}; - -/** - * Updates the particle. - * @method PIXI.particles.PathParticle#update - * @param {Number} delta Time elapsed since the previous frame, in __seconds__. - */ -p.update = function(delta) -{ - var lerp = this.Particle_update(delta); - //if the particle died during the update, then don't bother - if(lerp >= 0 && this.path) - { - //increase linear movement based on speed - var speed = (this.endSpeed - this.startSpeed) * lerp + this.startSpeed; - this.movement += speed * delta; - //set up the helper point for rotation - helperPoint.x = this.movement; - helperPoint.y = this.path(this.movement); - ParticleUtils.rotatePoint(this.initialRotation, helperPoint); - this.position.x = this.initialPosition.x + helperPoint.x; - this.position.y = this.initialPosition.y + helperPoint.y; - } -}; - -p.Particle_destroy = Particle.prototype.destroy; -/** - * Destroys the particle, removing references and preventing future use. - * @method PIXI.particles.PathParticle#destroy - */ -p.destroy = function() -{ - this.Particle_destroy(); - this.path = this.initialPosition = null; -}; - -/** - * Checks over the art that was passed to the Emitter's init() function, to do any special - * modifications to prepare it ahead of time. This just runs Particle.parseArt(). - * @method PIXI.particles.PathParticle.parseArt - * @static - * @param {Array} art The array of art data. For Particle, it should be an array of Textures. - * Any strings in the array will be converted to Textures via - * Texture.fromImage(). - * @return {Array} The art, after any needed modifications. - */ -PathParticle.parseArt = function(art) -{ - return Particle.parseArt(art); -}; - -/** - * Parses extra emitter data to ensure it is set up for this particle class. - * PathParticle checks for the existence of path data, and parses the path data for use - * by particle instances. - * @method PIXI.particles.PathParticle.parseData - * @static - * @param {Object} extraData The extra data from the particle config. - * @return {Object} The parsed extra data. - */ -PathParticle.parseData = function(extraData) -{ - var output = {}; - if(extraData && extraData.path) - { - try - { - output.path = parsePath(extraData.path); - } - catch(e) - { - if(ParticleUtils.verbose) - console.error("PathParticle: error in parsing path expression"); - output.path = null; - } - } - else - { - if(ParticleUtils.verbose) - console.error("PathParticle requires a path string in extraData!"); - output.path = null; - } - return output; -}; - -module.exports = PathParticle; \ No newline at end of file diff --git a/src/PathParticle.ts b/src/PathParticle.ts new file mode 100644 index 00000000..f310f79a --- /dev/null +++ b/src/PathParticle.ts @@ -0,0 +1,229 @@ +"use strict"; + +import ParticleUtils from "./ParticleUtils"; +import Particle from "./Particle"; +import Emitter from "./Emitter"; + +/** + * A helper point for math things. + * @private + */ +const helperPoint = new PIXI.Point(); + +//a hand picked list of Math functions (and a couple properties) that are allowable. +//they should be used without the preceding "Math." +const MATH_FUNCS = +[ + "pow", + "sqrt", + "abs", + "floor", + "round", + "ceil", + "E", + "PI", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "atan2", + "log" +]; +//create an actual regular expression object from the string +const WHITELISTER = new RegExp( + [ + //Allow the 4 basic operations, parentheses and all numbers/decimals, as well + //as 'x', for the variable usage. + "[01234567890\\.\\*\\-\\+\\/\\(\\)x ,]", + ].concat(MATH_FUNCS).join("|"), + "g" +); + +/** + * Parses a string into a function for path following. + * This involves whitelisting the string for safety, inserting "Math." to math function + * names, and using `new Function()` to generate a function. + * @method PIXI.particles.PathParticle~parsePath + * @private + * @static + * @param {String} pathString The string to parse. + * @return {Function} The path function - takes x, outputs y. + */ +const parsePath = function(pathString: string) +{ + let matches = pathString.match(WHITELISTER); + for(let i = matches.length - 1; i >= 0; --i) + { + if(MATH_FUNCS.indexOf(matches[i]) >= 0) + matches[i] = "Math." + matches[i]; + } + pathString = matches.join(""); + return new Function("x", "return "+ pathString + ";"); +}; + +/** + * An particle that follows a path defined by an algebraic expression, e.g. "sin(x)" or + * "5x + 3". + * To use this class, the particle config must have a "path" string in the + * "extraData" parameter. This string should have "x" in it to represent movement (from the + * speed settings of the particle). It may have numbers, parentheses, the four basic + * operations, and the following Math functions or properties (without the preceding "Math."): + * "pow", "sqrt", "abs", "floor", "round", "ceil", "E", "PI", "sin", "cos", "tan", "asin", + * "acos", "atan", "atan2", "log". + * The overall movement of the particle and the expression value become x and y positions for + * the particle, respectively. The final position is rotated by the spawn rotation/angle of + * the particle. + * + * Some example paths: + * + * "sin(x/10) * 20" // A sine wave path. + * "cos(x/100) * 30" // Particles curve counterclockwise (for medium speed/low lifetime particles) + * "pow(x/10, 2) / 2" // Particles curve clockwise (remember, +y is down). + * + * @memberof PIXI.particles + * @class PathParticle + * @extends PIXI.particles.Particle + * @constructor + * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle. + */ +export default class PathParticle extends Particle +{ + /** + * The function representing the path the particle should take. + * @property {Function} path + */ + public path: Function; + /** + * The initial rotation in degrees of the particle, because the direction of the path + * is based on that. + * @property {Number} initialRotation + */ + public initialRotation: number; + /** + * The initial position of the particle, as all path movement is added to that. + * @property {PIXI.Point} initialPosition + */ + public initialPosition: PIXI.Point; + /** + * Total single directional movement, due to speed. + * @property {Number} movement + */ + public movement: number; + + constructor(emitter: Emitter) + { + super(emitter); + this.path = null; + this.initialRotation = 0; + this.initialPosition = new PIXI.Point(); + this.movement = 0; + } + + /** + * Initializes the particle for use, based on the properties that have to + * have been set already on the particle. + * @method PIXI.particles.PathParticle#init + */ + public init() + { + //get initial rotation before it is converted to radians + this.initialRotation = this.rotation; + //standard init + this.Particle_init(); + + //set the path for the particle + this.path = this.extraData.path; + //cancel the normal movement behavior + this._doNormalMovement = !this.path; + //reset movement + this.movement = 0; + //grab position + this.initialPosition.x = this.position.x; + this.initialPosition.y = this.position.y; + } + + /** + * Updates the particle. + * @method PIXI.particles.PathParticle#update + * @param {Number} delta Time elapsed since the previous frame, in __seconds__. + */ + public update(delta: number): number + { + const lerp = this.Particle_update(delta); + //if the particle died during the update, then don't bother + if(lerp >= 0 && this.path) + { + //increase linear movement based on speed + const speed = this.speedList.interpolate(lerp) * this.speedMultiplier; + this.movement += speed * delta; + //set up the helper point for rotation + helperPoint.x = this.movement; + helperPoint.y = this.path(this.movement); + ParticleUtils.rotatePoint(this.initialRotation, helperPoint); + this.position.x = this.initialPosition.x + helperPoint.x; + this.position.y = this.initialPosition.y + helperPoint.y; + } + return lerp; + } + + /** + * Destroys the particle, removing references and preventing future use. + * @method PIXI.particles.PathParticle#destroy + */ + public destroy() + { + this.Particle_destroy(); + this.path = this.initialPosition = null; + } + + /** + * Checks over the art that was passed to the Emitter's init() function, to do any special + * modifications to prepare it ahead of time. This just runs Particle.parseArt(). + * @method PIXI.particles.PathParticle.parseArt + * @static + * @param {Array} art The array of art data. For Particle, it should be an array of Textures. + * Any strings in the array will be converted to Textures via + * Texture.fromImage(). + * @return {Array} The art, after any needed modifications. + */ + public static parseArt(art: any[]) + { + return Particle.parseArt(art); + } + + /** + * Parses extra emitter data to ensure it is set up for this particle class. + * PathParticle checks for the existence of path data, and parses the path data for use + * by particle instances. + * @method PIXI.particles.PathParticle.parseData + * @static + * @param {Object} extraData The extra data from the particle config. + * @return {Object} The parsed extra data. + */ + public static parseData(extraData: {path:string}) + { + let output: any = {}; + if(extraData && extraData.path) + { + try + { + output.path = parsePath(extraData.path); + } + catch(e) + { + if(ParticleUtils.verbose) + console.error("PathParticle: error in parsing path expression"); + output.path = null; + } + } + else + { + if(ParticleUtils.verbose) + console.error("PathParticle requires a path string in extraData!"); + output.path = null; + } + return output; + } +} \ No newline at end of file diff --git a/src/PropertyList.ts b/src/PropertyList.ts new file mode 100644 index 00000000..8616deb5 --- /dev/null +++ b/src/PropertyList.ts @@ -0,0 +1,160 @@ +import ParticleUtils, {SimpleEase, Color} from "./ParticleUtils"; +import PropertyNode from "./PropertyNode"; + +/** + * Singly linked list container for keeping track of interpolated properties for particles. + * Each Particle will have one of these for each interpolated property. + * @memberof PIXI.particles + * @class PropertyList + * @constructor + * @param {boolean} isColor If this list handles color values + */ +export default class PropertyList +{ + /** + * The current property node in the linked list. + * @property {PIXI.particles.PropertyNode} current + */ + public current: PropertyNode; + /** + * The next property node in the linked list. Stored separately for slightly less variable + * access. + * @property {PIXI.particles.PropertyNode} next + */ + public next: PropertyNode; + /** + * Calculates the correct value for the current interpolation value. This method is set in + * the reset() method. + * @method interpolate + * @param {number} lerp The interpolation value from 0-1. + * @return {number} Either the interpolated value. Colors are converted to the hex value. + */ + public interpolate: SimpleEase; + /** + * A custom easing method for this list. + * @method ease + * @param {number} lerp The interpolation value from 0-1. + * @return {number} The eased value, also from 0-1. + */ + public ease: SimpleEase; + /** + * If this list manages colors, which requires a different method for interpolation. + * @property {boolean} isColor + * @private + */ + private isColor: boolean; + + constructor(isColor: boolean = false) + { + this.current = null; + this.next = null; + this.isColor = !!isColor; + this.interpolate = null; + this.ease = null; + } + + /** + * Resets the list for use. + * @method interpolate + * @param {PIXI.particles.PropertyNode} first The first node in the list. + * @param {boolean} [isStepped=false] If the values should be stepped instead of interpolated linearly. + */ + public reset(first: PropertyNode) + { + this.current = first; + this.next = first.next; + const isSimple = this.next && this.next.time >= 1; + if (isSimple) + { + this.interpolate = this.isColor ? intColorSimple : intValueSimple; + } + else if (first.isStepped) + { + this.interpolate = this.isColor ? intColorStepped : intValueStepped; + } + else + { + this.interpolate = this.isColor ? intColorComplex : intValueComplex; + } + this.ease = this.current.ease; + } +} + +function intValueSimple(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + return (this.next.value - this.current.value) * lerp + this.current.value; +} + +function intColorSimple(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + let curVal = this.current.value, nextVal = this.next.value; + let r = (nextVal.r - curVal.r) * lerp + curVal.r; + let g = (nextVal.g - curVal.g) * lerp + curVal.g; + let b = (nextVal.b - curVal.b) * lerp + curVal.b; + return ParticleUtils.combineRGBComponents(r, g, b); +} + +function intValueComplex(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (lerp > this.next.time) + { + this.current = this.next; + this.next = this.next.next; + } + //convert the lerp value to the segment range + lerp = (lerp - this.current.time) / (this.next.time - this.current.time); + return (this.next.value - this.current.value) * lerp + this.current.value; +} + +function intColorComplex(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (lerp > this.next.time) + { + this.current = this.next; + this.next = this.next.next; + } + //convert the lerp value to the segment range + lerp = (lerp - this.current.time) / (this.next.time - this.current.time); + let curVal = this.current.value, nextVal = this.next.value; + let r = (nextVal.r - curVal.r) * lerp + curVal.r; + let g = (nextVal.g - curVal.g) * lerp + curVal.g; + let b = (nextVal.b - curVal.b) * lerp + curVal.b; + return ParticleUtils.combineRGBComponents(r, g, b); +} + +function intValueStepped(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (this.next && lerp > this.next.time) + { + this.current = this.next; + this.next = this.next.next; + } + return this.current.value; +} + +function intColorStepped(this: PropertyList, lerp: number) +{ + if (this.ease) + lerp = this.ease(lerp); + //make sure we are on the right segment + while (this.next && lerp > this.next.time) + { + this.current = this.next; + this.next = this.next.next; + } + let curVal = this.current.value; + return ParticleUtils.combineRGBComponents(curVal.r, curVal.g, curVal.b); +} \ No newline at end of file diff --git a/src/PropertyNode.ts b/src/PropertyNode.ts new file mode 100644 index 00000000..67b1d9f8 --- /dev/null +++ b/src/PropertyNode.ts @@ -0,0 +1,103 @@ +import ParticleUtils, {EaseSegment, SimpleEase, Color} from "./ParticleUtils"; + +export interface ValueStep { + value:number|string; + time:number; +} + +export interface ValueList { + list: ValueStep[], + isStepped?: boolean; + ease?: SimpleEase|EaseSegment[]; +} +/** + * A single node in a PropertyList. + * @memberof PIXI.particles + * @class PropertyNode + * @constructor + * @param {number|string} value The value for this node + * @param {number} time The time for this node, between 0-1 + * @param {Function|Array} [ease] Custom ease for this list. Only relevant for the first node. + */ +export default class PropertyNode +{ + /** + * Value for the node. + * @property {number|Object} value + */ + public value: V; + /** + * Time value for the node. Between 0-1. + * @property {number} value + */ + public time: number; + /** + * The next node in line. + * @property {PIXI.particles.PropertyNode} next + */ + public next: PropertyNode; + /** + * If this is the first node in the list, controls if the entire list is stepped or not. + * @property {boolean} isStepped + */ + public isStepped: boolean; + public ease: SimpleEase; + + constructor(value: V|string, time:number, ease?: SimpleEase|EaseSegment[]) + { + this.value = typeof value == "string" ? ParticleUtils.hexToRGB(value) as any : value; + this.time = time; + this.next = null; + this.isStepped = false; + if (ease) + { + this.ease = typeof ease == "function" ? ease : ParticleUtils.generateEase(ease); + } + else + { + this.ease = null; + } + } + + /** + * Creates a list of property values from a data object {list, isStepped} with a list of objects in + * the form {value, time}. Alternatively, the data object can be in the deprecated form of + * {start, end}. + * @method PIXI.particles.PropertyNode.createListFromArray + * @static + * @param {Object} data The data for the list. + * @param {Array} data.list The array of value and time objects. + * @param {boolean} [data.isStepped] If the list is stepped rather than interpolated. + * @param {Function|Array} [data.ease] Custom ease for this list. + * @return {PIXI.particles.PropertyNode} The first node in the list + */ + public static createList(data: ValueList) + { + if (Array.isArray(data.list)) + { + let array = data.list; + let node, first; + first = node = new PropertyNode(array[0].value, array[0].time, data.ease); + //only set up subsequent nodes if there are a bunch or the 2nd one is different from the first + if (array.length > 2 || (array.length === 2 && array[1].value !== array[0].value)) + { + for (let i = 1; i < array.length; ++i) + { + node.next = new PropertyNode(array[i].value, array[i].time); + node = node.next; + } + } + first.isStepped = !!data.isStepped; + return first; + } + else + { + //Handle deprecated version here + let start = new PropertyNode((data as any).start, 0); + //only set up a next value if it is different from the starting value + if ((data as any).end !== (data as any).start) + start.next = new PropertyNode((data as any).end, 1); + return start; + } + } +} \ No newline at end of file diff --git a/src/deprecation.js b/src/deprecation.js deleted file mode 100644 index 71d82be9..00000000 --- a/src/deprecation.js +++ /dev/null @@ -1 +0,0 @@ -//Nothing to deprecate right now! \ No newline at end of file diff --git a/src/index.js b/src/index.js deleted file mode 100644 index a488a139..00000000 --- a/src/index.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; - -// Check for window, fallback to global -var global = typeof window !== 'undefined' ? window : GLOBAL; - -//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not -if (!global.PIXI.particles) { - global.PIXI.particles = {}; -} - -// Export for Node-compatible environments like Electron -if (typeof module !== 'undefined' && module.exports) -{ - // Attempt to require the pixi module - if (typeof PIXI === 'undefined') - { - // Include the Pixi.js module - require('pixi.js'); - } - - // Export the module - module.exports = global.PIXI.particles || particles; -} -// If we're in the browser make sure PIXI is available -else if (typeof PIXI === 'undefined') -{ - throw "pixi-particles requires pixi.js to be loaded first"; -} - -// get the library itself -var particles = require('./particles'); - -// insert the lirbary into the particles namespace on PIXI -for (var prop in particles) { - global.PIXI.particles[prop] = particles[prop]; -} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..d90949d2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,20 @@ +"use strict"; + +// If we're in the browser make sure PIXI is available +if (typeof PIXI === 'undefined') +{ + throw "pixi-particles requires pixi.js to be loaded first"; +} + +//ensure that the particles namespace exist - PIXI 4 creates it itself, PIXI 3 does not +if (!PIXI.particles) { + (PIXI as any).particles = {}; +} + +// get the library itself +import * as particles from './particles'; + +// insert the library into the particles namespace on PIXI +for (let prop in particles) { + (PIXI as any).particles[prop] = (particles as any)[prop]; +} \ No newline at end of file diff --git a/src/particles.js b/src/particles.js deleted file mode 100644 index f04a3911..00000000 --- a/src/particles.js +++ /dev/null @@ -1,6 +0,0 @@ -exports.ParticleUtils = require("./ParticleUtils.js"); -exports.Particle = require("./Particle.js"); -exports.Emitter = require("./Emitter.js"); -exports.PathParticle = require("./PathParticle.js"); -exports.AnimatedParticle = require("./AnimatedParticle.js"); -require("./deprecation.js"); \ No newline at end of file diff --git a/src/particles.ts b/src/particles.ts new file mode 100644 index 00000000..cbbedefe --- /dev/null +++ b/src/particles.ts @@ -0,0 +1,5 @@ +export {default as ParticleUtils} from "./ParticleUtils.js"; +export {default as Particle} from "./Particle.js"; +export {default as Emitter} from "./Emitter.js"; +export {default as PathParticle} from "./PathParticle.js"; +export {default as AnimatedParticle} from "./AnimatedParticle.js"; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 8d1432b1..bd27b3b8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,12 @@ { - "files": [ - "./pixi.js.d.ts", - "./index.d.ts", - "./ambient.d.ts" + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "noImplicitAny": true, + "outDir": "ts-dist", + "types": ["pixi.js"] + }, + "include": [ + "src/*.ts" ] } \ No newline at end of file