particle-container.js 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /*!
  2. * @pixi/particle-container - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/particle-container is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. this.PIXI = this.PIXI || {};
  9. var _pixi_particle_container = (function (exports, constants, display, utils, core, math) {
  10. 'use strict';
  11. /*! *****************************************************************************
  12. Copyright (c) Microsoft Corporation.
  13. Permission to use, copy, modify, and/or distribute this software for any
  14. purpose with or without fee is hereby granted.
  15. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  16. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  17. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  18. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  19. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  20. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. PERFORMANCE OF THIS SOFTWARE.
  22. ***************************************************************************** */
  23. /* global Reflect, Promise */
  24. var extendStatics = function(d, b) {
  25. extendStatics = Object.setPrototypeOf ||
  26. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  27. function (d, b) { for (var p in b) { if (b.hasOwnProperty(p)) { d[p] = b[p]; } } };
  28. return extendStatics(d, b);
  29. };
  30. function __extends(d, b) {
  31. extendStatics(d, b);
  32. function __() { this.constructor = d; }
  33. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  34. }
  35. var __assign = function() {
  36. __assign = Object.assign || function __assign(t) {
  37. var arguments$1 = arguments;
  38. for (var s, i = 1, n = arguments.length; i < n; i++) {
  39. s = arguments$1[i];
  40. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p]; } }
  41. }
  42. return t;
  43. };
  44. return __assign.apply(this, arguments);
  45. };
  46. function __rest(s, e) {
  47. var t = {};
  48. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  49. { t[p] = s[p]; } }
  50. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  51. { for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  52. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  53. { t[p[i]] = s[p[i]]; }
  54. } }
  55. return t;
  56. }
  57. function __decorate(decorators, target, key, desc) {
  58. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  59. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") { r = Reflect.decorate(decorators, target, key, desc); }
  60. else { for (var i = decorators.length - 1; i >= 0; i--) { if (d = decorators[i]) { r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; } } }
  61. return c > 3 && r && Object.defineProperty(target, key, r), r;
  62. }
  63. function __param(paramIndex, decorator) {
  64. return function (target, key) { decorator(target, key, paramIndex); }
  65. }
  66. function __metadata(metadataKey, metadataValue) {
  67. if (typeof Reflect === "object" && typeof Reflect.metadata === "function") { return Reflect.metadata(metadataKey, metadataValue); }
  68. }
  69. function __awaiter(thisArg, _arguments, P, generator) {
  70. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  71. return new (P || (P = Promise))(function (resolve, reject) {
  72. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  73. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  74. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  75. step((generator = generator.apply(thisArg, _arguments || [])).next());
  76. });
  77. }
  78. function __generator(thisArg, body) {
  79. var _ = { label: 0, sent: function() { if (t[0] & 1) { throw t[1]; } return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  80. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  81. function verb(n) { return function (v) { return step([n, v]); }; }
  82. function step(op) {
  83. if (f) { throw new TypeError("Generator is already executing."); }
  84. while (_) { try {
  85. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) { return t; }
  86. if (y = 0, t) { op = [op[0] & 2, t.value]; }
  87. switch (op[0]) {
  88. case 0: case 1: t = op; break;
  89. case 4: _.label++; return { value: op[1], done: false };
  90. case 5: _.label++; y = op[1]; op = [0]; continue;
  91. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  92. default:
  93. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  94. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  95. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  96. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  97. if (t[2]) { _.ops.pop(); }
  98. _.trys.pop(); continue;
  99. }
  100. op = body.call(thisArg, _);
  101. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } }
  102. if (op[0] & 5) { throw op[1]; } return { value: op[0] ? op[1] : void 0, done: true };
  103. }
  104. }
  105. function __createBinding(o, m, k, k2) {
  106. if (k2 === undefined) { k2 = k; }
  107. o[k2] = m[k];
  108. }
  109. function __exportStar(m, exports) {
  110. for (var p in m) { if (p !== "default" && !exports.hasOwnProperty(p)) { exports[p] = m[p]; } }
  111. }
  112. function __values(o) {
  113. var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  114. if (m) { return m.call(o); }
  115. if (o && typeof o.length === "number") { return {
  116. next: function () {
  117. if (o && i >= o.length) { o = void 0; }
  118. return { value: o && o[i++], done: !o };
  119. }
  120. }; }
  121. throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
  122. }
  123. function __read(o, n) {
  124. var m = typeof Symbol === "function" && o[Symbol.iterator];
  125. if (!m) { return o; }
  126. var i = m.call(o), r, ar = [], e;
  127. try {
  128. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) { ar.push(r.value); }
  129. }
  130. catch (error) { e = { error: error }; }
  131. finally {
  132. try {
  133. if (r && !r.done && (m = i["return"])) { m.call(i); }
  134. }
  135. finally { if (e) { throw e.error; } }
  136. }
  137. return ar;
  138. }
  139. function __spread() {
  140. var arguments$1 = arguments;
  141. for (var ar = [], i = 0; i < arguments.length; i++)
  142. { ar = ar.concat(__read(arguments$1[i])); }
  143. return ar;
  144. }
  145. function __spreadArrays() {
  146. var arguments$1 = arguments;
  147. for (var s = 0, i = 0, il = arguments.length; i < il; i++) { s += arguments$1[i].length; }
  148. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  149. { for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  150. { r[k] = a[j]; } }
  151. return r;
  152. };
  153. function __await(v) {
  154. return this instanceof __await ? (this.v = v, this) : new __await(v);
  155. }
  156. function __asyncGenerator(thisArg, _arguments, generator) {
  157. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  158. var g = generator.apply(thisArg, _arguments || []), i, q = [];
  159. return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
  160. function verb(n) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } }
  161. function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
  162. function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
  163. function fulfill(value) { resume("next", value); }
  164. function reject(value) { resume("throw", value); }
  165. function settle(f, v) { if (f(v), q.shift(), q.length) { resume(q[0][0], q[0][1]); } }
  166. }
  167. function __asyncDelegator(o) {
  168. var i, p;
  169. return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
  170. function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
  171. }
  172. function __asyncValues(o) {
  173. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  174. var m = o[Symbol.asyncIterator], i;
  175. return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
  176. function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
  177. function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
  178. }
  179. function __makeTemplateObject(cooked, raw) {
  180. if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  181. return cooked;
  182. };
  183. function __importStar(mod) {
  184. if (mod && mod.__esModule) { return mod; }
  185. var result = {};
  186. if (mod != null) { for (var k in mod) { if (Object.hasOwnProperty.call(mod, k)) { result[k] = mod[k]; } } }
  187. result.default = mod;
  188. return result;
  189. }
  190. function __importDefault(mod) {
  191. return (mod && mod.__esModule) ? mod : { default: mod };
  192. }
  193. function __classPrivateFieldGet(receiver, privateMap) {
  194. if (!privateMap.has(receiver)) {
  195. throw new TypeError("attempted to get private field on non-instance");
  196. }
  197. return privateMap.get(receiver);
  198. }
  199. function __classPrivateFieldSet(receiver, privateMap, value) {
  200. if (!privateMap.has(receiver)) {
  201. throw new TypeError("attempted to set private field on non-instance");
  202. }
  203. privateMap.set(receiver, value);
  204. return value;
  205. }
  206. /**
  207. * The ParticleContainer class is a really fast version of the Container built solely for speed,
  208. * so use when you need a lot of sprites or particles.
  209. *
  210. * The tradeoff of the ParticleContainer is that most advanced functionality will not work.
  211. * ParticleContainer implements the basic object transform (position, scale, rotation)
  212. * and some advanced functionality like tint (as of v4.5.6).
  213. *
  214. * Other more advanced functionality like masking, children, filters, etc will not work on sprites in this batch.
  215. *
  216. * It's extremely easy to use:
  217. * ```js
  218. * let container = new ParticleContainer();
  219. *
  220. * for (let i = 0; i < 100; ++i)
  221. * {
  222. * let sprite = PIXI.Sprite.from("myImage.png");
  223. * container.addChild(sprite);
  224. * }
  225. * ```
  226. *
  227. * And here you have a hundred sprites that will be rendered at the speed of light.
  228. * @memberof PIXI
  229. */
  230. var ParticleContainer = /** @class */ (function (_super) {
  231. __extends(ParticleContainer, _super);
  232. /**
  233. * @param maxSize - The maximum number of particles that can be rendered by the container.
  234. * Affects size of allocated buffers.
  235. * @param properties - The properties of children that should be uploaded to the gpu and applied.
  236. * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied.
  237. * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`.
  238. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied.
  239. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied.
  240. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied.
  241. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied.
  242. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead.
  243. * @param {boolean} [autoResize=false] - If true, container allocates more batches in case
  244. * there are more than `maxSize` particles.
  245. */
  246. function ParticleContainer(maxSize, properties, batchSize, autoResize) {
  247. if (maxSize === void 0) { maxSize = 1500; }
  248. if (batchSize === void 0) { batchSize = 16384; }
  249. if (autoResize === void 0) { autoResize = false; }
  250. var _this = _super.call(this) || this;
  251. // Making sure the batch size is valid
  252. // 65535 is max vertex index in the index buffer (see ParticleRenderer)
  253. // so max number of particles is 65536 / 4 = 16384
  254. var maxBatchSize = 16384;
  255. if (batchSize > maxBatchSize) {
  256. batchSize = maxBatchSize;
  257. }
  258. _this._properties = [false, true, false, false, false];
  259. _this._maxSize = maxSize;
  260. _this._batchSize = batchSize;
  261. _this._buffers = null;
  262. _this._bufferUpdateIDs = [];
  263. _this._updateID = 0;
  264. _this.interactiveChildren = false;
  265. _this.blendMode = constants.BLEND_MODES.NORMAL;
  266. _this.autoResize = autoResize;
  267. _this.roundPixels = true;
  268. _this.baseTexture = null;
  269. _this.setProperties(properties);
  270. _this._tint = 0;
  271. _this.tintRgb = new Float32Array(4);
  272. _this.tint = 0xFFFFFF;
  273. return _this;
  274. }
  275. /**
  276. * Sets the private properties array to dynamic / static based on the passed properties object
  277. * @param properties - The properties to be uploaded
  278. */
  279. ParticleContainer.prototype.setProperties = function (properties) {
  280. if (properties) {
  281. this._properties[0] = 'vertices' in properties || 'scale' in properties
  282. ? !!properties.vertices || !!properties.scale : this._properties[0];
  283. this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1];
  284. this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2];
  285. this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3];
  286. this._properties[4] = 'tint' in properties || 'alpha' in properties
  287. ? !!properties.tint || !!properties.alpha : this._properties[4];
  288. }
  289. };
  290. ParticleContainer.prototype.updateTransform = function () {
  291. // TODO don't need to!
  292. this.displayObjectUpdateTransform();
  293. };
  294. Object.defineProperty(ParticleContainer.prototype, "tint", {
  295. /**
  296. * The tint applied to the container. This is a hex value.
  297. * A value of 0xFFFFFF will remove any tint effect.
  298. * IMPORTANT: This is a WebGL only feature and will be ignored by the canvas renderer.
  299. * @default 0xFFFFFF
  300. */
  301. get: function () {
  302. return this._tint;
  303. },
  304. set: function (value) {
  305. this._tint = value;
  306. utils.hex2rgb(value, this.tintRgb);
  307. },
  308. enumerable: false,
  309. configurable: true
  310. });
  311. /**
  312. * Renders the container using the WebGL renderer.
  313. * @param renderer - The WebGL renderer.
  314. */
  315. ParticleContainer.prototype.render = function (renderer) {
  316. var _this = this;
  317. if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) {
  318. return;
  319. }
  320. if (!this.baseTexture) {
  321. this.baseTexture = this.children[0]._texture.baseTexture;
  322. if (!this.baseTexture.valid) {
  323. this.baseTexture.once('update', function () { return _this.onChildrenChange(0); });
  324. }
  325. }
  326. renderer.batch.setObjectRenderer(renderer.plugins.particle);
  327. renderer.plugins.particle.render(this);
  328. };
  329. /**
  330. * Set the flag that static data should be updated to true
  331. * @param smallestChildIndex - The smallest child index.
  332. */
  333. ParticleContainer.prototype.onChildrenChange = function (smallestChildIndex) {
  334. var bufferIndex = Math.floor(smallestChildIndex / this._batchSize);
  335. while (this._bufferUpdateIDs.length < bufferIndex) {
  336. this._bufferUpdateIDs.push(0);
  337. }
  338. this._bufferUpdateIDs[bufferIndex] = ++this._updateID;
  339. };
  340. ParticleContainer.prototype.dispose = function () {
  341. if (this._buffers) {
  342. for (var i = 0; i < this._buffers.length; ++i) {
  343. this._buffers[i].destroy();
  344. }
  345. this._buffers = null;
  346. }
  347. };
  348. /**
  349. * Destroys the container
  350. * @param options - Options parameter. A boolean will act as if all options
  351. * have been set to that value
  352. * @param {boolean} [options.children=false] - if set to true, all the children will have their
  353. * destroy method called as well. 'options' will be passed on to those calls.
  354. * @param {boolean} [options.texture=false] - Only used for child Sprites if options.children is set to true
  355. * Should it destroy the texture of the child sprite
  356. * @param {boolean} [options.baseTexture=false] - Only used for child Sprites if options.children is set to true
  357. * Should it destroy the base texture of the child sprite
  358. */
  359. ParticleContainer.prototype.destroy = function (options) {
  360. _super.prototype.destroy.call(this, options);
  361. this.dispose();
  362. this._properties = null;
  363. this._buffers = null;
  364. this._bufferUpdateIDs = null;
  365. };
  366. return ParticleContainer;
  367. }(display.Container));
  368. /*
  369. * @author Mat Groves
  370. *
  371. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  372. * for creating the original PixiJS version!
  373. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that
  374. * they now share 4 bytes on the vertex buffer
  375. *
  376. * Heavily inspired by LibGDX's ParticleBuffer:
  377. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java
  378. */
  379. /**
  380. * The particle buffer manages the static and dynamic buffers for a particle container.
  381. * @private
  382. * @memberof PIXI
  383. */
  384. var ParticleBuffer = /** @class */ (function () {
  385. /**
  386. * @param {object} properties - The properties to upload.
  387. * @param {boolean[]} dynamicPropertyFlags - Flags for which properties are dynamic.
  388. * @param {number} size - The size of the batch.
  389. */
  390. function ParticleBuffer(properties, dynamicPropertyFlags, size) {
  391. this.geometry = new core.Geometry();
  392. this.indexBuffer = null;
  393. this.size = size;
  394. this.dynamicProperties = [];
  395. this.staticProperties = [];
  396. for (var i = 0; i < properties.length; ++i) {
  397. var property = properties[i];
  398. // Make copy of properties object so that when we edit the offset it doesn't
  399. // change all other instances of the object literal
  400. property = {
  401. attributeName: property.attributeName,
  402. size: property.size,
  403. uploadFunction: property.uploadFunction,
  404. type: property.type || constants.TYPES.FLOAT,
  405. offset: property.offset,
  406. };
  407. if (dynamicPropertyFlags[i]) {
  408. this.dynamicProperties.push(property);
  409. }
  410. else {
  411. this.staticProperties.push(property);
  412. }
  413. }
  414. this.staticStride = 0;
  415. this.staticBuffer = null;
  416. this.staticData = null;
  417. this.staticDataUint32 = null;
  418. this.dynamicStride = 0;
  419. this.dynamicBuffer = null;
  420. this.dynamicData = null;
  421. this.dynamicDataUint32 = null;
  422. this._updateID = 0;
  423. this.initBuffers();
  424. }
  425. /** Sets up the renderer context and necessary buffers. */
  426. ParticleBuffer.prototype.initBuffers = function () {
  427. var geometry = this.geometry;
  428. var dynamicOffset = 0;
  429. this.indexBuffer = new core.Buffer(utils.createIndicesForQuads(this.size), true, true);
  430. geometry.addIndex(this.indexBuffer);
  431. this.dynamicStride = 0;
  432. for (var i = 0; i < this.dynamicProperties.length; ++i) {
  433. var property = this.dynamicProperties[i];
  434. property.offset = dynamicOffset;
  435. dynamicOffset += property.size;
  436. this.dynamicStride += property.size;
  437. }
  438. var dynBuffer = new ArrayBuffer(this.size * this.dynamicStride * 4 * 4);
  439. this.dynamicData = new Float32Array(dynBuffer);
  440. this.dynamicDataUint32 = new Uint32Array(dynBuffer);
  441. this.dynamicBuffer = new core.Buffer(this.dynamicData, false, false);
  442. // static //
  443. var staticOffset = 0;
  444. this.staticStride = 0;
  445. for (var i = 0; i < this.staticProperties.length; ++i) {
  446. var property = this.staticProperties[i];
  447. property.offset = staticOffset;
  448. staticOffset += property.size;
  449. this.staticStride += property.size;
  450. }
  451. var statBuffer = new ArrayBuffer(this.size * this.staticStride * 4 * 4);
  452. this.staticData = new Float32Array(statBuffer);
  453. this.staticDataUint32 = new Uint32Array(statBuffer);
  454. this.staticBuffer = new core.Buffer(this.staticData, true, false);
  455. for (var i = 0; i < this.dynamicProperties.length; ++i) {
  456. var property = this.dynamicProperties[i];
  457. geometry.addAttribute(property.attributeName, this.dynamicBuffer, 0, property.type === constants.TYPES.UNSIGNED_BYTE, property.type, this.dynamicStride * 4, property.offset * 4);
  458. }
  459. for (var i = 0; i < this.staticProperties.length; ++i) {
  460. var property = this.staticProperties[i];
  461. geometry.addAttribute(property.attributeName, this.staticBuffer, 0, property.type === constants.TYPES.UNSIGNED_BYTE, property.type, this.staticStride * 4, property.offset * 4);
  462. }
  463. };
  464. /**
  465. * Uploads the dynamic properties.
  466. * @param children - The children to upload.
  467. * @param startIndex - The index to start at.
  468. * @param amount - The number to upload.
  469. */
  470. ParticleBuffer.prototype.uploadDynamic = function (children, startIndex, amount) {
  471. for (var i = 0; i < this.dynamicProperties.length; i++) {
  472. var property = this.dynamicProperties[i];
  473. property.uploadFunction(children, startIndex, amount, property.type === constants.TYPES.UNSIGNED_BYTE ? this.dynamicDataUint32 : this.dynamicData, this.dynamicStride, property.offset);
  474. }
  475. this.dynamicBuffer._updateID++;
  476. };
  477. /**
  478. * Uploads the static properties.
  479. * @param children - The children to upload.
  480. * @param startIndex - The index to start at.
  481. * @param amount - The number to upload.
  482. */
  483. ParticleBuffer.prototype.uploadStatic = function (children, startIndex, amount) {
  484. for (var i = 0; i < this.staticProperties.length; i++) {
  485. var property = this.staticProperties[i];
  486. property.uploadFunction(children, startIndex, amount, property.type === constants.TYPES.UNSIGNED_BYTE ? this.staticDataUint32 : this.staticData, this.staticStride, property.offset);
  487. }
  488. this.staticBuffer._updateID++;
  489. };
  490. /** Destroys the ParticleBuffer. */
  491. ParticleBuffer.prototype.destroy = function () {
  492. this.indexBuffer = null;
  493. this.dynamicProperties = null;
  494. this.dynamicBuffer = null;
  495. this.dynamicData = null;
  496. this.dynamicDataUint32 = null;
  497. this.staticProperties = null;
  498. this.staticBuffer = null;
  499. this.staticData = null;
  500. this.staticDataUint32 = null;
  501. // all buffers are destroyed inside geometry
  502. this.geometry.destroy();
  503. };
  504. return ParticleBuffer;
  505. }());
  506. var fragment = "varying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nvoid main(void){\n vec4 color = texture2D(uSampler, vTextureCoord) * vColor;\n gl_FragColor = color;\n}";
  507. var vertex = "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nattribute vec2 aPositionCoord;\nattribute float aRotation;\n\nuniform mat3 translationMatrix;\nuniform vec4 uColor;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void){\n float x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);\n float y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);\n\n vec2 v = vec2(x, y);\n v = v + aPositionCoord;\n\n gl_Position = vec4((translationMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n vColor = aColor * uColor;\n}\n";
  508. /*
  509. * @author Mat Groves
  510. *
  511. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  512. * for creating the original PixiJS version!
  513. * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now
  514. * share 4 bytes on the vertex buffer
  515. *
  516. * Heavily inspired by LibGDX's ParticleRenderer:
  517. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleRenderer.java
  518. */
  519. /**
  520. * Renderer for Particles that is designer for speed over feature set.
  521. * @memberof PIXI
  522. */
  523. var ParticleRenderer = /** @class */ (function (_super) {
  524. __extends(ParticleRenderer, _super);
  525. /**
  526. * @param renderer - The renderer this sprite batch works for.
  527. */
  528. function ParticleRenderer(renderer) {
  529. var _this = _super.call(this, renderer) || this;
  530. // 65535 is max vertex index in the index buffer (see ParticleRenderer)
  531. // so max number of particles is 65536 / 4 = 16384
  532. // and max number of element in the index buffer is 16384 * 6 = 98304
  533. // Creating a full index buffer, overhead is 98304 * 2 = 196Ko
  534. // let numIndices = 98304;
  535. _this.shader = null;
  536. _this.properties = null;
  537. _this.tempMatrix = new math.Matrix();
  538. _this.properties = [
  539. // verticesData
  540. {
  541. attributeName: 'aVertexPosition',
  542. size: 2,
  543. uploadFunction: _this.uploadVertices,
  544. offset: 0,
  545. },
  546. // positionData
  547. {
  548. attributeName: 'aPositionCoord',
  549. size: 2,
  550. uploadFunction: _this.uploadPosition,
  551. offset: 0,
  552. },
  553. // rotationData
  554. {
  555. attributeName: 'aRotation',
  556. size: 1,
  557. uploadFunction: _this.uploadRotation,
  558. offset: 0,
  559. },
  560. // uvsData
  561. {
  562. attributeName: 'aTextureCoord',
  563. size: 2,
  564. uploadFunction: _this.uploadUvs,
  565. offset: 0,
  566. },
  567. // tintData
  568. {
  569. attributeName: 'aColor',
  570. size: 1,
  571. type: constants.TYPES.UNSIGNED_BYTE,
  572. uploadFunction: _this.uploadTint,
  573. offset: 0,
  574. } ];
  575. _this.shader = core.Shader.from(vertex, fragment, {});
  576. _this.state = core.State.for2d();
  577. return _this;
  578. }
  579. /**
  580. * Renders the particle container object.
  581. * @param container - The container to render using this ParticleRenderer.
  582. */
  583. ParticleRenderer.prototype.render = function (container) {
  584. var children = container.children;
  585. var maxSize = container._maxSize;
  586. var batchSize = container._batchSize;
  587. var renderer = this.renderer;
  588. var totalChildren = children.length;
  589. if (totalChildren === 0) {
  590. return;
  591. }
  592. else if (totalChildren > maxSize && !container.autoResize) {
  593. totalChildren = maxSize;
  594. }
  595. var buffers = container._buffers;
  596. if (!buffers) {
  597. buffers = container._buffers = this.generateBuffers(container);
  598. }
  599. var baseTexture = children[0]._texture.baseTexture;
  600. var premultiplied = baseTexture.alphaMode > 0;
  601. // if the uvs have not updated then no point rendering just yet!
  602. this.state.blendMode = utils.correctBlendMode(container.blendMode, premultiplied);
  603. renderer.state.set(this.state);
  604. var gl = renderer.gl;
  605. var m = container.worldTransform.copyTo(this.tempMatrix);
  606. m.prepend(renderer.globalUniforms.uniforms.projectionMatrix);
  607. this.shader.uniforms.translationMatrix = m.toArray(true);
  608. this.shader.uniforms.uColor = utils.premultiplyRgba(container.tintRgb, container.worldAlpha, this.shader.uniforms.uColor, premultiplied);
  609. this.shader.uniforms.uSampler = baseTexture;
  610. this.renderer.shader.bind(this.shader);
  611. var updateStatic = false;
  612. // now lets upload and render the buffers..
  613. for (var i = 0, j = 0; i < totalChildren; i += batchSize, j += 1) {
  614. var amount = (totalChildren - i);
  615. if (amount > batchSize) {
  616. amount = batchSize;
  617. }
  618. if (j >= buffers.length) {
  619. buffers.push(this._generateOneMoreBuffer(container));
  620. }
  621. var buffer = buffers[j];
  622. // we always upload the dynamic
  623. buffer.uploadDynamic(children, i, amount);
  624. var bid = container._bufferUpdateIDs[j] || 0;
  625. updateStatic = updateStatic || (buffer._updateID < bid);
  626. // we only upload the static content when we have to!
  627. if (updateStatic) {
  628. buffer._updateID = container._updateID;
  629. buffer.uploadStatic(children, i, amount);
  630. }
  631. // bind the buffer
  632. renderer.geometry.bind(buffer.geometry);
  633. gl.drawElements(gl.TRIANGLES, amount * 6, gl.UNSIGNED_SHORT, 0);
  634. }
  635. };
  636. /**
  637. * Creates one particle buffer for each child in the container we want to render and updates internal properties.
  638. * @param container - The container to render using this ParticleRenderer
  639. * @returns - The buffers
  640. */
  641. ParticleRenderer.prototype.generateBuffers = function (container) {
  642. var buffers = [];
  643. var size = container._maxSize;
  644. var batchSize = container._batchSize;
  645. var dynamicPropertyFlags = container._properties;
  646. for (var i = 0; i < size; i += batchSize) {
  647. buffers.push(new ParticleBuffer(this.properties, dynamicPropertyFlags, batchSize));
  648. }
  649. return buffers;
  650. };
  651. /**
  652. * Creates one more particle buffer, because container has autoResize feature.
  653. * @param container - The container to render using this ParticleRenderer
  654. * @returns - The generated buffer
  655. */
  656. ParticleRenderer.prototype._generateOneMoreBuffer = function (container) {
  657. var batchSize = container._batchSize;
  658. var dynamicPropertyFlags = container._properties;
  659. return new ParticleBuffer(this.properties, dynamicPropertyFlags, batchSize);
  660. };
  661. /**
  662. * Uploads the vertices.
  663. * @param children - the array of sprites to render
  664. * @param startIndex - the index to start from in the children array
  665. * @param amount - the amount of children that will have their vertices uploaded
  666. * @param array - The vertices to upload.
  667. * @param stride - Stride to use for iteration.
  668. * @param offset - Offset to start at.
  669. */
  670. ParticleRenderer.prototype.uploadVertices = function (children, startIndex, amount, array, stride, offset) {
  671. var w0 = 0;
  672. var w1 = 0;
  673. var h0 = 0;
  674. var h1 = 0;
  675. for (var i = 0; i < amount; ++i) {
  676. var sprite = children[startIndex + i];
  677. var texture = sprite._texture;
  678. var sx = sprite.scale.x;
  679. var sy = sprite.scale.y;
  680. var trim = texture.trim;
  681. var orig = texture.orig;
  682. if (trim) {
  683. // if the sprite is trimmed and is not a tilingsprite then we need to add the
  684. // extra space before transforming the sprite coords..
  685. w1 = trim.x - (sprite.anchor.x * orig.width);
  686. w0 = w1 + trim.width;
  687. h1 = trim.y - (sprite.anchor.y * orig.height);
  688. h0 = h1 + trim.height;
  689. }
  690. else {
  691. w0 = (orig.width) * (1 - sprite.anchor.x);
  692. w1 = (orig.width) * -sprite.anchor.x;
  693. h0 = orig.height * (1 - sprite.anchor.y);
  694. h1 = orig.height * -sprite.anchor.y;
  695. }
  696. array[offset] = w1 * sx;
  697. array[offset + 1] = h1 * sy;
  698. array[offset + stride] = w0 * sx;
  699. array[offset + stride + 1] = h1 * sy;
  700. array[offset + (stride * 2)] = w0 * sx;
  701. array[offset + (stride * 2) + 1] = h0 * sy;
  702. array[offset + (stride * 3)] = w1 * sx;
  703. array[offset + (stride * 3) + 1] = h0 * sy;
  704. offset += stride * 4;
  705. }
  706. };
  707. /**
  708. * Uploads the position.
  709. * @param children - the array of sprites to render
  710. * @param startIndex - the index to start from in the children array
  711. * @param amount - the amount of children that will have their positions uploaded
  712. * @param array - The vertices to upload.
  713. * @param stride - Stride to use for iteration.
  714. * @param offset - Offset to start at.
  715. */
  716. ParticleRenderer.prototype.uploadPosition = function (children, startIndex, amount, array, stride, offset) {
  717. for (var i = 0; i < amount; i++) {
  718. var spritePosition = children[startIndex + i].position;
  719. array[offset] = spritePosition.x;
  720. array[offset + 1] = spritePosition.y;
  721. array[offset + stride] = spritePosition.x;
  722. array[offset + stride + 1] = spritePosition.y;
  723. array[offset + (stride * 2)] = spritePosition.x;
  724. array[offset + (stride * 2) + 1] = spritePosition.y;
  725. array[offset + (stride * 3)] = spritePosition.x;
  726. array[offset + (stride * 3) + 1] = spritePosition.y;
  727. offset += stride * 4;
  728. }
  729. };
  730. /**
  731. * Uploads the rotation.
  732. * @param children - the array of sprites to render
  733. * @param startIndex - the index to start from in the children array
  734. * @param amount - the amount of children that will have their rotation uploaded
  735. * @param array - The vertices to upload.
  736. * @param stride - Stride to use for iteration.
  737. * @param offset - Offset to start at.
  738. */
  739. ParticleRenderer.prototype.uploadRotation = function (children, startIndex, amount, array, stride, offset) {
  740. for (var i = 0; i < amount; i++) {
  741. var spriteRotation = children[startIndex + i].rotation;
  742. array[offset] = spriteRotation;
  743. array[offset + stride] = spriteRotation;
  744. array[offset + (stride * 2)] = spriteRotation;
  745. array[offset + (stride * 3)] = spriteRotation;
  746. offset += stride * 4;
  747. }
  748. };
  749. /**
  750. * Uploads the UVs.
  751. * @param children - the array of sprites to render
  752. * @param startIndex - the index to start from in the children array
  753. * @param amount - the amount of children that will have their rotation uploaded
  754. * @param array - The vertices to upload.
  755. * @param stride - Stride to use for iteration.
  756. * @param offset - Offset to start at.
  757. */
  758. ParticleRenderer.prototype.uploadUvs = function (children, startIndex, amount, array, stride, offset) {
  759. for (var i = 0; i < amount; ++i) {
  760. var textureUvs = children[startIndex + i]._texture._uvs;
  761. if (textureUvs) {
  762. array[offset] = textureUvs.x0;
  763. array[offset + 1] = textureUvs.y0;
  764. array[offset + stride] = textureUvs.x1;
  765. array[offset + stride + 1] = textureUvs.y1;
  766. array[offset + (stride * 2)] = textureUvs.x2;
  767. array[offset + (stride * 2) + 1] = textureUvs.y2;
  768. array[offset + (stride * 3)] = textureUvs.x3;
  769. array[offset + (stride * 3) + 1] = textureUvs.y3;
  770. offset += stride * 4;
  771. }
  772. else {
  773. // TODO you know this can be easier!
  774. array[offset] = 0;
  775. array[offset + 1] = 0;
  776. array[offset + stride] = 0;
  777. array[offset + stride + 1] = 0;
  778. array[offset + (stride * 2)] = 0;
  779. array[offset + (stride * 2) + 1] = 0;
  780. array[offset + (stride * 3)] = 0;
  781. array[offset + (stride * 3) + 1] = 0;
  782. offset += stride * 4;
  783. }
  784. }
  785. };
  786. /**
  787. * Uploads the tint.
  788. * @param children - the array of sprites to render
  789. * @param startIndex - the index to start from in the children array
  790. * @param amount - the amount of children that will have their rotation uploaded
  791. * @param array - The vertices to upload.
  792. * @param stride - Stride to use for iteration.
  793. * @param offset - Offset to start at.
  794. */
  795. ParticleRenderer.prototype.uploadTint = function (children, startIndex, amount, array, stride, offset) {
  796. for (var i = 0; i < amount; ++i) {
  797. var sprite = children[startIndex + i];
  798. var premultiplied = sprite._texture.baseTexture.alphaMode > 0;
  799. var alpha = sprite.alpha;
  800. // we dont call extra function if alpha is 1.0, that's faster
  801. var argb = alpha < 1.0 && premultiplied
  802. ? utils.premultiplyTint(sprite._tintRGB, alpha) : sprite._tintRGB + (alpha * 255 << 24);
  803. array[offset] = argb;
  804. array[offset + stride] = argb;
  805. array[offset + (stride * 2)] = argb;
  806. array[offset + (stride * 3)] = argb;
  807. offset += stride * 4;
  808. }
  809. };
  810. /** Destroys the ParticleRenderer. */
  811. ParticleRenderer.prototype.destroy = function () {
  812. _super.prototype.destroy.call(this);
  813. if (this.shader) {
  814. this.shader.destroy();
  815. this.shader = null;
  816. }
  817. this.tempMatrix = null;
  818. };
  819. /** @ignore */
  820. ParticleRenderer.extension = {
  821. name: 'particle',
  822. type: core.ExtensionType.RendererPlugin,
  823. };
  824. return ParticleRenderer;
  825. }(core.ObjectRenderer));
  826. exports.ParticleContainer = ParticleContainer;
  827. exports.ParticleRenderer = ParticleRenderer;
  828. Object.defineProperty(exports, '__esModule', { value: true });
  829. return exports;
  830. })({}, PIXI, PIXI, PIXI.utils, PIXI, PIXI);
  831. Object.assign(this.PIXI, _pixi_particle_container);
  832. //# sourceMappingURL=particle-container.js.map