}
+ */
+ _this._glDatas = {};
+
+ /**
+ * transform that is applied to UV to get the texture coords
+ * its updated independently from texture uvTransform
+ * updates of uvs are tied to that thing
+ *
+ * @member {PIXI.extras.TextureTransform}
+ * @private
+ */
+ _this._uvTransform = new _TextureTransform2.default(texture);
+
+ /**
+ * whether or not upload uvTransform to shader
+ * if its false, then uvs should be pre-multiplied
+ * if you change it for generated mesh, please call 'refresh(true)'
+ * @member {boolean}
+ * @default false
+ */
+ _this.uploadUvTransform = false;
+
+ /**
+ * Plugin that is responsible for rendering this element.
+ * Allows to customize the rendering process without overriding '_renderWebGL' & '_renderCanvas' methods.
+ * @member {string}
+ * @default 'mesh'
+ */
+ _this.pluginName = 'mesh';
+ return _this;
+ }
+
+ /**
+ * Renders the object using the WebGL renderer
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer} renderer - a reference to the WebGL renderer
+ */
+
+
+ Mesh.prototype._renderWebGL = function _renderWebGL(renderer) {
+ this.refresh();
+ renderer.setObjectRenderer(renderer.plugins[this.pluginName]);
+ renderer.plugins[this.pluginName].render(this);
+ };
+
+ /**
+ * Renders the object using the Canvas renderer
+ *
+ * @private
+ * @param {PIXI.CanvasRenderer} renderer - The canvas renderer.
+ */
+
+
+ Mesh.prototype._renderCanvas = function _renderCanvas(renderer) {
+ this.refresh();
+ renderer.plugins[this.pluginName].render(this);
+ };
+
+ /**
+ * When the texture is updated, this event will fire to update the scale and frame
+ *
+ * @private
+ */
+
+
+ Mesh.prototype._onTextureUpdate = function _onTextureUpdate() {
+ this._uvTransform.texture = this._texture;
+ this.refresh();
+ };
+
+ /**
+ * multiplies uvs only if uploadUvTransform is false
+ * call it after you change uvs manually
+ * make sure that texture is valid
+ */
+
+
+ Mesh.prototype.multiplyUvs = function multiplyUvs() {
+ if (!this.uploadUvTransform) {
+ this._uvTransform.multiplyUvs(this.uvs);
+ }
+ };
+
+ /**
+ * Refreshes uvs for generated meshes (rope, plane)
+ * sometimes refreshes vertices too
+ *
+ * @param {boolean} [forceUpdate=false] if true, matrices will be updated any case
+ */
+
+
+ Mesh.prototype.refresh = function refresh(forceUpdate) {
+ if (this._uvTransform.update(forceUpdate)) {
+ this._refresh();
+ }
+ };
+
+ /**
+ * re-calculates mesh coords
+ * @protected
+ */
+
+
+ Mesh.prototype._refresh = function _refresh() {}
+ /* empty */
+
+
+ /**
+ * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account.
+ *
+ */
+ ;
+
+ Mesh.prototype._calculateBounds = function _calculateBounds() {
+ // TODO - we can cache local bounds and use them if they are dirty (like graphics)
+ this._bounds.addVertices(this.transform, this.vertices, 0, this.vertices.length);
+ };
+
+ /**
+ * Tests if a point is inside this mesh. Works only for TRIANGLE_MESH
+ *
+ * @param {PIXI.Point} point - the point to test
+ * @return {boolean} the result of the test
+ */
+
+
+ Mesh.prototype.containsPoint = function containsPoint(point) {
+ if (!this.getBounds().contains(point.x, point.y)) {
+ return false;
+ }
+
+ this.worldTransform.applyInverse(point, tempPoint);
+
+ var vertices = this.vertices;
+ var points = tempPolygon.points;
+ var indices = this.indices;
+ var len = this.indices.length;
+ var step = this.drawMode === Mesh.DRAW_MODES.TRIANGLES ? 3 : 1;
+
+ for (var i = 0; i + 2 < len; i += step) {
+ var ind0 = indices[i] * 2;
+ var ind1 = indices[i + 1] * 2;
+ var ind2 = indices[i + 2] * 2;
+
+ points[0] = vertices[ind0];
+ points[1] = vertices[ind0 + 1];
+ points[2] = vertices[ind1];
+ points[3] = vertices[ind1 + 1];
+ points[4] = vertices[ind2];
+ points[5] = vertices[ind2 + 1];
+
+ if (tempPolygon.contains(tempPoint.x, tempPoint.y)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * The texture that the mesh uses.
+ *
+ * @member {PIXI.Texture}
+ */
+
+
+ _createClass(Mesh, [{
+ key: 'texture',
+ get: function get() {
+ return this._texture;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ if (this._texture === value) {
+ return;
+ }
+
+ this._texture = value;
+
+ if (value) {
+ // wait for the texture to load
+ if (value.baseTexture.hasLoaded) {
+ this._onTextureUpdate();
+ } else {
+ value.once('update', this._onTextureUpdate, this);
+ }
+ }
+ }
+
+ /**
+ * The tint applied to the mesh. This is a hex value. A value of 0xFFFFFF will remove any tint effect.
+ *
+ * @member {number}
+ * @default 0xFFFFFF
+ */
+
+ }, {
+ key: 'tint',
+ get: function get() {
+ return core.utils.rgb2hex(this.tintRgb);
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this.tintRgb = core.utils.hex2rgb(value, this.tintRgb);
+ }
+ }]);
+
+ return Mesh;
+}(core.Container);
+
+/**
+ * Different drawing buffer modes supported
+ *
+ * @static
+ * @constant
+ * @type {object}
+ * @property {number} TRIANGLE_MESH
+ * @property {number} TRIANGLES
+ */
+
+
+exports.default = Mesh;
+Mesh.DRAW_MODES = {
+ TRIANGLE_MESH: 0,
+ TRIANGLES: 1
+};
+
+},{"../core":64,"../extras/TextureTransform":134}],165:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _Plane2 = require('./Plane');
+
+var _Plane3 = _interopRequireDefault(_Plane2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var DEFAULT_BORDER_SIZE = 10;
+
+/**
+ * The NineSlicePlane allows you to stretch a texture using 9-slice scaling. The corners will remain unscaled (useful
+ * for buttons with rounded corners for example) and the other areas will be scaled horizontally and or vertically
+ *
+ *```js
+ * let Plane9 = new PIXI.NineSlicePlane(PIXI.Texture.fromImage('BoxWithRoundedCorners.png'), 15, 15, 15, 15);
+ * ```
+ *
+ * A B
+ * +---+----------------------+---+
+ * C | 1 | 2 | 3 |
+ * +---+----------------------+---+
+ * | | | |
+ * | 4 | 5 | 6 |
+ * | | | |
+ * +---+----------------------+---+
+ * D | 7 | 8 | 9 |
+ * +---+----------------------+---+
+
+ * When changing this objects width and/or height:
+ * areas 1 3 7 and 9 will remain unscaled.
+ * areas 2 and 8 will be stretched horizontally
+ * areas 4 and 6 will be stretched vertically
+ * area 5 will be stretched both horizontally and vertically
+ *
+ *
+ * @class
+ * @extends PIXI.mesh.Plane
+ * @memberof PIXI.mesh
+ *
+ */
+
+var NineSlicePlane = function (_Plane) {
+ _inherits(NineSlicePlane, _Plane);
+
+ /**
+ * @param {PIXI.Texture} texture - The texture to use on the NineSlicePlane.
+ * @param {int} [leftWidth=10] size of the left vertical bar (A)
+ * @param {int} [topHeight=10] size of the top horizontal bar (C)
+ * @param {int} [rightWidth=10] size of the right vertical bar (B)
+ * @param {int} [bottomHeight=10] size of the bottom horizontal bar (D)
+ */
+ function NineSlicePlane(texture, leftWidth, topHeight, rightWidth, bottomHeight) {
+ _classCallCheck(this, NineSlicePlane);
+
+ var _this = _possibleConstructorReturn(this, _Plane.call(this, texture, 4, 4));
+
+ var uvs = _this.uvs;
+
+ // right and bottom uv's are always 1
+ uvs[6] = uvs[14] = uvs[22] = uvs[30] = 1;
+ uvs[25] = uvs[27] = uvs[29] = uvs[31] = 1;
+
+ _this._origWidth = texture.orig.width;
+ _this._origHeight = texture.orig.height;
+ _this._uvw = 1 / _this._origWidth;
+ _this._uvh = 1 / _this._origHeight;
+
+ /**
+ * The width of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.width = _this._origWidth;
+
+ /**
+ * The height of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.height = _this._origHeight;
+
+ uvs[2] = uvs[10] = uvs[18] = uvs[26] = _this._uvw * leftWidth;
+ uvs[4] = uvs[12] = uvs[20] = uvs[28] = 1 - _this._uvw * rightWidth;
+ uvs[9] = uvs[11] = uvs[13] = uvs[15] = _this._uvh * topHeight;
+ uvs[17] = uvs[19] = uvs[21] = uvs[23] = 1 - _this._uvh * bottomHeight;
+
+ /**
+ * The width of the left column (a)
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.leftWidth = typeof leftWidth !== 'undefined' ? leftWidth : DEFAULT_BORDER_SIZE;
+
+ /**
+ * The width of the right column (b)
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.rightWidth = typeof rightWidth !== 'undefined' ? rightWidth : DEFAULT_BORDER_SIZE;
+
+ /**
+ * The height of the top row (c)
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.topHeight = typeof topHeight !== 'undefined' ? topHeight : DEFAULT_BORDER_SIZE;
+
+ /**
+ * The height of the bottom row (d)
+ *
+ * @member {number}
+ * @memberof PIXI.NineSlicePlane#
+ * @override
+ */
+ _this.bottomHeight = typeof bottomHeight !== 'undefined' ? bottomHeight : DEFAULT_BORDER_SIZE;
+
+ _this.refresh(true);
+ return _this;
+ }
+
+ /**
+ * Updates the horizontal vertices.
+ *
+ */
+
+
+ NineSlicePlane.prototype.updateHorizontalVertices = function updateHorizontalVertices() {
+ var vertices = this.vertices;
+
+ vertices[9] = vertices[11] = vertices[13] = vertices[15] = this._topHeight;
+ vertices[17] = vertices[19] = vertices[21] = vertices[23] = this._height - this._bottomHeight;
+ vertices[25] = vertices[27] = vertices[29] = vertices[31] = this._height;
+ };
+
+ /**
+ * Updates the vertical vertices.
+ *
+ */
+
+
+ NineSlicePlane.prototype.updateVerticalVertices = function updateVerticalVertices() {
+ var vertices = this.vertices;
+
+ vertices[2] = vertices[10] = vertices[18] = vertices[26] = this._leftWidth;
+ vertices[4] = vertices[12] = vertices[20] = vertices[28] = this._width - this._rightWidth;
+ vertices[6] = vertices[14] = vertices[22] = vertices[30] = this._width;
+ };
+
+ /**
+ * Renders the object using the Canvas renderer
+ *
+ * @private
+ * @param {PIXI.CanvasRenderer} renderer - The canvas renderer to render with.
+ */
+
+
+ NineSlicePlane.prototype._renderCanvas = function _renderCanvas(renderer) {
+ var context = renderer.context;
+
+ context.globalAlpha = this.worldAlpha;
+
+ var transform = this.worldTransform;
+ var res = renderer.resolution;
+
+ if (renderer.roundPixels) {
+ context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, transform.tx * res | 0, transform.ty * res | 0);
+ } else {
+ context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, transform.tx * res, transform.ty * res);
+ }
+
+ var base = this._texture.baseTexture;
+ var textureSource = base.source;
+ var w = base.width;
+ var h = base.height;
+
+ this.drawSegment(context, textureSource, w, h, 0, 1, 10, 11);
+ this.drawSegment(context, textureSource, w, h, 2, 3, 12, 13);
+ this.drawSegment(context, textureSource, w, h, 4, 5, 14, 15);
+ this.drawSegment(context, textureSource, w, h, 8, 9, 18, 19);
+ this.drawSegment(context, textureSource, w, h, 10, 11, 20, 21);
+ this.drawSegment(context, textureSource, w, h, 12, 13, 22, 23);
+ this.drawSegment(context, textureSource, w, h, 16, 17, 26, 27);
+ this.drawSegment(context, textureSource, w, h, 18, 19, 28, 29);
+ this.drawSegment(context, textureSource, w, h, 20, 21, 30, 31);
+ };
+
+ /**
+ * Renders one segment of the plane.
+ * to mimic the exact drawing behavior of stretching the image like WebGL does, we need to make sure
+ * that the source area is at least 1 pixel in size, otherwise nothing gets drawn when a slice size of 0 is used.
+ *
+ * @private
+ * @param {CanvasRenderingContext2D} context - The context to draw with.
+ * @param {CanvasImageSource} textureSource - The source to draw.
+ * @param {number} w - width of the texture
+ * @param {number} h - height of the texture
+ * @param {number} x1 - x index 1
+ * @param {number} y1 - y index 1
+ * @param {number} x2 - x index 2
+ * @param {number} y2 - y index 2
+ */
+
+
+ NineSlicePlane.prototype.drawSegment = function drawSegment(context, textureSource, w, h, x1, y1, x2, y2) {
+ // otherwise you get weird results when using slices of that are 0 wide or high.
+ var uvs = this.uvs;
+ var vertices = this.vertices;
+
+ var sw = (uvs[x2] - uvs[x1]) * w;
+ var sh = (uvs[y2] - uvs[y1]) * h;
+ var dw = vertices[x2] - vertices[x1];
+ var dh = vertices[y2] - vertices[y1];
+
+ // make sure the source is at least 1 pixel wide and high, otherwise nothing will be drawn.
+ if (sw < 1) {
+ sw = 1;
+ }
+
+ if (sh < 1) {
+ sh = 1;
+ }
+
+ // make sure destination is at least 1 pixel wide and high, otherwise you get
+ // lines when rendering close to original size.
+ if (dw < 1) {
+ dw = 1;
+ }
+
+ if (dh < 1) {
+ dh = 1;
+ }
+
+ context.drawImage(textureSource, uvs[x1] * w, uvs[y1] * h, sw, sh, vertices[x1], vertices[y1], dw, dh);
+ };
+
+ /**
+ * The width of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane
+ *
+ * @member {number}
+ */
+
+
+ _createClass(NineSlicePlane, [{
+ key: 'width',
+ get: function get() {
+ return this._width;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._width = value;
+ this.updateVerticalVertices();
+ }
+
+ /**
+ * The height of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane
+ *
+ * @member {number}
+ */
+
+ }, {
+ key: 'height',
+ get: function get() {
+ return this._height;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._height = value;
+ this.updateHorizontalVertices();
+ }
+
+ /**
+ * The width of the left column
+ *
+ * @member {number}
+ */
+
+ }, {
+ key: 'leftWidth',
+ get: function get() {
+ return this._leftWidth;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._leftWidth = value;
+
+ var uvs = this.uvs;
+ var vertices = this.vertices;
+
+ uvs[2] = uvs[10] = uvs[18] = uvs[26] = this._uvw * value;
+ vertices[2] = vertices[10] = vertices[18] = vertices[26] = value;
+
+ this.dirty = true;
+ }
+
+ /**
+ * The width of the right column
+ *
+ * @member {number}
+ */
+
+ }, {
+ key: 'rightWidth',
+ get: function get() {
+ return this._rightWidth;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._rightWidth = value;
+
+ var uvs = this.uvs;
+ var vertices = this.vertices;
+
+ uvs[4] = uvs[12] = uvs[20] = uvs[28] = 1 - this._uvw * value;
+ vertices[4] = vertices[12] = vertices[20] = vertices[28] = this._width - value;
+
+ this.dirty = true;
+ }
+
+ /**
+ * The height of the top row
+ *
+ * @member {number}
+ */
+
+ }, {
+ key: 'topHeight',
+ get: function get() {
+ return this._topHeight;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._topHeight = value;
+
+ var uvs = this.uvs;
+ var vertices = this.vertices;
+
+ uvs[9] = uvs[11] = uvs[13] = uvs[15] = this._uvh * value;
+ vertices[9] = vertices[11] = vertices[13] = vertices[15] = value;
+
+ this.dirty = true;
+ }
+
+ /**
+ * The height of the bottom row
+ *
+ * @member {number}
+ */
+
+ }, {
+ key: 'bottomHeight',
+ get: function get() {
+ return this._bottomHeight;
+ },
+ set: function set(value) // eslint-disable-line require-jsdoc
+ {
+ this._bottomHeight = value;
+
+ var uvs = this.uvs;
+ var vertices = this.vertices;
+
+ uvs[17] = uvs[19] = uvs[21] = uvs[23] = 1 - this._uvh * value;
+ vertices[17] = vertices[19] = vertices[21] = vertices[23] = this._height - value;
+
+ this.dirty = true;
+ }
+ }]);
+
+ return NineSlicePlane;
+}(_Plane3.default);
+
+exports.default = NineSlicePlane;
+
+},{"./Plane":166}],166:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _Mesh2 = require('./Mesh');
+
+var _Mesh3 = _interopRequireDefault(_Mesh2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * The Plane allows you to draw a texture across several points and them manipulate these points
+ *
+ *```js
+ * for (let i = 0; i < 20; i++) {
+ * points.push(new PIXI.Point(i * 50, 0));
+ * };
+ * let Plane = new PIXI.Plane(PIXI.Texture.fromImage("snake.png"), points);
+ * ```
+ *
+ * @class
+ * @extends PIXI.mesh.Mesh
+ * @memberof PIXI.mesh
+ *
+ */
+var Plane = function (_Mesh) {
+ _inherits(Plane, _Mesh);
+
+ /**
+ * @param {PIXI.Texture} texture - The texture to use on the Plane.
+ * @param {number} verticesX - The number of vertices in the x-axis
+ * @param {number} verticesY - The number of vertices in the y-axis
+ */
+ function Plane(texture, verticesX, verticesY) {
+ _classCallCheck(this, Plane);
+
+ /**
+ * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can
+ * call _onTextureUpdated which could call refresh too early.
+ *
+ * @member {boolean}
+ * @private
+ */
+ var _this = _possibleConstructorReturn(this, _Mesh.call(this, texture));
+
+ _this._ready = true;
+
+ _this.verticesX = verticesX || 10;
+ _this.verticesY = verticesY || 10;
+
+ _this.drawMode = _Mesh3.default.DRAW_MODES.TRIANGLES;
+ _this.refresh();
+ return _this;
+ }
+
+ /**
+ * Refreshes plane coordinates
+ *
+ */
+
+
+ Plane.prototype._refresh = function _refresh() {
+ var texture = this._texture;
+ var total = this.verticesX * this.verticesY;
+ var verts = [];
+ var colors = [];
+ var uvs = [];
+ var indices = [];
+
+ var segmentsX = this.verticesX - 1;
+ var segmentsY = this.verticesY - 1;
+
+ var sizeX = texture.width / segmentsX;
+ var sizeY = texture.height / segmentsY;
+
+ for (var i = 0; i < total; i++) {
+ var x = i % this.verticesX;
+ var y = i / this.verticesX | 0;
+
+ verts.push(x * sizeX, y * sizeY);
+
+ uvs.push(x / segmentsX, y / segmentsY);
+ }
+
+ // cons
+
+ var totalSub = segmentsX * segmentsY;
+
+ for (var _i = 0; _i < totalSub; _i++) {
+ var xpos = _i % segmentsX;
+ var ypos = _i / segmentsX | 0;
+
+ var value = ypos * this.verticesX + xpos;
+ var value2 = ypos * this.verticesX + xpos + 1;
+ var value3 = (ypos + 1) * this.verticesX + xpos;
+ var value4 = (ypos + 1) * this.verticesX + xpos + 1;
+
+ indices.push(value, value2, value3);
+ indices.push(value2, value4, value3);
+ }
+
+ // console.log(indices)
+ this.vertices = new Float32Array(verts);
+ this.uvs = new Float32Array(uvs);
+ this.colors = new Float32Array(colors);
+ this.indices = new Uint16Array(indices);
+ this.indexDirty = true;
+
+ this.multiplyUvs();
+ };
+
+ /**
+ * Clear texture UVs when new texture is set
+ *
+ * @private
+ */
+
+
+ Plane.prototype._onTextureUpdate = function _onTextureUpdate() {
+ _Mesh3.default.prototype._onTextureUpdate.call(this);
+
+ // wait for the Plane ctor to finish before calling refresh
+ if (this._ready) {
+ this.refresh();
+ }
+ };
+
+ return Plane;
+}(_Mesh3.default);
+
+exports.default = Plane;
+
+},{"./Mesh":164}],167:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _Mesh2 = require('./Mesh');
+
+var _Mesh3 = _interopRequireDefault(_Mesh2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * The rope allows you to draw a texture across several points and them manipulate these points
+ *
+ *```js
+ * for (let i = 0; i < 20; i++) {
+ * points.push(new PIXI.Point(i * 50, 0));
+ * };
+ * let rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points);
+ * ```
+ *
+ * @class
+ * @extends PIXI.mesh.Mesh
+ * @memberof PIXI.mesh
+ *
+ */
+var Rope = function (_Mesh) {
+ _inherits(Rope, _Mesh);
+
+ /**
+ * @param {PIXI.Texture} texture - The texture to use on the rope.
+ * @param {PIXI.Point[]} points - An array of {@link PIXI.Point} objects to construct this rope.
+ */
+ function Rope(texture, points) {
+ _classCallCheck(this, Rope);
+
+ /**
+ * An array of points that determine the rope
+ *
+ * @member {PIXI.Point[]}
+ */
+ var _this = _possibleConstructorReturn(this, _Mesh.call(this, texture));
+
+ _this.points = points;
+
+ /**
+ * An array of vertices used to construct this rope.
+ *
+ * @member {Float32Array}
+ */
+ _this.vertices = new Float32Array(points.length * 4);
+
+ /**
+ * The WebGL Uvs of the rope.
+ *
+ * @member {Float32Array}
+ */
+ _this.uvs = new Float32Array(points.length * 4);
+
+ /**
+ * An array containing the color components
+ *
+ * @member {Float32Array}
+ */
+ _this.colors = new Float32Array(points.length * 2);
+
+ /**
+ * An array containing the indices of the vertices
+ *
+ * @member {Uint16Array}
+ */
+ _this.indices = new Uint16Array(points.length * 2);
+
+ /**
+ * refreshes vertices on every updateTransform
+ * @member {boolean}
+ * @default true
+ */
+ _this.autoUpdate = true;
+
+ _this.refresh();
+ return _this;
+ }
+
+ /**
+ * Refreshes
+ *
+ */
+
+
+ Rope.prototype._refresh = function _refresh() {
+ var points = this.points;
+
+ // if too little points, or texture hasn't got UVs set yet just move on.
+ if (points.length < 1 || !this._texture._uvs) {
+ return;
+ }
+
+ // if the number of points has changed we will need to recreate the arraybuffers
+ if (this.vertices.length / 4 !== points.length) {
+ this.vertices = new Float32Array(points.length * 4);
+ this.uvs = new Float32Array(points.length * 4);
+ this.colors = new Float32Array(points.length * 2);
+ this.indices = new Uint16Array(points.length * 2);
+ }
+
+ var uvs = this.uvs;
+
+ var indices = this.indices;
+ var colors = this.colors;
+
+ uvs[0] = 0;
+ uvs[1] = 0;
+ uvs[2] = 0;
+ uvs[3] = 1;
+
+ colors[0] = 1;
+ colors[1] = 1;
+
+ indices[0] = 0;
+ indices[1] = 1;
+
+ var total = points.length;
+
+ for (var i = 1; i < total; i++) {
+ // time to do some smart drawing!
+ var index = i * 4;
+ var amount = i / (total - 1);
+
+ uvs[index] = amount;
+ uvs[index + 1] = 0;
+
+ uvs[index + 2] = amount;
+ uvs[index + 3] = 1;
+
+ index = i * 2;
+ colors[index] = 1;
+ colors[index + 1] = 1;
+
+ index = i * 2;
+ indices[index] = index;
+ indices[index + 1] = index + 1;
+ }
+
+ // ensure that the changes are uploaded
+ this.dirty++;
+ this.indexDirty++;
+
+ this.multiplyUvs();
+ this.refreshVertices();
+ };
+
+ /**
+ * refreshes vertices of Rope mesh
+ */
+
+
+ Rope.prototype.refreshVertices = function refreshVertices() {
+ var points = this.points;
+
+ if (points.length < 1) {
+ return;
+ }
+
+ var lastPoint = points[0];
+ var nextPoint = void 0;
+ var perpX = 0;
+ var perpY = 0;
+
+ // this.count -= 0.2;
+
+ var vertices = this.vertices;
+ var total = points.length;
+
+ for (var i = 0; i < total; i++) {
+ var point = points[i];
+ var index = i * 4;
+
+ if (i < points.length - 1) {
+ nextPoint = points[i + 1];
+ } else {
+ nextPoint = point;
+ }
+
+ perpY = -(nextPoint.x - lastPoint.x);
+ perpX = nextPoint.y - lastPoint.y;
+
+ var ratio = (1 - i / (total - 1)) * 10;
+
+ if (ratio > 1) {
+ ratio = 1;
+ }
+
+ var perpLength = Math.sqrt(perpX * perpX + perpY * perpY);
+ var num = this._texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio;
+
+ perpX /= perpLength;
+ perpY /= perpLength;
+
+ perpX *= num;
+ perpY *= num;
+
+ vertices[index] = point.x + perpX;
+ vertices[index + 1] = point.y + perpY;
+ vertices[index + 2] = point.x - perpX;
+ vertices[index + 3] = point.y - perpY;
+
+ lastPoint = point;
+ }
+ };
+
+ /**
+ * Updates the object transform for rendering
+ *
+ * @private
+ */
+
+
+ Rope.prototype.updateTransform = function updateTransform() {
+ if (this.autoUpdate) {
+ this.refreshVertices();
+ }
+ this.containerUpdateTransform();
+ };
+
+ return Rope;
+}(_Mesh3.default);
+
+exports.default = Rope;
+
+},{"./Mesh":164}],168:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _Mesh = require('../Mesh');
+
+var _Mesh2 = _interopRequireDefault(_Mesh);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Renderer dedicated to meshes.
+ *
+ * @class
+ * @private
+ * @memberof PIXI
+ */
+var MeshSpriteRenderer = function () {
+ /**
+ * @param {PIXI.CanvasRenderer} renderer - The renderer this downport works for
+ */
+ function MeshSpriteRenderer(renderer) {
+ _classCallCheck(this, MeshSpriteRenderer);
+
+ this.renderer = renderer;
+ }
+
+ /**
+ * Renders the Mesh
+ *
+ * @param {PIXI.mesh.Mesh} mesh - the Mesh to render
+ */
+
+
+ MeshSpriteRenderer.prototype.render = function render(mesh) {
+ var renderer = this.renderer;
+ var context = renderer.context;
+
+ var transform = mesh.worldTransform;
+ var res = renderer.resolution;
+
+ if (renderer.roundPixels) {
+ context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, transform.tx * res | 0, transform.ty * res | 0);
+ } else {
+ context.setTransform(transform.a * res, transform.b * res, transform.c * res, transform.d * res, transform.tx * res, transform.ty * res);
+ }
+
+ renderer.setBlendMode(mesh.blendMode);
+
+ if (mesh.drawMode === _Mesh2.default.DRAW_MODES.TRIANGLE_MESH) {
+ this._renderTriangleMesh(mesh);
+ } else {
+ this._renderTriangles(mesh);
+ }
+ };
+
+ /**
+ * Draws the object in Triangle Mesh mode
+ *
+ * @private
+ * @param {PIXI.mesh.Mesh} mesh - the Mesh to render
+ */
+
+
+ MeshSpriteRenderer.prototype._renderTriangleMesh = function _renderTriangleMesh(mesh) {
+ // draw triangles!!
+ var length = mesh.vertices.length / 2;
+
+ for (var i = 0; i < length - 2; i++) {
+ // draw some triangles!
+ var index = i * 2;
+
+ this._renderDrawTriangle(mesh, index, index + 2, index + 4);
+ }
+ };
+
+ /**
+ * Draws the object in triangle mode using canvas
+ *
+ * @private
+ * @param {PIXI.mesh.Mesh} mesh - the current mesh
+ */
+
+
+ MeshSpriteRenderer.prototype._renderTriangles = function _renderTriangles(mesh) {
+ // draw triangles!!
+ var indices = mesh.indices;
+ var length = indices.length;
+
+ for (var i = 0; i < length; i += 3) {
+ // draw some triangles!
+ var index0 = indices[i] * 2;
+ var index1 = indices[i + 1] * 2;
+ var index2 = indices[i + 2] * 2;
+
+ this._renderDrawTriangle(mesh, index0, index1, index2);
+ }
+ };
+
+ /**
+ * Draws one of the triangles that from the Mesh
+ *
+ * @private
+ * @param {PIXI.mesh.Mesh} mesh - the current mesh
+ * @param {number} index0 - the index of the first vertex
+ * @param {number} index1 - the index of the second vertex
+ * @param {number} index2 - the index of the third vertex
+ */
+
+
+ MeshSpriteRenderer.prototype._renderDrawTriangle = function _renderDrawTriangle(mesh, index0, index1, index2) {
+ var context = this.renderer.context;
+ var uvs = mesh.uvs;
+ var vertices = mesh.vertices;
+ var texture = mesh._texture;
+
+ if (!texture.valid) {
+ return;
+ }
+
+ var base = texture.baseTexture;
+ var textureSource = base.source;
+ var textureWidth = base.width;
+ var textureHeight = base.height;
+
+ var u0 = void 0;
+ var u1 = void 0;
+ var u2 = void 0;
+ var v0 = void 0;
+ var v1 = void 0;
+ var v2 = void 0;
+
+ if (mesh.uploadUvTransform) {
+ var ut = mesh._uvTransform.mapCoord;
+
+ u0 = (uvs[index0] * ut.a + uvs[index0 + 1] * ut.c + ut.tx) * base.width;
+ u1 = (uvs[index1] * ut.a + uvs[index1 + 1] * ut.c + ut.tx) * base.width;
+ u2 = (uvs[index2] * ut.a + uvs[index2 + 1] * ut.c + ut.tx) * base.width;
+ v0 = (uvs[index0] * ut.b + uvs[index0 + 1] * ut.d + ut.ty) * base.height;
+ v1 = (uvs[index1] * ut.b + uvs[index1 + 1] * ut.d + ut.ty) * base.height;
+ v2 = (uvs[index2] * ut.b + uvs[index2 + 1] * ut.d + ut.ty) * base.height;
+ } else {
+ u0 = uvs[index0] * base.width;
+ u1 = uvs[index1] * base.width;
+ u2 = uvs[index2] * base.width;
+ v0 = uvs[index0 + 1] * base.height;
+ v1 = uvs[index1 + 1] * base.height;
+ v2 = uvs[index2 + 1] * base.height;
+ }
+
+ var x0 = vertices[index0];
+ var x1 = vertices[index1];
+ var x2 = vertices[index2];
+ var y0 = vertices[index0 + 1];
+ var y1 = vertices[index1 + 1];
+ var y2 = vertices[index2 + 1];
+
+ if (mesh.canvasPadding > 0) {
+ var paddingX = mesh.canvasPadding / mesh.worldTransform.a;
+ var paddingY = mesh.canvasPadding / mesh.worldTransform.d;
+ var centerX = (x0 + x1 + x2) / 3;
+ var centerY = (y0 + y1 + y2) / 3;
+
+ var normX = x0 - centerX;
+ var normY = y0 - centerY;
+
+ var dist = Math.sqrt(normX * normX + normY * normY);
+
+ x0 = centerX + normX / dist * (dist + paddingX);
+ y0 = centerY + normY / dist * (dist + paddingY);
+
+ //
+
+ normX = x1 - centerX;
+ normY = y1 - centerY;
+
+ dist = Math.sqrt(normX * normX + normY * normY);
+ x1 = centerX + normX / dist * (dist + paddingX);
+ y1 = centerY + normY / dist * (dist + paddingY);
+
+ normX = x2 - centerX;
+ normY = y2 - centerY;
+
+ dist = Math.sqrt(normX * normX + normY * normY);
+ x2 = centerX + normX / dist * (dist + paddingX);
+ y2 = centerY + normY / dist * (dist + paddingY);
+ }
+
+ context.save();
+ context.beginPath();
+
+ context.moveTo(x0, y0);
+ context.lineTo(x1, y1);
+ context.lineTo(x2, y2);
+
+ context.closePath();
+
+ context.clip();
+
+ // Compute matrix transform
+ var delta = u0 * v1 + v0 * u2 + u1 * v2 - v1 * u2 - v0 * u1 - u0 * v2;
+ var deltaA = x0 * v1 + v0 * x2 + x1 * v2 - v1 * x2 - v0 * x1 - x0 * v2;
+ var deltaB = u0 * x1 + x0 * u2 + u1 * x2 - x1 * u2 - x0 * u1 - u0 * x2;
+ var deltaC = u0 * v1 * x2 + v0 * x1 * u2 + x0 * u1 * v2 - x0 * v1 * u2 - v0 * u1 * x2 - u0 * x1 * v2;
+ var deltaD = y0 * v1 + v0 * y2 + y1 * v2 - v1 * y2 - v0 * y1 - y0 * v2;
+ var deltaE = u0 * y1 + y0 * u2 + u1 * y2 - y1 * u2 - y0 * u1 - u0 * y2;
+ var deltaF = u0 * v1 * y2 + v0 * y1 * u2 + y0 * u1 * v2 - y0 * v1 * u2 - v0 * u1 * y2 - u0 * y1 * v2;
+
+ context.transform(deltaA / delta, deltaD / delta, deltaB / delta, deltaE / delta, deltaC / delta, deltaF / delta);
+
+ context.drawImage(textureSource, 0, 0, textureWidth * base.resolution, textureHeight * base.resolution, 0, 0, textureWidth, textureHeight);
+
+ context.restore();
+ };
+
+ /**
+ * Renders a flat Mesh
+ *
+ * @private
+ * @param {PIXI.mesh.Mesh} mesh - The Mesh to render
+ */
+
+
+ MeshSpriteRenderer.prototype.renderMeshFlat = function renderMeshFlat(mesh) {
+ var context = this.renderer.context;
+ var vertices = mesh.vertices;
+ var length = vertices.length / 2;
+
+ // this.count++;
+
+ context.beginPath();
+
+ for (var i = 1; i < length - 2; ++i) {
+ // draw some triangles!
+ var index = i * 2;
+
+ var x0 = vertices[index];
+ var y0 = vertices[index + 1];
+
+ var x1 = vertices[index + 2];
+ var y1 = vertices[index + 3];
+
+ var x2 = vertices[index + 4];
+ var y2 = vertices[index + 5];
+
+ context.moveTo(x0, y0);
+ context.lineTo(x1, y1);
+ context.lineTo(x2, y2);
+ }
+
+ context.fillStyle = '#FF0000';
+ context.fill();
+ context.closePath();
+ };
+
+ /**
+ * destroy the the renderer.
+ *
+ */
+
+
+ MeshSpriteRenderer.prototype.destroy = function destroy() {
+ this.renderer = null;
+ };
+
+ return MeshSpriteRenderer;
+}();
+
+exports.default = MeshSpriteRenderer;
+
+
+core.CanvasRenderer.registerPlugin('mesh', MeshSpriteRenderer);
+
+},{"../../core":64,"../Mesh":164}],169:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _Mesh = require('./Mesh');
+
+Object.defineProperty(exports, 'Mesh', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_Mesh).default;
+ }
+});
+
+var _MeshRenderer = require('./webgl/MeshRenderer');
+
+Object.defineProperty(exports, 'MeshRenderer', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_MeshRenderer).default;
+ }
+});
+
+var _CanvasMeshRenderer = require('./canvas/CanvasMeshRenderer');
+
+Object.defineProperty(exports, 'CanvasMeshRenderer', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_CanvasMeshRenderer).default;
+ }
+});
+
+var _Plane = require('./Plane');
+
+Object.defineProperty(exports, 'Plane', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_Plane).default;
+ }
+});
+
+var _NineSlicePlane = require('./NineSlicePlane');
+
+Object.defineProperty(exports, 'NineSlicePlane', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_NineSlicePlane).default;
+ }
+});
+
+var _Rope = require('./Rope');
+
+Object.defineProperty(exports, 'Rope', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_Rope).default;
+ }
+});
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+},{"./Mesh":164,"./NineSlicePlane":165,"./Plane":166,"./Rope":167,"./canvas/CanvasMeshRenderer":168,"./webgl/MeshRenderer":170}],170:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _pixiGlCore = require('pixi-gl-core');
+
+var _pixiGlCore2 = _interopRequireDefault(_pixiGlCore);
+
+var _Mesh = require('../Mesh');
+
+var _Mesh2 = _interopRequireDefault(_Mesh);
+
+var _path = require('path');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var matrixIdentity = core.Matrix.IDENTITY;
+
+/**
+ * WebGL renderer plugin for tiling sprites
+ *
+ * @class
+ * @memberof PIXI
+ * @extends PIXI.ObjectRenderer
+ */
+
+var MeshRenderer = function (_core$ObjectRenderer) {
+ _inherits(MeshRenderer, _core$ObjectRenderer);
+
+ /**
+ * constructor for renderer
+ *
+ * @param {WebGLRenderer} renderer The renderer this tiling awesomeness works for.
+ */
+ function MeshRenderer(renderer) {
+ _classCallCheck(this, MeshRenderer);
+
+ var _this = _possibleConstructorReturn(this, _core$ObjectRenderer.call(this, renderer));
+
+ _this.shader = null;
+ return _this;
+ }
+
+ /**
+ * Sets up the renderer context and necessary buffers.
+ *
+ * @private
+ */
+
+
+ MeshRenderer.prototype.onContextChange = function onContextChange() {
+ var gl = this.renderer.gl;
+
+ this.shader = new core.Shader(gl, 'attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nuniform mat3 translationMatrix;\nuniform mat3 uTransform;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\n}\n', 'varying vec2 vTextureCoord;\nuniform float alpha;\nuniform vec3 tint;\n\nuniform sampler2D uSampler;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord) * vec4(tint * alpha, alpha);\n}\n');
+ };
+
+ /**
+ * renders mesh
+ *
+ * @param {PIXI.mesh.Mesh} mesh mesh instance
+ */
+
+
+ MeshRenderer.prototype.render = function render(mesh) {
+ var renderer = this.renderer;
+ var gl = renderer.gl;
+ var texture = mesh._texture;
+
+ if (!texture.valid) {
+ return;
+ }
+
+ var glData = mesh._glDatas[renderer.CONTEXT_UID];
+
+ if (!glData) {
+ renderer.bindVao(null);
+
+ glData = {
+ shader: this.shader,
+ vertexBuffer: _pixiGlCore2.default.GLBuffer.createVertexBuffer(gl, mesh.vertices, gl.STREAM_DRAW),
+ uvBuffer: _pixiGlCore2.default.GLBuffer.createVertexBuffer(gl, mesh.uvs, gl.STREAM_DRAW),
+ indexBuffer: _pixiGlCore2.default.GLBuffer.createIndexBuffer(gl, mesh.indices, gl.STATIC_DRAW),
+ // build the vao object that will render..
+ vao: null,
+ dirty: mesh.dirty,
+ indexDirty: mesh.indexDirty
+ };
+
+ // build the vao object that will render..
+ glData.vao = new _pixiGlCore2.default.VertexArrayObject(gl).addIndex(glData.indexBuffer).addAttribute(glData.vertexBuffer, glData.shader.attributes.aVertexPosition, gl.FLOAT, false, 2 * 4, 0).addAttribute(glData.uvBuffer, glData.shader.attributes.aTextureCoord, gl.FLOAT, false, 2 * 4, 0);
+
+ mesh._glDatas[renderer.CONTEXT_UID] = glData;
+ }
+
+ renderer.bindVao(glData.vao);
+
+ if (mesh.dirty !== glData.dirty) {
+ glData.dirty = mesh.dirty;
+ glData.uvBuffer.upload(mesh.uvs);
+ }
+
+ if (mesh.indexDirty !== glData.indexDirty) {
+ glData.indexDirty = mesh.indexDirty;
+ glData.indexBuffer.upload(mesh.indices);
+ }
+
+ glData.vertexBuffer.upload(mesh.vertices);
+
+ renderer.bindShader(glData.shader);
+
+ glData.shader.uniforms.uSampler = renderer.bindTexture(texture);
+
+ renderer.state.setBlendMode(mesh.blendMode);
+
+ if (glData.shader.uniforms.uTransform) {
+ if (mesh.uploadUvTransform) {
+ glData.shader.uniforms.uTransform = mesh._uvTransform.mapCoord.toArray(true);
+ } else {
+ glData.shader.uniforms.uTransform = matrixIdentity.toArray(true);
+ }
+ }
+ glData.shader.uniforms.translationMatrix = mesh.worldTransform.toArray(true);
+ glData.shader.uniforms.alpha = mesh.worldAlpha;
+ glData.shader.uniforms.tint = mesh.tintRgb;
+
+ var drawMode = mesh.drawMode === _Mesh2.default.DRAW_MODES.TRIANGLE_MESH ? gl.TRIANGLE_STRIP : gl.TRIANGLES;
+
+ glData.vao.draw(drawMode, mesh.indices.length, 0);
+ };
+
+ return MeshRenderer;
+}(core.ObjectRenderer);
+
+exports.default = MeshRenderer;
+
+
+core.WebGLRenderer.registerPlugin('mesh', MeshRenderer);
+
+},{"../../core":64,"../Mesh":164,"path":23,"pixi-gl-core":12}],171:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../core');
+
+var core = _interopRequireWildcard(_core);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * The ParticleContainer class is a really fast version of the Container built solely for speed,
+ * so use when you need a lot of sprites or particles. The tradeoff of the ParticleContainer is that advanced
+ * functionality will not work. ParticleContainer implements only the basic object transform (position, scale, rotation).
+ * Any other functionality like tinting, masking, etc will not work on sprites in this batch.
+ *
+ * It's extremely easy to use :
+ *
+ * ```js
+ * let container = new ParticleContainer();
+ *
+ * for (let i = 0; i < 100; ++i)
+ * {
+ * let sprite = new PIXI.Sprite.fromImage("myImage.png");
+ * container.addChild(sprite);
+ * }
+ * ```
+ *
+ * And here you have a hundred sprites that will be renderer at the speed of light.
+ *
+ * @class
+ * @extends PIXI.Container
+ * @memberof PIXI.particles
+ */
+var ParticleContainer = function (_core$Container) {
+ _inherits(ParticleContainer, _core$Container);
+
+ /**
+ * @param {number} [maxSize=15000] - The maximum number of particles that can be renderer by the container.
+ * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied.
+ * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied.
+ * @param {boolean} [properties.position=true] - When true, position be uploaded and applied.
+ * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied.
+ * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied.
+ * @param {boolean} [properties.alpha=false] - When true, alpha be uploaded and applied.
+ * @param {number} [batchSize=15000] - Number of particles per batch.
+ */
+ function ParticleContainer() {
+ var maxSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1500;
+ var properties = arguments[1];
+ var batchSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 16384;
+
+ _classCallCheck(this, ParticleContainer);
+
+ // Making sure the batch size is valid
+ // 65535 is max vertex index in the index buffer (see ParticleRenderer)
+ // so max number of particles is 65536 / 4 = 16384
+ var _this = _possibleConstructorReturn(this, _core$Container.call(this));
+
+ var maxBatchSize = 16384;
+
+ if (batchSize > maxBatchSize) {
+ batchSize = maxBatchSize;
+ }
+
+ if (batchSize > maxSize) {
+ batchSize = maxSize;
+ }
+
+ /**
+ * Set properties to be dynamic (true) / static (false)
+ *
+ * @member {boolean[]}
+ * @private
+ */
+ _this._properties = [false, true, false, false, false];
+
+ /**
+ * @member {number}
+ * @private
+ */
+ _this._maxSize = maxSize;
+
+ /**
+ * @member {number}
+ * @private
+ */
+ _this._batchSize = batchSize;
+
+ /**
+ * @member {object}
+ * @private
+ */
+ _this._glBuffers = {};
+
+ /**
+ * @member {number}
+ * @private
+ */
+ _this._bufferToUpdate = 0;
+
+ /**
+ * @member {boolean}
+ *
+ */
+ _this.interactiveChildren = false;
+
+ /**
+ * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL`
+ * to reset the blend mode.
+ *
+ * @member {number}
+ * @default PIXI.BLEND_MODES.NORMAL
+ * @see PIXI.BLEND_MODES
+ */
+ _this.blendMode = core.BLEND_MODES.NORMAL;
+
+ /**
+ * Used for canvas renderering. If true then the elements will be positioned at the
+ * nearest pixel. This provides a nice speed boost.
+ *
+ * @member {boolean}
+ * @default true;
+ */
+ _this.roundPixels = true;
+
+ /**
+ * The texture used to render the children.
+ *
+ * @readonly
+ * @member {BaseTexture}
+ */
+ _this.baseTexture = null;
+
+ _this.setProperties(properties);
+ return _this;
+ }
+
+ /**
+ * Sets the private properties array to dynamic / static based on the passed properties object
+ *
+ * @param {object} properties - The properties to be uploaded
+ */
+
+
+ ParticleContainer.prototype.setProperties = function setProperties(properties) {
+ if (properties) {
+ this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0];
+ this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1];
+ this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2];
+ this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3];
+ this._properties[4] = 'alpha' in properties ? !!properties.alpha : this._properties[4];
+ }
+ };
+
+ /**
+ * Updates the object transform for rendering
+ *
+ * @private
+ */
+
+
+ ParticleContainer.prototype.updateTransform = function updateTransform() {
+ // TODO don't need to!
+ this.displayObjectUpdateTransform();
+ // PIXI.Container.prototype.updateTransform.call( this );
+ };
+
+ /**
+ * Renders the container using the WebGL renderer
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer} renderer - The webgl renderer
+ */
+
+
+ ParticleContainer.prototype.renderWebGL = function renderWebGL(renderer) {
+ var _this2 = this;
+
+ if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) {
+ return;
+ }
+
+ if (!this.baseTexture) {
+ this.baseTexture = this.children[0]._texture.baseTexture;
+ if (!this.baseTexture.hasLoaded) {
+ this.baseTexture.once('update', function () {
+ return _this2.onChildrenChange(0);
+ });
+ }
+ }
+
+ renderer.setObjectRenderer(renderer.plugins.particle);
+ renderer.plugins.particle.render(this);
+ };
+
+ /**
+ * Set the flag that static data should be updated to true
+ *
+ * @private
+ * @param {number} smallestChildIndex - The smallest child index
+ */
+
+
+ ParticleContainer.prototype.onChildrenChange = function onChildrenChange(smallestChildIndex) {
+ var bufferIndex = Math.floor(smallestChildIndex / this._batchSize);
+
+ if (bufferIndex < this._bufferToUpdate) {
+ this._bufferToUpdate = bufferIndex;
+ }
+ };
+
+ /**
+ * Renders the object using the Canvas renderer
+ *
+ * @private
+ * @param {PIXI.CanvasRenderer} renderer - The canvas renderer
+ */
+
+
+ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer) {
+ if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) {
+ return;
+ }
+
+ var context = renderer.context;
+ var transform = this.worldTransform;
+ var isRotated = true;
+
+ var positionX = 0;
+ var positionY = 0;
+
+ var finalWidth = 0;
+ var finalHeight = 0;
+
+ var compositeOperation = renderer.blendModes[this.blendMode];
+
+ if (compositeOperation !== context.globalCompositeOperation) {
+ context.globalCompositeOperation = compositeOperation;
+ }
+
+ context.globalAlpha = this.worldAlpha;
+
+ this.displayObjectUpdateTransform();
+
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+
+ if (!child.visible) {
+ continue;
+ }
+
+ var frame = child._texture.frame;
+
+ context.globalAlpha = this.worldAlpha * child.alpha;
+
+ if (child.rotation % (Math.PI * 2) === 0) {
+ // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call
+ if (isRotated) {
+ context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx * renderer.resolution, transform.ty * renderer.resolution);
+
+ isRotated = false;
+ }
+
+ positionX = child.anchor.x * (-frame.width * child.scale.x) + child.position.x + 0.5;
+ positionY = child.anchor.y * (-frame.height * child.scale.y) + child.position.y + 0.5;
+
+ finalWidth = frame.width * child.scale.x;
+ finalHeight = frame.height * child.scale.y;
+ } else {
+ if (!isRotated) {
+ isRotated = true;
+ }
+
+ child.displayObjectUpdateTransform();
+
+ var childTransform = child.worldTransform;
+
+ if (renderer.roundPixels) {
+ context.setTransform(childTransform.a, childTransform.b, childTransform.c, childTransform.d, childTransform.tx * renderer.resolution | 0, childTransform.ty * renderer.resolution | 0);
+ } else {
+ context.setTransform(childTransform.a, childTransform.b, childTransform.c, childTransform.d, childTransform.tx * renderer.resolution, childTransform.ty * renderer.resolution);
+ }
+
+ positionX = child.anchor.x * -frame.width + 0.5;
+ positionY = child.anchor.y * -frame.height + 0.5;
+
+ finalWidth = frame.width;
+ finalHeight = frame.height;
+ }
+
+ var resolution = child._texture.baseTexture.resolution;
+
+ context.drawImage(child._texture.baseTexture.source, frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution, positionX * renderer.resolution, positionY * renderer.resolution, finalWidth * renderer.resolution, finalHeight * renderer.resolution);
+ }
+ };
+
+ /**
+ * Destroys the container
+ *
+ * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options
+ * have been set to that value
+ * @param {boolean} [options.children=false] - if set to true, all the children will have their
+ * destroy method called as well. 'options' will be passed on to those calls.
+ * @param {boolean} [options.texture=false] - Only used for child Sprites if options.children is set to true
+ * Should it destroy the texture of the child sprite
+ * @param {boolean} [options.baseTexture=false] - Only used for child Sprites if options.children is set to true
+ * Should it destroy the base texture of the child sprite
+ */
+
+
+ ParticleContainer.prototype.destroy = function destroy(options) {
+ _core$Container.prototype.destroy.call(this, options);
+
+ if (this._buffers) {
+ for (var i = 0; i < this._buffers.length; ++i) {
+ this._buffers[i].destroy();
+ }
+ }
+
+ this._properties = null;
+ this._buffers = null;
+ };
+
+ return ParticleContainer;
+}(core.Container);
+
+exports.default = ParticleContainer;
+
+},{"../core":64}],172:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _ParticleContainer = require('./ParticleContainer');
+
+Object.defineProperty(exports, 'ParticleContainer', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_ParticleContainer).default;
+ }
+});
+
+var _ParticleRenderer = require('./webgl/ParticleRenderer');
+
+Object.defineProperty(exports, 'ParticleRenderer', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_ParticleRenderer).default;
+ }
+});
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+},{"./ParticleContainer":171,"./webgl/ParticleRenderer":174}],173:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _pixiGlCore = require('pixi-gl-core');
+
+var _pixiGlCore2 = _interopRequireDefault(_pixiGlCore);
+
+var _createIndicesForQuads = require('../../core/utils/createIndicesForQuads');
+
+var _createIndicesForQuads2 = _interopRequireDefault(_createIndicesForQuads);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * @author Mat Groves
+ *
+ * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/
+ * for creating the original pixi version!
+ * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that
+ * they now share 4 bytes on the vertex buffer
+ *
+ * Heavily inspired by LibGDX's ParticleBuffer:
+ * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java
+ */
+
+/**
+ * The particle buffer manages the static and dynamic buffers for a particle container.
+ *
+ * @class
+ * @private
+ * @memberof PIXI
+ */
+var ParticleBuffer = function () {
+ /**
+ * @param {WebGLRenderingContext} gl - The rendering context.
+ * @param {object} properties - The properties to upload.
+ * @param {boolean[]} dynamicPropertyFlags - Flags for which properties are dynamic.
+ * @param {number} size - The size of the batch.
+ */
+ function ParticleBuffer(gl, properties, dynamicPropertyFlags, size) {
+ _classCallCheck(this, ParticleBuffer);
+
+ /**
+ * The current WebGL drawing context.
+ *
+ * @member {WebGLRenderingContext}
+ */
+ this.gl = gl;
+
+ /**
+ * Size of a single vertex.
+ *
+ * @member {number}
+ */
+ this.vertSize = 2;
+
+ /**
+ * Size of a single vertex in bytes.
+ *
+ * @member {number}
+ */
+ this.vertByteSize = this.vertSize * 4;
+
+ /**
+ * The number of particles the buffer can hold
+ *
+ * @member {number}
+ */
+ this.size = size;
+
+ /**
+ * A list of the properties that are dynamic.
+ *
+ * @member {object[]}
+ */
+ this.dynamicProperties = [];
+
+ /**
+ * A list of the properties that are static.
+ *
+ * @member {object[]}
+ */
+ this.staticProperties = [];
+
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i];
+
+ // Make copy of properties object so that when we edit the offset it doesn't
+ // change all other instances of the object literal
+ property = {
+ attribute: property.attribute,
+ size: property.size,
+ uploadFunction: property.uploadFunction,
+ offset: property.offset
+ };
+
+ if (dynamicPropertyFlags[i]) {
+ this.dynamicProperties.push(property);
+ } else {
+ this.staticProperties.push(property);
+ }
+ }
+
+ this.staticStride = 0;
+ this.staticBuffer = null;
+ this.staticData = null;
+
+ this.dynamicStride = 0;
+ this.dynamicBuffer = null;
+ this.dynamicData = null;
+
+ this.initBuffers();
+ }
+
+ /**
+ * Sets up the renderer context and necessary buffers.
+ *
+ * @private
+ */
+
+
+ ParticleBuffer.prototype.initBuffers = function initBuffers() {
+ var gl = this.gl;
+ var dynamicOffset = 0;
+
+ /**
+ * Holds the indices of the geometry (quads) to draw
+ *
+ * @member {Uint16Array}
+ */
+ this.indices = (0, _createIndicesForQuads2.default)(this.size);
+ this.indexBuffer = _pixiGlCore2.default.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW);
+
+ this.dynamicStride = 0;
+
+ for (var i = 0; i < this.dynamicProperties.length; ++i) {
+ var property = this.dynamicProperties[i];
+
+ property.offset = dynamicOffset;
+ dynamicOffset += property.size;
+ this.dynamicStride += property.size;
+ }
+
+ this.dynamicData = new Float32Array(this.size * this.dynamicStride * 4);
+ this.dynamicBuffer = _pixiGlCore2.default.GLBuffer.createVertexBuffer(gl, this.dynamicData, gl.STREAM_DRAW);
+
+ // static //
+ var staticOffset = 0;
+
+ this.staticStride = 0;
+
+ for (var _i = 0; _i < this.staticProperties.length; ++_i) {
+ var _property = this.staticProperties[_i];
+
+ _property.offset = staticOffset;
+ staticOffset += _property.size;
+ this.staticStride += _property.size;
+ }
+
+ this.staticData = new Float32Array(this.size * this.staticStride * 4);
+ this.staticBuffer = _pixiGlCore2.default.GLBuffer.createVertexBuffer(gl, this.staticData, gl.STATIC_DRAW);
+
+ this.vao = new _pixiGlCore2.default.VertexArrayObject(gl).addIndex(this.indexBuffer);
+
+ for (var _i2 = 0; _i2 < this.dynamicProperties.length; ++_i2) {
+ var _property2 = this.dynamicProperties[_i2];
+
+ this.vao.addAttribute(this.dynamicBuffer, _property2.attribute, gl.FLOAT, false, this.dynamicStride * 4, _property2.offset * 4);
+ }
+
+ for (var _i3 = 0; _i3 < this.staticProperties.length; ++_i3) {
+ var _property3 = this.staticProperties[_i3];
+
+ this.vao.addAttribute(this.staticBuffer, _property3.attribute, gl.FLOAT, false, this.staticStride * 4, _property3.offset * 4);
+ }
+ };
+
+ /**
+ * Uploads the dynamic properties.
+ *
+ * @param {PIXI.DisplayObject[]} children - The children to upload.
+ * @param {number} startIndex - The index to start at.
+ * @param {number} amount - The number to upload.
+ */
+
+
+ ParticleBuffer.prototype.uploadDynamic = function uploadDynamic(children, startIndex, amount) {
+ for (var i = 0; i < this.dynamicProperties.length; i++) {
+ var property = this.dynamicProperties[i];
+
+ property.uploadFunction(children, startIndex, amount, this.dynamicData, this.dynamicStride, property.offset);
+ }
+
+ this.dynamicBuffer.upload();
+ };
+
+ /**
+ * Uploads the static properties.
+ *
+ * @param {PIXI.DisplayObject[]} children - The children to upload.
+ * @param {number} startIndex - The index to start at.
+ * @param {number} amount - The number to upload.
+ */
+
+
+ ParticleBuffer.prototype.uploadStatic = function uploadStatic(children, startIndex, amount) {
+ for (var i = 0; i < this.staticProperties.length; i++) {
+ var property = this.staticProperties[i];
+
+ property.uploadFunction(children, startIndex, amount, this.staticData, this.staticStride, property.offset);
+ }
+
+ this.staticBuffer.upload();
+ };
+
+ /**
+ * Destroys the ParticleBuffer.
+ *
+ */
+
+
+ ParticleBuffer.prototype.destroy = function destroy() {
+ this.dynamicProperties = null;
+ this.dynamicData = null;
+ this.dynamicBuffer.destroy();
+
+ this.staticProperties = null;
+ this.staticData = null;
+ this.staticBuffer.destroy();
+ };
+
+ return ParticleBuffer;
+}();
+
+exports.default = ParticleBuffer;
+
+},{"../../core/utils/createIndicesForQuads":121,"pixi-gl-core":12}],174:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _ParticleShader = require('./ParticleShader');
+
+var _ParticleShader2 = _interopRequireDefault(_ParticleShader);
+
+var _ParticleBuffer = require('./ParticleBuffer');
+
+var _ParticleBuffer2 = _interopRequireDefault(_ParticleBuffer);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * @author Mat Groves
+ *
+ * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/
+ * for creating the original pixi version!
+ * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now
+ * share 4 bytes on the vertex buffer
+ *
+ * Heavily inspired by LibGDX's ParticleRenderer:
+ * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleRenderer.java
+ */
+
+/**
+ *
+ * @class
+ * @private
+ * @memberof PIXI
+ */
+var ParticleRenderer = function (_core$ObjectRenderer) {
+ _inherits(ParticleRenderer, _core$ObjectRenderer);
+
+ /**
+ * @param {PIXI.WebGLRenderer} renderer - The renderer this sprite batch works for.
+ */
+ function ParticleRenderer(renderer) {
+ _classCallCheck(this, ParticleRenderer);
+
+ // 65535 is max vertex index in the index buffer (see ParticleRenderer)
+ // so max number of particles is 65536 / 4 = 16384
+ // and max number of element in the index buffer is 16384 * 6 = 98304
+ // Creating a full index buffer, overhead is 98304 * 2 = 196Ko
+ // let numIndices = 98304;
+
+ /**
+ * The default shader that is used if a sprite doesn't have a more specific one.
+ *
+ * @member {PIXI.Shader}
+ */
+ var _this = _possibleConstructorReturn(this, _core$ObjectRenderer.call(this, renderer));
+
+ _this.shader = null;
+
+ _this.indexBuffer = null;
+
+ _this.properties = null;
+
+ _this.tempMatrix = new core.Matrix();
+
+ _this.CONTEXT_UID = 0;
+ return _this;
+ }
+
+ /**
+ * When there is a WebGL context change
+ *
+ * @private
+ */
+
+
+ ParticleRenderer.prototype.onContextChange = function onContextChange() {
+ var gl = this.renderer.gl;
+
+ this.CONTEXT_UID = this.renderer.CONTEXT_UID;
+
+ // setup default shader
+ this.shader = new _ParticleShader2.default(gl);
+
+ this.properties = [
+ // verticesData
+ {
+ attribute: this.shader.attributes.aVertexPosition,
+ size: 2,
+ uploadFunction: this.uploadVertices,
+ offset: 0
+ },
+ // positionData
+ {
+ attribute: this.shader.attributes.aPositionCoord,
+ size: 2,
+ uploadFunction: this.uploadPosition,
+ offset: 0
+ },
+ // rotationData
+ {
+ attribute: this.shader.attributes.aRotation,
+ size: 1,
+ uploadFunction: this.uploadRotation,
+ offset: 0
+ },
+ // uvsData
+ {
+ attribute: this.shader.attributes.aTextureCoord,
+ size: 2,
+ uploadFunction: this.uploadUvs,
+ offset: 0
+ },
+ // alphaData
+ {
+ attribute: this.shader.attributes.aColor,
+ size: 1,
+ uploadFunction: this.uploadAlpha,
+ offset: 0
+ }];
+ };
+
+ /**
+ * Starts a new particle batch.
+ *
+ */
+
+
+ ParticleRenderer.prototype.start = function start() {
+ this.renderer.bindShader(this.shader);
+ };
+
+ /**
+ * Renders the particle container object.
+ *
+ * @param {PIXI.ParticleContainer} container - The container to render using this ParticleRenderer
+ */
+
+
+ ParticleRenderer.prototype.render = function render(container) {
+ var children = container.children;
+ var maxSize = container._maxSize;
+ var batchSize = container._batchSize;
+ var renderer = this.renderer;
+ var totalChildren = children.length;
+
+ if (totalChildren === 0) {
+ return;
+ } else if (totalChildren > maxSize) {
+ totalChildren = maxSize;
+ }
+
+ var buffers = container._glBuffers[renderer.CONTEXT_UID];
+
+ if (!buffers) {
+ buffers = container._glBuffers[renderer.CONTEXT_UID] = this.generateBuffers(container);
+ }
+
+ // if the uvs have not updated then no point rendering just yet!
+ this.renderer.setBlendMode(container.blendMode);
+
+ var gl = renderer.gl;
+
+ var m = container.worldTransform.copy(this.tempMatrix);
+
+ m.prepend(renderer._activeRenderTarget.projectionMatrix);
+
+ this.shader.uniforms.projectionMatrix = m.toArray(true);
+ this.shader.uniforms.uAlpha = container.worldAlpha;
+
+ // make sure the texture is bound..
+ var baseTexture = children[0]._texture.baseTexture;
+
+ this.shader.uniforms.uSampler = renderer.bindTexture(baseTexture);
+
+ // now lets upload and render the buffers..
+ for (var i = 0, j = 0; i < totalChildren; i += batchSize, j += 1) {
+ var amount = totalChildren - i;
+
+ if (amount > batchSize) {
+ amount = batchSize;
+ }
+
+ var buffer = buffers[j];
+
+ // we always upload the dynamic
+ buffer.uploadDynamic(children, i, amount);
+
+ // we only upload the static content when we have to!
+ if (container._bufferToUpdate === j) {
+ buffer.uploadStatic(children, i, amount);
+ container._bufferToUpdate = j + 1;
+ }
+
+ // bind the buffer
+ renderer.bindVao(buffer.vao);
+ buffer.vao.draw(gl.TRIANGLES, amount * 6);
+ }
+ };
+
+ /**
+ * Creates one particle buffer for each child in the container we want to render and updates internal properties
+ *
+ * @param {PIXI.ParticleContainer} container - The container to render using this ParticleRenderer
+ * @return {PIXI.ParticleBuffer[]} The buffers
+ */
+
+
+ ParticleRenderer.prototype.generateBuffers = function generateBuffers(container) {
+ var gl = this.renderer.gl;
+ var buffers = [];
+ var size = container._maxSize;
+ var batchSize = container._batchSize;
+ var dynamicPropertyFlags = container._properties;
+
+ for (var i = 0; i < size; i += batchSize) {
+ buffers.push(new _ParticleBuffer2.default(gl, this.properties, dynamicPropertyFlags, batchSize));
+ }
+
+ return buffers;
+ };
+
+ /**
+ * Uploads the verticies.
+ *
+ * @param {PIXI.DisplayObject[]} children - the array of display objects to render
+ * @param {number} startIndex - the index to start from in the children array
+ * @param {number} amount - the amount of children that will have their vertices uploaded
+ * @param {number[]} array - The vertices to upload.
+ * @param {number} stride - Stride to use for iteration.
+ * @param {number} offset - Offset to start at.
+ */
+
+
+ ParticleRenderer.prototype.uploadVertices = function uploadVertices(children, startIndex, amount, array, stride, offset) {
+ var w0 = 0;
+ var w1 = 0;
+ var h0 = 0;
+ var h1 = 0;
+
+ for (var i = 0; i < amount; ++i) {
+ var sprite = children[startIndex + i];
+ var texture = sprite._texture;
+ var sx = sprite.scale.x;
+ var sy = sprite.scale.y;
+ var trim = texture.trim;
+ var orig = texture.orig;
+
+ if (trim) {
+ // if the sprite is trimmed and is not a tilingsprite then we need to add the
+ // extra space before transforming the sprite coords..
+ w1 = trim.x - sprite.anchor.x * orig.width;
+ w0 = w1 + trim.width;
+
+ h1 = trim.y - sprite.anchor.y * orig.height;
+ h0 = h1 + trim.height;
+ } else {
+ w0 = orig.width * (1 - sprite.anchor.x);
+ w1 = orig.width * -sprite.anchor.x;
+
+ h0 = orig.height * (1 - sprite.anchor.y);
+ h1 = orig.height * -sprite.anchor.y;
+ }
+
+ array[offset] = w1 * sx;
+ array[offset + 1] = h1 * sy;
+
+ array[offset + stride] = w0 * sx;
+ array[offset + stride + 1] = h1 * sy;
+
+ array[offset + stride * 2] = w0 * sx;
+ array[offset + stride * 2 + 1] = h0 * sy;
+
+ array[offset + stride * 3] = w1 * sx;
+ array[offset + stride * 3 + 1] = h0 * sy;
+
+ offset += stride * 4;
+ }
+ };
+
+ /**
+ *
+ * @param {PIXI.DisplayObject[]} children - the array of display objects to render
+ * @param {number} startIndex - the index to start from in the children array
+ * @param {number} amount - the amount of children that will have their positions uploaded
+ * @param {number[]} array - The vertices to upload.
+ * @param {number} stride - Stride to use for iteration.
+ * @param {number} offset - Offset to start at.
+ */
+
+
+ ParticleRenderer.prototype.uploadPosition = function uploadPosition(children, startIndex, amount, array, stride, offset) {
+ for (var i = 0; i < amount; i++) {
+ var spritePosition = children[startIndex + i].position;
+
+ array[offset] = spritePosition.x;
+ array[offset + 1] = spritePosition.y;
+
+ array[offset + stride] = spritePosition.x;
+ array[offset + stride + 1] = spritePosition.y;
+
+ array[offset + stride * 2] = spritePosition.x;
+ array[offset + stride * 2 + 1] = spritePosition.y;
+
+ array[offset + stride * 3] = spritePosition.x;
+ array[offset + stride * 3 + 1] = spritePosition.y;
+
+ offset += stride * 4;
+ }
+ };
+
+ /**
+ *
+ * @param {PIXI.DisplayObject[]} children - the array of display objects to render
+ * @param {number} startIndex - the index to start from in the children array
+ * @param {number} amount - the amount of children that will have their rotation uploaded
+ * @param {number[]} array - The vertices to upload.
+ * @param {number} stride - Stride to use for iteration.
+ * @param {number} offset - Offset to start at.
+ */
+
+
+ ParticleRenderer.prototype.uploadRotation = function uploadRotation(children, startIndex, amount, array, stride, offset) {
+ for (var i = 0; i < amount; i++) {
+ var spriteRotation = children[startIndex + i].rotation;
+
+ array[offset] = spriteRotation;
+ array[offset + stride] = spriteRotation;
+ array[offset + stride * 2] = spriteRotation;
+ array[offset + stride * 3] = spriteRotation;
+
+ offset += stride * 4;
+ }
+ };
+
+ /**
+ *
+ * @param {PIXI.DisplayObject[]} children - the array of display objects to render
+ * @param {number} startIndex - the index to start from in the children array
+ * @param {number} amount - the amount of children that will have their rotation uploaded
+ * @param {number[]} array - The vertices to upload.
+ * @param {number} stride - Stride to use for iteration.
+ * @param {number} offset - Offset to start at.
+ */
+
+
+ ParticleRenderer.prototype.uploadUvs = function uploadUvs(children, startIndex, amount, array, stride, offset) {
+ for (var i = 0; i < amount; ++i) {
+ var textureUvs = children[startIndex + i]._texture._uvs;
+
+ if (textureUvs) {
+ array[offset] = textureUvs.x0;
+ array[offset + 1] = textureUvs.y0;
+
+ array[offset + stride] = textureUvs.x1;
+ array[offset + stride + 1] = textureUvs.y1;
+
+ array[offset + stride * 2] = textureUvs.x2;
+ array[offset + stride * 2 + 1] = textureUvs.y2;
+
+ array[offset + stride * 3] = textureUvs.x3;
+ array[offset + stride * 3 + 1] = textureUvs.y3;
+
+ offset += stride * 4;
+ } else {
+ // TODO you know this can be easier!
+ array[offset] = 0;
+ array[offset + 1] = 0;
+
+ array[offset + stride] = 0;
+ array[offset + stride + 1] = 0;
+
+ array[offset + stride * 2] = 0;
+ array[offset + stride * 2 + 1] = 0;
+
+ array[offset + stride * 3] = 0;
+ array[offset + stride * 3 + 1] = 0;
+
+ offset += stride * 4;
+ }
+ }
+ };
+
+ /**
+ *
+ * @param {PIXI.DisplayObject[]} children - the array of display objects to render
+ * @param {number} startIndex - the index to start from in the children array
+ * @param {number} amount - the amount of children that will have their rotation uploaded
+ * @param {number[]} array - The vertices to upload.
+ * @param {number} stride - Stride to use for iteration.
+ * @param {number} offset - Offset to start at.
+ */
+
+
+ ParticleRenderer.prototype.uploadAlpha = function uploadAlpha(children, startIndex, amount, array, stride, offset) {
+ for (var i = 0; i < amount; i++) {
+ var spriteAlpha = children[startIndex + i].alpha;
+
+ array[offset] = spriteAlpha;
+ array[offset + stride] = spriteAlpha;
+ array[offset + stride * 2] = spriteAlpha;
+ array[offset + stride * 3] = spriteAlpha;
+
+ offset += stride * 4;
+ }
+ };
+
+ /**
+ * Destroys the ParticleRenderer.
+ *
+ */
+
+
+ ParticleRenderer.prototype.destroy = function destroy() {
+ if (this.renderer.gl) {
+ this.renderer.gl.deleteBuffer(this.indexBuffer);
+ }
+
+ _core$ObjectRenderer.prototype.destroy.call(this);
+
+ this.shader.destroy();
+
+ this.indices = null;
+ this.tempMatrix = null;
+ };
+
+ return ParticleRenderer;
+}(core.ObjectRenderer);
+
+exports.default = ParticleRenderer;
+
+
+core.WebGLRenderer.registerPlugin('particle', ParticleRenderer);
+
+},{"../../core":64,"./ParticleBuffer":173,"./ParticleShader":175}],175:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _Shader2 = require('../../core/Shader');
+
+var _Shader3 = _interopRequireDefault(_Shader2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * @class
+ * @extends PIXI.Shader
+ * @memberof PIXI
+ */
+var ParticleShader = function (_Shader) {
+ _inherits(ParticleShader, _Shader);
+
+ /**
+ * @param {PIXI.Shader} gl - The webgl shader manager this shader works for.
+ */
+ function ParticleShader(gl) {
+ _classCallCheck(this, ParticleShader);
+
+ return _possibleConstructorReturn(this, _Shader.call(this, gl,
+ // vertex shader
+ ['attribute vec2 aVertexPosition;', 'attribute vec2 aTextureCoord;', 'attribute float aColor;', 'attribute vec2 aPositionCoord;', 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', 'varying vec2 vTextureCoord;', 'varying float vColor;', 'void main(void){', ' vec2 v = aVertexPosition;', ' v.x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);', ' v.y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);', ' v = v + aPositionCoord;', ' gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);', ' vTextureCoord = aTextureCoord;', ' vColor = aColor;', '}'].join('\n'),
+ // hello
+ ['varying vec2 vTextureCoord;', 'varying float vColor;', 'uniform sampler2D uSampler;', 'uniform float uAlpha;', 'void main(void){', ' vec4 color = texture2D(uSampler, vTextureCoord) * vColor * uAlpha;', ' if (color.a == 0.0) discard;', ' gl_FragColor = color;', '}'].join('\n')));
+ }
+
+ return ParticleShader;
+}(_Shader3.default);
+
+exports.default = ParticleShader;
+
+},{"../../core/Shader":43}],176:[function(require,module,exports){
+"use strict";
+
+// References:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
+
+if (!Math.sign) {
+ Math.sign = function mathSign(x) {
+ x = Number(x);
+
+ if (x === 0 || isNaN(x)) {
+ return x;
+ }
+
+ return x > 0 ? 1 : -1;
+ };
+}
+
+},{}],177:[function(require,module,exports){
+'use strict';
+
+var _objectAssign = require('object-assign');
+
+var _objectAssign2 = _interopRequireDefault(_objectAssign);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+if (!Object.assign) {
+ Object.assign = _objectAssign2.default;
+} // References:
+// https://github.com/sindresorhus/object-assign
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
+
+},{"object-assign":5}],178:[function(require,module,exports){
+'use strict';
+
+require('./Object.assign');
+
+require('./requestAnimationFrame');
+
+require('./Math.sign');
+
+if (!window.ArrayBuffer) {
+ window.ArrayBuffer = Array;
+}
+
+if (!window.Float32Array) {
+ window.Float32Array = Array;
+}
+
+if (!window.Uint32Array) {
+ window.Uint32Array = Array;
+}
+
+if (!window.Uint16Array) {
+ window.Uint16Array = Array;
+}
+
+},{"./Math.sign":176,"./Object.assign":177,"./requestAnimationFrame":179}],179:[function(require,module,exports){
+(function (global){
+'use strict';
+
+// References:
+// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+// https://gist.github.com/1579671
+// http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision
+// https://gist.github.com/timhall/4078614
+// https://github.com/Financial-Times/polyfill-service/tree/master/polyfills/requestAnimationFrame
+
+// Expected to be used with Browserfiy
+// Browserify automatically detects the use of `global` and passes the
+// correct reference of `global`, `self`, and finally `window`
+
+var ONE_FRAME_TIME = 16;
+
+// Date.now
+if (!(Date.now && Date.prototype.getTime)) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+}
+
+// performance.now
+if (!(global.performance && global.performance.now)) {
+ var startTime = Date.now();
+
+ if (!global.performance) {
+ global.performance = {};
+ }
+
+ global.performance.now = function () {
+ return Date.now() - startTime;
+ };
+}
+
+// requestAnimationFrame
+var lastTime = Date.now();
+var vendors = ['ms', 'moz', 'webkit', 'o'];
+
+for (var x = 0; x < vendors.length && !global.requestAnimationFrame; ++x) {
+ var p = vendors[x];
+
+ global.requestAnimationFrame = global[p + 'RequestAnimationFrame'];
+ global.cancelAnimationFrame = global[p + 'CancelAnimationFrame'] || global[p + 'CancelRequestAnimationFrame'];
+}
+
+if (!global.requestAnimationFrame) {
+ global.requestAnimationFrame = function (callback) {
+ if (typeof callback !== 'function') {
+ throw new TypeError(callback + 'is not a function');
+ }
+
+ var currentTime = Date.now();
+ var delay = ONE_FRAME_TIME + lastTime - currentTime;
+
+ if (delay < 0) {
+ delay = 0;
+ }
+
+ lastTime = currentTime;
+
+ return setTimeout(function () {
+ lastTime = Date.now();
+ callback(performance.now());
+ }, delay);
+ };
+}
+
+if (!global.cancelAnimationFrame) {
+ global.cancelAnimationFrame = function (id) {
+ return clearTimeout(id);
+ };
+}
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],180:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _CountLimiter = require('./limiters/CountLimiter');
+
+var _CountLimiter2 = _interopRequireDefault(_CountLimiter);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var SharedTicker = core.ticker.shared;
+
+/**
+ * Default number of uploads per frame using prepare plugin.
+ *
+ * @static
+ * @memberof PIXI.settings
+ * @name UPLOADS_PER_FRAME
+ * @type {number}
+ * @default 4
+ */
+core.settings.UPLOADS_PER_FRAME = 4;
+
+/**
+ * The prepare manager provides functionality to upload content to the GPU. BasePrepare handles
+ * basic queuing functionality and is extended by {@link PIXI.prepare.WebGLPrepare} and {@link PIXI.prepare.CanvasPrepare}
+ * to provide preparation capabilities specific to their respective renderers.
+ *
+ * @example
+ * // Create a sprite
+ * const sprite = new PIXI.Sprite.fromImage('something.png');
+ *
+ * // Load object into GPU
+ * app.renderer.plugins.prepare.upload(sprite, () => {
+ *
+ * //Texture(s) has been uploaded to GPU
+ * app.stage.addChild(sprite);
+ *
+ * })
+ *
+ * @abstract
+ * @class
+ * @memberof PIXI.prepare
+ */
+
+var BasePrepare = function () {
+ /**
+ * @param {PIXI.SystemRenderer} renderer - A reference to the current renderer
+ */
+ function BasePrepare(renderer) {
+ var _this = this;
+
+ _classCallCheck(this, BasePrepare);
+
+ /**
+ * The limiter to be used to control how quickly items are prepared.
+ * @type {PIXI.prepare.CountLimiter|PIXI.prepare.TimeLimiter}
+ */
+ this.limiter = new _CountLimiter2.default(core.settings.UPLOADS_PER_FRAME);
+
+ /**
+ * Reference to the renderer.
+ * @type {PIXI.SystemRenderer}
+ * @protected
+ */
+ this.renderer = renderer;
+
+ /**
+ * The only real difference between CanvasPrepare and WebGLPrepare is what they pass
+ * to upload hooks. That different parameter is stored here.
+ * @type {PIXI.prepare.CanvasPrepare|PIXI.WebGLRenderer}
+ * @protected
+ */
+ this.uploadHookHelper = null;
+
+ /**
+ * Collection of items to uploads at once.
+ * @type {Array<*>}
+ * @private
+ */
+ this.queue = [];
+
+ /**
+ * Collection of additional hooks for finding assets.
+ * @type {Array}
+ * @private
+ */
+ this.addHooks = [];
+
+ /**
+ * Collection of additional hooks for processing assets.
+ * @type {Array}
+ * @private
+ */
+ this.uploadHooks = [];
+
+ /**
+ * Callback to call after completed.
+ * @type {Array}
+ * @private
+ */
+ this.completes = [];
+
+ /**
+ * If prepare is ticking (running).
+ * @type {boolean}
+ * @private
+ */
+ this.ticking = false;
+
+ /**
+ * 'bound' call for prepareItems().
+ * @type {Function}
+ * @private
+ */
+ this.delayedTick = function () {
+ // unlikely, but in case we were destroyed between tick() and delayedTick()
+ if (!_this.queue) {
+ return;
+ }
+ _this.prepareItems();
+ };
+
+ // hooks to find the correct texture
+ this.registerFindHook(findText);
+ this.registerFindHook(findTextStyle);
+ this.registerFindHook(findMultipleBaseTextures);
+ this.registerFindHook(findBaseTexture);
+ this.registerFindHook(findTexture);
+
+ // upload hooks
+ this.registerUploadHook(drawText);
+ this.registerUploadHook(calculateTextStyle);
+ }
+
+ /**
+ * Upload all the textures and graphics to the GPU.
+ *
+ * @param {Function|PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text} item -
+ * Either the container or display object to search for items to upload, the items to upload themselves,
+ * or the callback function, if items have been added using `prepare.add`.
+ * @param {Function} [done] - Optional callback when all queued uploads have completed
+ */
+
+
+ BasePrepare.prototype.upload = function upload(item, done) {
+ if (typeof item === 'function') {
+ done = item;
+ item = null;
+ }
+
+ // If a display object, search for items
+ // that we could upload
+ if (item) {
+ this.add(item);
+ }
+
+ // Get the items for upload from the display
+ if (this.queue.length) {
+ if (done) {
+ this.completes.push(done);
+ }
+
+ if (!this.ticking) {
+ this.ticking = true;
+ SharedTicker.addOnce(this.tick, this, core.UPDATE_PRIORITY.UTILITY);
+ }
+ } else if (done) {
+ done();
+ }
+ };
+
+ /**
+ * Handle tick update
+ *
+ * @private
+ */
+
+
+ BasePrepare.prototype.tick = function tick() {
+ setTimeout(this.delayedTick, 0);
+ };
+
+ /**
+ * Actually prepare items. This is handled outside of the tick because it will take a while
+ * and we do NOT want to block the current animation frame from rendering.
+ *
+ * @private
+ */
+
+
+ BasePrepare.prototype.prepareItems = function prepareItems() {
+ this.limiter.beginFrame();
+ // Upload the graphics
+ while (this.queue.length && this.limiter.allowedToUpload()) {
+ var item = this.queue[0];
+ var uploaded = false;
+
+ if (item && !item._destroyed) {
+ for (var i = 0, len = this.uploadHooks.length; i < len; i++) {
+ if (this.uploadHooks[i](this.uploadHookHelper, item)) {
+ this.queue.shift();
+ uploaded = true;
+ break;
+ }
+ }
+ }
+
+ if (!uploaded) {
+ this.queue.shift();
+ }
+ }
+
+ // We're finished
+ if (!this.queue.length) {
+ this.ticking = false;
+
+ var completes = this.completes.slice(0);
+
+ this.completes.length = 0;
+
+ for (var _i = 0, _len = completes.length; _i < _len; _i++) {
+ completes[_i]();
+ }
+ } else {
+ // if we are not finished, on the next rAF do this again
+ SharedTicker.addOnce(this.tick, this, core.UPDATE_PRIORITY.UTILITY);
+ }
+ };
+
+ /**
+ * Adds hooks for finding items.
+ *
+ * @param {Function} addHook - Function call that takes two parameters: `item:*, queue:Array`
+ * function must return `true` if it was able to add item to the queue.
+ * @return {PIXI.BasePrepare} Instance of plugin for chaining.
+ */
+
+
+ BasePrepare.prototype.registerFindHook = function registerFindHook(addHook) {
+ if (addHook) {
+ this.addHooks.push(addHook);
+ }
+
+ return this;
+ };
+
+ /**
+ * Adds hooks for uploading items.
+ *
+ * @param {Function} uploadHook - Function call that takes two parameters: `prepare:CanvasPrepare, item:*` and
+ * function must return `true` if it was able to handle upload of item.
+ * @return {PIXI.BasePrepare} Instance of plugin for chaining.
+ */
+
+
+ BasePrepare.prototype.registerUploadHook = function registerUploadHook(uploadHook) {
+ if (uploadHook) {
+ this.uploadHooks.push(uploadHook);
+ }
+
+ return this;
+ };
+
+ /**
+ * Manually add an item to the uploading queue.
+ *
+ * @param {PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text|*} item - Object to
+ * add to the queue
+ * @return {PIXI.CanvasPrepare} Instance of plugin for chaining.
+ */
+
+
+ BasePrepare.prototype.add = function add(item) {
+ // Add additional hooks for finding elements on special
+ // types of objects that
+ for (var i = 0, len = this.addHooks.length; i < len; i++) {
+ if (this.addHooks[i](item, this.queue)) {
+ break;
+ }
+ }
+
+ // Get childen recursively
+ if (item instanceof core.Container) {
+ for (var _i2 = item.children.length - 1; _i2 >= 0; _i2--) {
+ this.add(item.children[_i2]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Destroys the plugin, don't use after this.
+ *
+ */
+
+
+ BasePrepare.prototype.destroy = function destroy() {
+ if (this.ticking) {
+ SharedTicker.remove(this.tick, this);
+ }
+ this.ticking = false;
+ this.addHooks = null;
+ this.uploadHooks = null;
+ this.renderer = null;
+ this.completes = null;
+ this.queue = null;
+ this.limiter = null;
+ this.uploadHookHelper = null;
+ };
+
+ return BasePrepare;
+}();
+
+/**
+ * Built-in hook to find multiple textures from objects like AnimatedSprites.
+ *
+ * @private
+ * @param {PIXI.DisplayObject} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.Texture object was found.
+ */
+
+
+exports.default = BasePrepare;
+function findMultipleBaseTextures(item, queue) {
+ var result = false;
+
+ // Objects with mutliple textures
+ if (item && item._textures && item._textures.length) {
+ for (var i = 0; i < item._textures.length; i++) {
+ if (item._textures[i] instanceof core.Texture) {
+ var baseTexture = item._textures[i].baseTexture;
+
+ if (queue.indexOf(baseTexture) === -1) {
+ queue.push(baseTexture);
+ result = true;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Built-in hook to find BaseTextures from Sprites.
+ *
+ * @private
+ * @param {PIXI.DisplayObject} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.Texture object was found.
+ */
+function findBaseTexture(item, queue) {
+ // Objects with textures, like Sprites/Text
+ if (item instanceof core.BaseTexture) {
+ if (queue.indexOf(item) === -1) {
+ queue.push(item);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to find textures from objects.
+ *
+ * @private
+ * @param {PIXI.DisplayObject} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.Texture object was found.
+ */
+function findTexture(item, queue) {
+ if (item._texture && item._texture instanceof core.Texture) {
+ var texture = item._texture.baseTexture;
+
+ if (queue.indexOf(texture) === -1) {
+ queue.push(texture);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to draw PIXI.Text to its texture.
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer|PIXI.CanvasPrepare} helper - Not used by this upload handler
+ * @param {PIXI.DisplayObject} item - Item to check
+ * @return {boolean} If item was uploaded.
+ */
+function drawText(helper, item) {
+ if (item instanceof core.Text) {
+ // updating text will return early if it is not dirty
+ item.updateText(true);
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to calculate a text style for a PIXI.Text object.
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer|PIXI.CanvasPrepare} helper - Not used by this upload handler
+ * @param {PIXI.DisplayObject} item - Item to check
+ * @return {boolean} If item was uploaded.
+ */
+function calculateTextStyle(helper, item) {
+ if (item instanceof core.TextStyle) {
+ var font = core.Text.getFontStyle(item);
+
+ if (!core.Text.fontPropertiesCache[font]) {
+ core.Text.calculateFontProperties(font);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to find Text objects.
+ *
+ * @private
+ * @param {PIXI.DisplayObject} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.Text object was found.
+ */
+function findText(item, queue) {
+ if (item instanceof core.Text) {
+ // push the text style to prepare it - this can be really expensive
+ if (queue.indexOf(item.style) === -1) {
+ queue.push(item.style);
+ }
+ // also push the text object so that we can render it (to canvas/texture) if needed
+ if (queue.indexOf(item) === -1) {
+ queue.push(item);
+ }
+ // also push the Text's texture for upload to GPU
+ var texture = item._texture.baseTexture;
+
+ if (queue.indexOf(texture) === -1) {
+ queue.push(texture);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to find TextStyle objects.
+ *
+ * @private
+ * @param {PIXI.TextStyle} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.TextStyle object was found.
+ */
+function findTextStyle(item, queue) {
+ if (item instanceof core.TextStyle) {
+ if (queue.indexOf(item) === -1) {
+ queue.push(item);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+},{"../core":64,"./limiters/CountLimiter":183}],181:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _BasePrepare2 = require('../BasePrepare');
+
+var _BasePrepare3 = _interopRequireDefault(_BasePrepare2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var CANVAS_START_SIZE = 16;
+
+/**
+ * The prepare manager provides functionality to upload content to the GPU
+ * This cannot be done directly for Canvas like in WebGL, but the effect can be achieved by drawing
+ * textures to an offline canvas.
+ * This draw call will force the texture to be moved onto the GPU.
+ *
+ * An instance of this class is automatically created by default, and can be found at renderer.plugins.prepare
+ *
+ * @class
+ * @extends PIXI.prepare.BasePrepare
+ * @memberof PIXI.prepare
+ */
+
+var CanvasPrepare = function (_BasePrepare) {
+ _inherits(CanvasPrepare, _BasePrepare);
+
+ /**
+ * @param {PIXI.CanvasRenderer} renderer - A reference to the current renderer
+ */
+ function CanvasPrepare(renderer) {
+ _classCallCheck(this, CanvasPrepare);
+
+ var _this = _possibleConstructorReturn(this, _BasePrepare.call(this, renderer));
+
+ _this.uploadHookHelper = _this;
+
+ /**
+ * An offline canvas to render textures to
+ * @type {HTMLCanvasElement}
+ * @private
+ */
+ _this.canvas = document.createElement('canvas');
+ _this.canvas.width = CANVAS_START_SIZE;
+ _this.canvas.height = CANVAS_START_SIZE;
+
+ /**
+ * The context to the canvas
+ * @type {CanvasRenderingContext2D}
+ * @private
+ */
+ _this.ctx = _this.canvas.getContext('2d');
+
+ // Add textures to upload
+ _this.registerUploadHook(uploadBaseTextures);
+ return _this;
+ }
+
+ /**
+ * Destroys the plugin, don't use after this.
+ *
+ */
+
+
+ CanvasPrepare.prototype.destroy = function destroy() {
+ _BasePrepare.prototype.destroy.call(this);
+ this.ctx = null;
+ this.canvas = null;
+ };
+
+ return CanvasPrepare;
+}(_BasePrepare3.default);
+
+/**
+ * Built-in hook to upload PIXI.Texture objects to the GPU.
+ *
+ * @private
+ * @param {*} prepare - Instance of CanvasPrepare
+ * @param {*} item - Item to check
+ * @return {boolean} If item was uploaded.
+ */
+
+
+exports.default = CanvasPrepare;
+function uploadBaseTextures(prepare, item) {
+ if (item instanceof core.BaseTexture) {
+ var image = item.source;
+
+ // Sometimes images (like atlas images) report a size of zero, causing errors on windows phone.
+ // So if the width or height is equal to zero then use the canvas size
+ // Otherwise use whatever is smaller, the image dimensions or the canvas dimensions.
+ var imageWidth = image.width === 0 ? prepare.canvas.width : Math.min(prepare.canvas.width, image.width);
+ var imageHeight = image.height === 0 ? prepare.canvas.height : Math.min(prepare.canvas.height, image.height);
+
+ // Only a small subsections is required to be drawn to have the whole texture uploaded to the GPU
+ // A smaller draw can be faster.
+ prepare.ctx.drawImage(image, 0, 0, imageWidth, imageHeight, 0, 0, prepare.canvas.width, prepare.canvas.height);
+
+ return true;
+ }
+
+ return false;
+}
+
+core.CanvasRenderer.registerPlugin('prepare', CanvasPrepare);
+
+},{"../../core":64,"../BasePrepare":180}],182:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _WebGLPrepare = require('./webgl/WebGLPrepare');
+
+Object.defineProperty(exports, 'webgl', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_WebGLPrepare).default;
+ }
+});
+
+var _CanvasPrepare = require('./canvas/CanvasPrepare');
+
+Object.defineProperty(exports, 'canvas', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_CanvasPrepare).default;
+ }
+});
+
+var _BasePrepare = require('./BasePrepare');
+
+Object.defineProperty(exports, 'BasePrepare', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_BasePrepare).default;
+ }
+});
+
+var _CountLimiter = require('./limiters/CountLimiter');
+
+Object.defineProperty(exports, 'CountLimiter', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_CountLimiter).default;
+ }
+});
+
+var _TimeLimiter = require('./limiters/TimeLimiter');
+
+Object.defineProperty(exports, 'TimeLimiter', {
+ enumerable: true,
+ get: function get() {
+ return _interopRequireDefault(_TimeLimiter).default;
+ }
+});
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+},{"./BasePrepare":180,"./canvas/CanvasPrepare":181,"./limiters/CountLimiter":183,"./limiters/TimeLimiter":184,"./webgl/WebGLPrepare":185}],183:[function(require,module,exports){
+"use strict";
+
+exports.__esModule = true;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * CountLimiter limits the number of items handled by a {@link PIXI.prepare.BasePrepare} to a specified
+ * number of items per frame.
+ *
+ * @class
+ * @memberof PIXI
+ */
+var CountLimiter = function () {
+ /**
+ * @param {number} maxItemsPerFrame - The maximum number of items that can be prepared each frame.
+ */
+ function CountLimiter(maxItemsPerFrame) {
+ _classCallCheck(this, CountLimiter);
+
+ /**
+ * The maximum number of items that can be prepared each frame.
+ * @private
+ */
+ this.maxItemsPerFrame = maxItemsPerFrame;
+ /**
+ * The number of items that can be prepared in the current frame.
+ * @type {number}
+ * @private
+ */
+ this.itemsLeft = 0;
+ }
+
+ /**
+ * Resets any counting properties to start fresh on a new frame.
+ */
+
+
+ CountLimiter.prototype.beginFrame = function beginFrame() {
+ this.itemsLeft = this.maxItemsPerFrame;
+ };
+
+ /**
+ * Checks to see if another item can be uploaded. This should only be called once per item.
+ * @return {boolean} If the item is allowed to be uploaded.
+ */
+
+
+ CountLimiter.prototype.allowedToUpload = function allowedToUpload() {
+ return this.itemsLeft-- > 0;
+ };
+
+ return CountLimiter;
+}();
+
+exports.default = CountLimiter;
+
+},{}],184:[function(require,module,exports){
+"use strict";
+
+exports.__esModule = true;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * TimeLimiter limits the number of items handled by a {@link PIXI.BasePrepare} to a specified
+ * number of milliseconds per frame.
+ *
+ * @class
+ * @memberof PIXI
+ */
+var TimeLimiter = function () {
+ /**
+ * @param {number} maxMilliseconds - The maximum milliseconds that can be spent preparing items each frame.
+ */
+ function TimeLimiter(maxMilliseconds) {
+ _classCallCheck(this, TimeLimiter);
+
+ /**
+ * The maximum milliseconds that can be spent preparing items each frame.
+ * @private
+ */
+ this.maxMilliseconds = maxMilliseconds;
+ /**
+ * The start time of the current frame.
+ * @type {number}
+ * @private
+ */
+ this.frameStart = 0;
+ }
+
+ /**
+ * Resets any counting properties to start fresh on a new frame.
+ */
+
+
+ TimeLimiter.prototype.beginFrame = function beginFrame() {
+ this.frameStart = Date.now();
+ };
+
+ /**
+ * Checks to see if another item can be uploaded. This should only be called once per item.
+ * @return {boolean} If the item is allowed to be uploaded.
+ */
+
+
+ TimeLimiter.prototype.allowedToUpload = function allowedToUpload() {
+ return Date.now() - this.frameStart < this.maxMilliseconds;
+ };
+
+ return TimeLimiter;
+}();
+
+exports.default = TimeLimiter;
+
+},{}],185:[function(require,module,exports){
+'use strict';
+
+exports.__esModule = true;
+
+var _core = require('../../core');
+
+var core = _interopRequireWildcard(_core);
+
+var _BasePrepare2 = require('../BasePrepare');
+
+var _BasePrepare3 = _interopRequireDefault(_BasePrepare2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * The prepare manager provides functionality to upload content to the GPU.
+ *
+ * An instance of this class is automatically created by default, and can be found at renderer.plugins.prepare
+ *
+ * @class
+ * @extends PIXI.prepare.BasePrepare
+ * @memberof PIXI.prepare
+ */
+var WebGLPrepare = function (_BasePrepare) {
+ _inherits(WebGLPrepare, _BasePrepare);
+
+ /**
+ * @param {PIXI.WebGLRenderer} renderer - A reference to the current renderer
+ */
+ function WebGLPrepare(renderer) {
+ _classCallCheck(this, WebGLPrepare);
+
+ var _this = _possibleConstructorReturn(this, _BasePrepare.call(this, renderer));
+
+ _this.uploadHookHelper = _this.renderer;
+
+ // Add textures and graphics to upload
+ _this.registerFindHook(findGraphics);
+ _this.registerUploadHook(uploadBaseTextures);
+ _this.registerUploadHook(uploadGraphics);
+ return _this;
+ }
+
+ return WebGLPrepare;
+}(_BasePrepare3.default);
+/**
+ * Built-in hook to upload PIXI.Texture objects to the GPU.
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer} renderer - instance of the webgl renderer
+ * @param {PIXI.DisplayObject} item - Item to check
+ * @return {boolean} If item was uploaded.
+ */
+
+
+exports.default = WebGLPrepare;
+function uploadBaseTextures(renderer, item) {
+ if (item instanceof core.BaseTexture) {
+ // if the texture already has a GL texture, then the texture has been prepared or rendered
+ // before now. If the texture changed, then the changer should be calling texture.update() which
+ // reuploads the texture without need for preparing it again
+ if (!item._glTextures[renderer.CONTEXT_UID]) {
+ renderer.textureManager.updateTexture(item);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to upload PIXI.Graphics to the GPU.
+ *
+ * @private
+ * @param {PIXI.WebGLRenderer} renderer - instance of the webgl renderer
+ * @param {PIXI.DisplayObject} item - Item to check
+ * @return {boolean} If item was uploaded.
+ */
+function uploadGraphics(renderer, item) {
+ if (item instanceof core.Graphics) {
+ // if the item is not dirty and already has webgl data, then it got prepared or rendered
+ // before now and we shouldn't waste time updating it again
+ if (item.dirty || item.clearDirty || !item._webGL[renderer.plugins.graphics.CONTEXT_UID]) {
+ renderer.plugins.graphics.updateGraphics(item);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Built-in hook to find graphics.
+ *
+ * @private
+ * @param {PIXI.DisplayObject} item - Display object to check
+ * @param {Array<*>} queue - Collection of items to upload
+ * @return {boolean} if a PIXI.Graphics object was found.
+ */
+function findGraphics(item, queue) {
+ if (item instanceof core.Graphics) {
+ queue.push(item);
+
+ return true;
+ }
+
+ return false;
+}
+
+core.WebGLRenderer.registerPlugin('prepare', WebGLPrepare);
+
+},{"../../core":64,"../BasePrepare":180}],186:[function(require,module,exports){
+(function (global){
+'use strict';
+
+exports.__esModule = true;
+exports.loader = exports.prepare = exports.particles = exports.mesh = exports.loaders = exports.interaction = exports.filters = exports.extras = exports.extract = exports.accessibility = undefined;
+
+var _polyfill = require('./polyfill');
+
+Object.keys(_polyfill).forEach(function (key) {
+ if (key === "default" || key === "__esModule") return;
+ Object.defineProperty(exports, key, {
+ enumerable: true,
+ get: function get() {
+ return _polyfill[key];
+ }
+ });
+});
+
+var _core = require('./core');
+
+Object.keys(_core).forEach(function (key) {
+ if (key === "default" || key === "__esModule") return;
+ Object.defineProperty(exports, key, {
+ enumerable: true,
+ get: function get() {
+ return _core[key];
+ }
+ });
+});
+
+var _deprecation = require('./deprecation');
+
+var _deprecation2 = _interopRequireDefault(_deprecation);
+
+var _accessibility = require('./accessibility');
+
+var accessibility = _interopRequireWildcard(_accessibility);
+
+var _extract = require('./extract');
+
+var extract = _interopRequireWildcard(_extract);
+
+var _extras = require('./extras');
+
+var extras = _interopRequireWildcard(_extras);
+
+var _filters = require('./filters');
+
+var filters = _interopRequireWildcard(_filters);
+
+var _interaction = require('./interaction');
+
+var interaction = _interopRequireWildcard(_interaction);
+
+var _loaders = require('./loaders');
+
+var loaders = _interopRequireWildcard(_loaders);
+
+var _mesh = require('./mesh');
+
+var mesh = _interopRequireWildcard(_mesh);
+
+var _particles = require('./particles');
+
+var particles = _interopRequireWildcard(_particles);
+
+var _prepare = require('./prepare');
+
+var prepare = _interopRequireWildcard(_prepare);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// export core
+_core.utils.mixins.performMixins();
+
+/**
+ * Alias for {@link PIXI.loaders.shared}.
+ * @name loader
+ * @memberof PIXI
+ * @type {PIXI.loader.Loader}
+ */
+
+
+// handle mixins now, after all code has been added, including deprecation
+
+
+// export libs
+// import polyfills. Done as an export to make sure polyfills are imported first
+var loader = loaders.shared || null;
+
+exports.accessibility = accessibility;
+exports.extract = extract;
+exports.extras = extras;
+exports.filters = filters;
+exports.interaction = interaction;
+exports.loaders = loaders;
+exports.mesh = mesh;
+exports.particles = particles;
+exports.prepare = prepare;
+exports.loader = loader;
+
+// Apply the deprecations
+
+if (typeof _deprecation2.default === 'function') {
+ (0, _deprecation2.default)(exports);
+}
+
+// Always export pixi globally.
+global.PIXI = exports; // eslint-disable-line
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"./accessibility":41,"./core":64,"./deprecation":128,"./extract":130,"./extras":139,"./filters":150,"./interaction":157,"./loaders":160,"./mesh":169,"./particles":172,"./polyfill":178,"./prepare":182}]},{},[186])(186)
+});
+
+
+//# sourceMappingURL=pixi.js.map
diff --git a/h5/snake/lib/utils/Chain.js b/h5/snake/lib/utils/Chain.js
new file mode 100644
index 0000000..5059165
--- /dev/null
+++ b/h5/snake/lib/utils/Chain.js
@@ -0,0 +1,315 @@
+/*
+ @author: leeenx
+ @双向链表结构
+*/
+
+export default class Chain {
+ constructor(arr = []) {
+ // 用于存储链表的数组
+ this.chain = [];
+ this.chain.length = arr.length;
+ // 把 arr 转化为 chain
+ for(let i = 0, len = arr.length; i < len; ++i) {
+ this.chain[i] = {
+ index: i,
+ prev: i - 1,
+ next: i !== len -1 ? i + 1 : -1,
+ data: arr[i]
+ }
+ }
+
+ // 头指针
+ this.HEAD = arr.length ? 0 : -1;
+ // 尾指针
+ this.TAIL = arr.length ? arr.length - 1 : -1;
+ // 定位指针
+ this.POINTER = -1;
+ // 自由指针
+ this.FREE = arr.length;
+ // 自由列表 - 回收FREE
+ this.FREELIST = [];
+ // 链表的长度
+ this.length = this.chain.length;
+ // 创建一个迭代器
+ this[Symbol.iterator] = () => {
+ // 指针指向头部
+ let that = this, cur = that.chain[this.HEAD];
+ return (function* () {
+ while(cur !== undefined) {
+ yield cur;
+ cur = that.chain[cur.next];
+ }
+ }());
+ }
+ }
+ // 返回链头并删除链头
+ shift() {
+ // 回收 FREE
+ this.collection();
+ // FREE 指向被删除的位置
+ this.FREE = this.HEAD;
+ // 头指头指向下一个位置
+ this.HEAD = this.chain[this.HEAD].next;
+ // 当前头指针的 prev 指向 -1
+ this.HEAD !== -1 && (this.chain[this.HEAD].prev = -1);
+ // 链表长度为0时,尾指针指向-1
+ --this.length === 0 && (this.TAIL = -1);
+ // 返回 FREE
+ return this.chain[this.FREE];
+ }
+ // 插入新的链头
+ unshift(item) {
+ // 新链表的第二个节点
+ let second = this.HEAD;
+ // 头指针指向 FREE
+ this.HEAD = this.FREE;
+ // 创建新的头节点
+ this.chain[this.HEAD] = {
+ index: this.HEAD,
+ prev: -1,
+ next: second,
+ data: item
+ }
+ // 旧的头节点 prev 指向当前头节点
+ if(second !== -1) {
+ this.chain[second].prev = this.HEAD;
+ }
+ else {
+ // 链表里只有一个节点,保证this.TAIL !== -1
+ this.TAIL = this.HEAD;
+ }
+ // 创建一个 FREE
+ this.calloc();
+ // 链表长度 +1
+ ++this.length;
+ }
+ // 返回链尾并删除表尾
+ pop() {
+ // 回收 FREE
+ this.collection();
+ // FREE 指向被删除的位置
+ this.FREE = this.TAIL;
+ // 尾指针指向上一个位置
+ this.TAIL = this.chain[this.TAIL].prev;
+ // 当前尾指针的 next 指向 -1
+ this.TAIL !== -1 && (this.chain[this.TAIL].next = -1);
+ // 链表长度为0时,头指针指向-1
+ --this.length === 0 && (this.HEAD = -1);
+ // 返回 FREE
+ return this.chain[this.FREE];
+ }
+ // 插入新的链尾
+ push(item) {
+ // 新链表的倒数第二个节点
+ let penultimate = this.TAIL;
+ // 尾指针指向 FREE
+ this.TAIL = this.FREE;
+ // 创建新的尾节点
+ this.chain[this.TAIL] = {
+ index: this.TAIL,
+ prev: penultimate,
+ next: -1,
+ data: item
+ }
+
+ // 旧的尾节点 next 指向当前尾节点
+ if(penultimate !== -1) {
+ this.chain[penultimate].next = this.TAIL;
+ }
+ else {
+ // 链表里只有一个节点,保证this.HEAD !== -1
+ this.HEAD = this.TAIL;
+ }
+ // 创建一个 FREE
+ this.calloc();
+ // 链表长度 +1
+ ++this.length;
+ }
+ // 返回指定索引的元素
+ at(index = 0) {
+ if(index < 0 || index >= this.length) return;
+ let cur;
+ if(index < this.length / 2) {
+ // 从头部开始
+ cur = this.chain[this.HEAD];
+ for(let i = 0; i !== index; ++i) {
+ cur = this.chain[cur.next];
+ this.POINTER = cur.index;
+ }
+ } else {
+ // 从尾部开始
+ cur = this.chain[this.TAIL];
+ for(let i = this.length - 1; i !== index; --i) {
+ cur = this.chain[cur.prev];
+ }
+ }
+ return cur;
+ }
+ // 返回指定指针的元素
+ pointerAt(addr) {
+ // 指针地址索引在 0 ~ this.lenght,为合法地址
+ if(addr >= 0 && addr < this.length) {
+ return this.chain[addr];
+ }
+ }
+ // 返回第一个元素
+ first() {
+ return this.chain[this.HEAD];
+ }
+ // 返回最后一个元素
+ last() {
+ return this.chain[this.TAIL];
+ }
+ // 返回当前元素,并把 POINTER 指向上一个元素
+ prev() {
+ // 当前节点
+ let cur = this.curr();
+ // POINTER 指向上一个,如果指向 -1 则重置为 this.HEAD
+ this.POINTER !== -1 ? (this.POINTER = this.chain[this.POINTER].prev) : (this.POINTER = this.HEAD);
+ return cur;
+ }
+ // 返回前当元素,并把 POINTER 指向下一个元素
+ next() {
+ // 当前节点
+ let cur = this.curr();
+ // POINTER 指向下一个,如果指向 -1 则重置为 this.TAIL
+ this.POINTER !== -1 ? (this.POINTER = this.chain[this.POINTER].next) : (this.POINTER = this.TAIL);
+ return cur;
+ }
+ // 返回当前元素
+ curr() {
+ return this.chain[this.POINTER];
+ }
+ // 定位指针
+ setPointer(addr = this.POINTER) {
+ // 指针地址索引在 0 ~ this.lenght,为合法地址
+ if(addr >= 0 && addr < this.length) {
+ this.POINTER = addr;
+ return true;
+ }
+ }
+ // 克隆
+ clone() {
+ let copy = new Chain();
+ for(let key of ["HEAD", "TAIL", "FREE", "length"]) {
+ copy[key] = this[key];
+ }
+ copy.chain.length = copy.length;
+ // 链表数据拷贝
+ for(let i = 0, len = copy.length; i=this.length) return ;
+ // 数组索引内
+ if(index === 0) {
+ // 指向表头
+ return this.shift();
+ } else if(index === this.length - 1) {
+ // 指向表尾
+ return this.pop();
+ } else {
+ // 当前节点
+ let cur = this.at(index);
+ // 上一个节点
+ let prev = this.chain[cur.prev];
+ // 下一个节点
+ let next = this.chain[cur.next];
+ // 回收 FREE
+ this.collection();
+ // FREE 指向被删除的位置
+ this.FREE = cur.index;
+ // 删除当前节点
+ [prev.next, next.prev] = [next.index, prev.index];
+ // 链表长度 -1
+ --this.length;
+ // 返回 FREE
+ return cur;
+ }
+ }
+ // 在指定索引前插入元素
+ insertBefore(index, item) {
+ // 数组范围之外
+ if(index < 0 || index >= this.length) return ;
+ // 当前节点
+ let cur = this.at(index);
+ // 上一个节点
+ let prev = this.chain[cur.prev] || {index: -1};
+ // 下一个节点
+ let next = cur;
+ // 插入新节点
+ cur = this.chain[this.FREE] = {
+ index: this.FREE,
+ prev: prev.index,
+ next: next.index,
+ data: item
+ }
+ next.prev = cur.index;
+ // 上一个节点存在
+ if(prev.index !== -1) {
+ prev.next = cur.index;
+ }
+ // 插入的是头节点
+ else {
+ this.HEAD = cur.index;
+ }
+ // 创建一个 FREE
+ this.calloc();
+ // 链表长度 +1
+ ++this.length;
+ }
+ // 在指定索引后插入元素,与 insertBefore 做对就
+ insertAfter(index, item) {
+ // 数组范围之外
+ if(index < 0 || index >= this.length) return ;
+ // 当前节点
+ let cur = this.at(index);
+ // 下一个节点
+ let next = this.chain[cur.next] || {index: -1};
+ // 上一个节点
+ let prev = cur;
+ // 插入新节点
+ cur = this.chain[this.FREE] = {
+ index: this.FREE,
+ prev: prev.index,
+ next: next.index,
+ data: item
+ }
+ prev.next = cur.index;
+ // 下一个节点存在
+ if(next.index !== -1) {
+ next.prev = cur.index;
+ }
+ // 插入的是尾节点
+ else {
+ this.TAIL = cur.index;
+ }
+ // 创建一个 FREE
+ this.calloc();
+ // 链表长度 +1
+ ++this.length;
+ }
+ // 清空链表
+ clean() {
+ // 清空数组
+ this.length = this.chain.length = this.FREELIST.length = 0;
+ this.POINTER = this.HEAD = this.TAIL = -1;
+ this.FREE = 0;
+ }
+ // 动态分配 FREE
+ calloc() {
+ // FREE 指向新位置
+ this.FREE = this.FREELIST.length ? this.FREELIST.pop() : this.chain.length;
+ }
+ // 回收 FREE
+ collection() {
+ // 把 FREE 加入到 FREELIST
+ this.FREELIST.push(this.FREE);
+ }
+}
\ No newline at end of file
diff --git a/h5/snake/lib/utils/events.js b/h5/snake/lib/utils/events.js
new file mode 100644
index 0000000..e6ed9bb
--- /dev/null
+++ b/h5/snake/lib/utils/events.js
@@ -0,0 +1,63 @@
+/*
+ @ author: leeenx
+ @ 事件封装
+ @ object.on(event, fn) // 监听一个事件
+ @ object.off(event, fn) // 取消监听
+ @ object.once(event, fn) // 只监听一次事件
+ @ object.dispacth(event, arg) // 触发一个事件
+*/
+
+export default class Events {
+ constructor() {
+ // 定义的事件与回调
+ this.defineEvent = {};
+ }
+ // 注册事件
+ register(event, cb) {
+ if(!this.defineEvent[event]) {
+ (this.defineEvent[event] = [cb]);
+ }
+ else {
+ this.defineEvent[event].push(cb);
+ }
+ }
+ // 派遣事件
+ dispatch(event, arg) {
+ if(this.defineEvent[event]) {{
+ for(let i=0, len = this.defineEvent[event].length; i this.defineEvent[event].splice(i, 1), 0);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // once 方法,监听一次
+ once(event, cb) {
+ let onceCb = () => {
+ cb && cb();
+ this.off(event, onceCb);
+ }
+ this.register(event, onceCb);
+ }
+}
\ No newline at end of file
diff --git a/h5/snake/lib/utils/getContentBoxSize.js b/h5/snake/lib/utils/getContentBoxSize.js
new file mode 100644
index 0000000..f9cb44b
--- /dev/null
+++ b/h5/snake/lib/utils/getContentBoxSize.js
@@ -0,0 +1,36 @@
+/*
+ author: leeenx
+ date: 2017.09.08
+ @ 获取不带描边的boudary
+*/
+import * as PIXI from "../pixi";
+{
+ let dirty = Symbol("dirty");
+ let getContentBox = function () {
+ if (this[dirty] == this.dirty) return;
+ this[dirty] = this.dirty; // 表示已经更新
+ let cp = this.clone();
+ let graphicsData = cp.graphicsData;
+ for (let graphics of graphicsData) {
+ graphics.lineWidth = 0;
+ }
+ this._cwidth = cp.width;
+ this._cheight = cp.height;
+ };
+ Object.defineProperties(PIXI.Graphics.prototype, {
+ _cwidth: { writable: true, value: 0 },
+ _cheight: { writable: true, value: 0 },
+ cwidth: {
+ get: function () {
+ getContentBox.call(this);
+ return this._cwidth;
+ },
+ },
+ cheight: {
+ get: function () {
+ getContentBox.call(this);
+ return this._cheight;
+ },
+ },
+ });
+}
diff --git a/h5/snake/lib/utils/noHello.js b/h5/snake/lib/utils/noHello.js
new file mode 100644
index 0000000..3802c94
--- /dev/null
+++ b/h5/snake/lib/utils/noHello.js
@@ -0,0 +1 @@
+PIXI.utils.skipHello();
\ No newline at end of file
diff --git a/h5/snake/lib/utils/randomList.js b/h5/snake/lib/utils/randomList.js
new file mode 100644
index 0000000..5ad505b
--- /dev/null
+++ b/h5/snake/lib/utils/randomList.js
@@ -0,0 +1,12 @@
+// es6 随机按顺序数组
+export default (list = [], count = list.length, filter) =>
+{
+ list = [].concat(list); // 切断与参数list 的耦合
+ list = typeof filter === "function" ? list.filter( (...args) => filter(...args) ) : list;
+ let res = [];
+ for(let i=0; i>0];
+ res = res.concat(list.splice(randomIndex, 1));
+ }
+ return res.length == 1 ? res[0] : res;
+}
\ No newline at end of file
diff --git a/h5/snake/lib/utils/ticker.js b/h5/snake/lib/utils/ticker.js
new file mode 100644
index 0000000..09570cf
--- /dev/null
+++ b/h5/snake/lib/utils/ticker.js
@@ -0,0 +1,27 @@
+/*
+ author: leeenx
+ @ ticker 对象
+ @ 提供 5 个API如下:
+ @ ticker.addEventListener
+ @ ticker.removeEventListener
+ @ ticker.pause - 暂停
+ @ ticker.resume - 恢复
+ @ ticker.paused - 暂停状态
+ @ 这里直接借用 GSAP.TweenMax.ticker
+*/
+import TweenMax from "../gsap/TweenMax";
+let ticker = {};
+ticker.paused = 0;
+(ticker.pause = () => (ticker.paused = 1)), TweenMax.pauseAll();
+(ticker.resume = () => (ticker.paused = 0)), TweenMax.resumeAll();
+ticker.addEventListener = (...args) =>
+ TweenMax.ticker.addEventListener(...args);
+ticker.removeEventListener = (...args) =>
+ TweenMax.ticker.removeEventListener(...args);
+
+TweenMax.ticker.addEventListener("tick", () => {
+ ticker.elapsedMS = TweenMax.ticker.time - TweenMax.ticker._time;
+ TweenMax.ticker._time = TweenMax.ticker.time;
+});
+
+export default ticker;
diff --git a/h5/snake/lib/utils/timer.js b/h5/snake/lib/utils/timer.js
new file mode 100644
index 0000000..8816e25
--- /dev/null
+++ b/h5/snake/lib/utils/timer.js
@@ -0,0 +1,176 @@
+/*
+ author: leeenx
+ @ timer 对象
+ @ 提供 7 个API如下:
+ @ timer.setTimeout(fun, delay[, id])
+ @ timer.clearTimeout(id)
+ @ timer.setInterval(fun, delay[, id])
+ @ timer.clearInterval(id)
+ @ timer.delete(id) 删除对应id的timeout/interval
+ @ timer.pause(id) 暂停对应id的timeout/interval
+ @ timer.resume(id) 恢复对应id的timeout/interval
+ @ timer.clean() 清空所有 timeout & interval
+*/
+
+class Timer {
+ // 构造函数
+ constructor() {
+ // 暂停状态 - 这是个公共状态,由外部 Ticker 决定。
+ this.paused = true;
+
+ // 队列
+ this.queue = new Map();
+
+ // 正在使用 timer 的 RAF
+ this.usingRAF = false;
+
+ // useRAF 触发器
+ Reflect.defineProperty(this, "useRAF", {
+ set: function(value) {
+ Reflect.set(this, "usingRAF", value);
+ value ? Timer.RAF.enable() : Timer.RAF.disable();
+ }
+ });
+ }
+
+ // setTimeout 的实现
+ setTimeout(fn, delay, id = Symbol("timeoutID")) {
+ // 存入队列
+ this.queue.set(id, {
+ fn: fn,
+ type: 0,
+ paused: 0,
+ elapsed: 0,
+ delay: delay
+ });
+ return id;
+ }
+
+ // clearTimeout
+ clearTimeout(id) {
+ this.delete(id);
+ }
+
+ // setInterval 的实现
+ setInterval(fn, delay, id = Symbol("intervalID")) {
+ // 存入队列
+ this.queue.set(id, {
+ fn: fn,
+ type: 1,
+ paused: 0,
+ elapsed: 0,
+ delay: delay
+ });
+ return id;
+ }
+
+ // clearInterval
+ clearInterval(id) {
+ this.delete(id);
+ }
+
+ // 修改指定id的 delay/fn
+ set(id, config = {}) {
+ let item = this.queue.get(id) || {};
+ for(let key in config) {
+ item[key] = config[key];
+ }
+ }
+
+ // 删除 queue 上的成员
+ delete(id) {
+ this.queue.delete(id);
+ }
+
+ // 暂停指定id
+ pause(id) {
+ id === undefined ? this.pauseAll() : (this.queue.get(id).paused = 1);
+ }
+
+ // 恢复指定id
+ resume(id) {
+ this.play(id);
+ }
+
+ // 播放指定id
+ play(id) {
+ id === undefined ? this.playAll() : (this.queue.get(id).paused = 0);
+ }
+
+ // 清空timer
+ clean() {
+ this.queue = new Map();
+ }
+
+ // 暂停全部 id
+ pauseAll() {
+ this.queue.forEach((item) => item.paused = 1);
+ }
+
+ // 播放全部 id
+ playAll() {
+ this.queue.forEach((item) => item.paused = 0);
+ }
+
+ // tick
+ tick(delta) {
+ this.paused || this.updateQueue(delta);
+ }
+
+ // 更新 map 队列
+ updateQueue(delta) {
+ this.queue.forEach((item, id) => {
+ if(item.paused === 1) return;
+ item.elapsed += delta;
+ if(item.elapsed >= item.delay) {
+ item.fn();
+ item.type === 0 ? this.delete(id) : (item.elapsed = 0);
+ }
+ });
+ }
+
+ // 状态更新
+ update() {
+ // 第一次调用 update 时主动停用原生接口
+ this.useRAF = false;
+
+ // 下面是真正的 update
+ this.update = (paused, delta) => {
+ if(this.usingRAF) return;
+ // 播放开关
+ this.paused == paused || (this.paused = paused);
+ this.tick(delta);
+ }
+ }
+
+}
+
+class AnimationFrame {
+ constructor() {
+ this.time = 0;
+ this.auto = this.auto.bind(this);
+ }
+ auto(elapsed) {
+ timer.tick(elapsed - this.time);
+ this.time = elapsed;
+ this.id = requestAnimationFrame(this.auto);
+ }
+ enable() {
+ timer.paused = false;
+ this.id = requestAnimationFrame(this.auto);
+ }
+ disable() {
+ cancelAnimationFrame(this.id);
+ }
+}
+
+// 原生RAF
+Timer.RAF = new AnimationFrame();
+
+// 对外接口
+let timer = new Timer();
+
+// 默认使用原生 RAF
+timer.useRAF = true;
+// 导出timer
+export default timer;
diff --git a/h5/snake/snake.css b/h5/snake/snake.css
new file mode 100644
index 0000000..d99211f
--- /dev/null
+++ b/h5/snake/snake.css
@@ -0,0 +1,7 @@
+.snake {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ background-image: url(./bg.jpg);
+ background-size: cover;
+}
diff --git a/h5/snake/snake.js b/h5/snake/snake.js
new file mode 100644
index 0000000..287acc2
--- /dev/null
+++ b/h5/snake/snake.js
@@ -0,0 +1,106 @@
+import "./snake.css";
+import SnakeModel from "./core/model";
+
+// view
+import SnakeView from "./core/view";
+
+// control
+import SnakeControl from "./core/control";
+
+export default class SnakeClass extends SnakeControl {
+ constructor({ containerId, onLose }) {
+ const container = document.getElementById(containerId);
+ const width = container.clientWidth;
+ const row = 14;
+ const column = 18;
+ const height = (width / column) * row;
+ const bg = document.createElement("div");
+ bg.className = "snake";
+ bg.style.paddingTop = `${(240 / 2160) * width}px`;
+ container.appendChild(bg);
+
+ super(new SnakeModel(), new SnakeView(bg, width, height));
+
+ this.init({
+ time: 3000000, // 总时间
+ width,
+ height,
+ row,
+ column,
+ // 显示屏的边框
+ border: 0x414042,
+ color: 0x414042, // 蛇的节点颜色
+ food: 0x990000, // 食物的颜色
+ min: 4, // 初始长度
+ speed: 1.5, // 速度标量
+ });
+ this.event.on("gameover", onLose);
+ // snakeGame.event.on("eat", (food) => {
+ // console.log("吃到食物,当前长度: " + snakeGame.length);
+ // });
+ this.start();
+ }
+ dispose() {}
+ addControl() {
+ let controller = document.querySelector(".snake-direction"),
+ curDirection,
+ { top, left, width, height } = controller.getBoundingClientRect(),
+ x = left + width / 2,
+ y = top + height / 2,
+ deg45 = Math.PI / 4,
+ deg90 = Math.PI / 2,
+ deg135 = Math.PI / 2 + deg45,
+ deg180 = Math.PI,
+ deg225 = Math.PI + deg45,
+ deg270 = Math.PI + deg90,
+ deg315 = Math.PI * 2 - deg45;
+
+ controller.addEventListener(
+ "touchstart",
+ ({ targetTouches: [{ pageX, pageY }] }) => {
+ checkDirection(pageX - x, pageY - y);
+ }
+ );
+
+ controller.addEventListener(
+ "touchmove",
+ ({ targetTouches: [{ pageX, pageY }] }) => {
+ checkDirection(pageX - x, pageY - y);
+ }
+ );
+
+ controller.addEventListener(
+ "touchend",
+ ({ changedTouches: [{ pageX, pageY }] }) => {
+ curDirection = undefined;
+ controller.className = "snake-direction";
+ }
+ );
+
+ let checkDirection = function (x, y) {
+ let radian = Math.asin(y / Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
+ // 1~2象限
+ if ((x > 0 && y < 0) || (x > 0 && y > 0)) {
+ radian += deg90;
+ }
+ // 3~4象限
+ else if ((x < 0 && y > 0) || (x < 0 && y < 0)) {
+ radian = deg270 - radian;
+ }
+
+ let direction = "up";
+ if (radian > deg45 && radian < deg135) {
+ direction = "right";
+ } else if (radian > deg135 && radian < deg225) {
+ direction = "down";
+ } else if (radian > deg225 && radian < deg315) {
+ direction = "left";
+ }
+ direction === curDirection ||
+ snakeGame.turn(
+ (curDirection = direction),
+ (controller.className = "snake-direction " + direction)
+ );
+ };
+ }
+}
diff --git a/h5/snake/星星.png b/h5/snake/星星.png
new file mode 100644
index 0000000..6bf616a
Binary files /dev/null and b/h5/snake/星星.png differ
diff --git a/h5/snake/舌头.png b/h5/snake/舌头.png
new file mode 100644
index 0000000..d0cef76
Binary files /dev/null and b/h5/snake/舌头.png differ
diff --git a/h5/snake/苹果.png b/h5/snake/苹果.png
new file mode 100644
index 0000000..29a412b
Binary files /dev/null and b/h5/snake/苹果.png differ
diff --git a/h5/snake/蛇-原始状态.png b/h5/snake/蛇-原始状态.png
new file mode 100644
index 0000000..0cd7ab3
Binary files /dev/null and b/h5/snake/蛇-原始状态.png differ
diff --git a/h5/snake/蛇-张嘴.png b/h5/snake/蛇-张嘴.png
new file mode 100644
index 0000000..22db8ff
Binary files /dev/null and b/h5/snake/蛇-张嘴.png differ
diff --git a/h5/snake/蛇-张嘴一半.png b/h5/snake/蛇-张嘴一半.png
new file mode 100644
index 0000000..39fe5ef
Binary files /dev/null and b/h5/snake/蛇-张嘴一半.png differ
diff --git a/h5/snake/蛇-闭眼哭泣.png b/h5/snake/蛇-闭眼哭泣.png
new file mode 100644
index 0000000..b5b6ddd
Binary files /dev/null and b/h5/snake/蛇-闭眼哭泣.png differ
diff --git a/h5/snake/蛇整体效果.png b/h5/snake/蛇整体效果.png
new file mode 100644
index 0000000..0682ab0
Binary files /dev/null and b/h5/snake/蛇整体效果.png differ