prepare.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /*!
  2. * @pixi/prepare - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/prepare is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. this.PIXI = this.PIXI || {};
  9. var _pixi_prepare = (function (exports, settings, core, graphics, ticker, display, text, utils) {
  10. 'use strict';
  11. /**
  12. * Default number of uploads per frame using prepare plugin.
  13. * @static
  14. * @memberof PIXI.settings
  15. * @name UPLOADS_PER_FRAME
  16. * @type {number}
  17. * @default 4
  18. */
  19. settings.settings.UPLOADS_PER_FRAME = 4;
  20. /*! *****************************************************************************
  21. Copyright (c) Microsoft Corporation.
  22. Permission to use, copy, modify, and/or distribute this software for any
  23. purpose with or without fee is hereby granted.
  24. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  25. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  26. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  27. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  28. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  29. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  30. PERFORMANCE OF THIS SOFTWARE.
  31. ***************************************************************************** */
  32. /* global Reflect, Promise */
  33. var extendStatics = function(d, b) {
  34. extendStatics = Object.setPrototypeOf ||
  35. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  36. function (d, b) { for (var p in b) { if (b.hasOwnProperty(p)) { d[p] = b[p]; } } };
  37. return extendStatics(d, b);
  38. };
  39. function __extends(d, b) {
  40. extendStatics(d, b);
  41. function __() { this.constructor = d; }
  42. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  43. }
  44. var __assign = function() {
  45. __assign = Object.assign || function __assign(t) {
  46. var arguments$1 = arguments;
  47. for (var s, i = 1, n = arguments.length; i < n; i++) {
  48. s = arguments$1[i];
  49. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p]; } }
  50. }
  51. return t;
  52. };
  53. return __assign.apply(this, arguments);
  54. };
  55. function __rest(s, e) {
  56. var t = {};
  57. for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  58. { t[p] = s[p]; } }
  59. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  60. { for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  61. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  62. { t[p[i]] = s[p[i]]; }
  63. } }
  64. return t;
  65. }
  66. function __decorate(decorators, target, key, desc) {
  67. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  68. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") { r = Reflect.decorate(decorators, target, key, desc); }
  69. 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; } } }
  70. return c > 3 && r && Object.defineProperty(target, key, r), r;
  71. }
  72. function __param(paramIndex, decorator) {
  73. return function (target, key) { decorator(target, key, paramIndex); }
  74. }
  75. function __metadata(metadataKey, metadataValue) {
  76. if (typeof Reflect === "object" && typeof Reflect.metadata === "function") { return Reflect.metadata(metadataKey, metadataValue); }
  77. }
  78. function __awaiter(thisArg, _arguments, P, generator) {
  79. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  80. return new (P || (P = Promise))(function (resolve, reject) {
  81. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  82. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  83. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  84. step((generator = generator.apply(thisArg, _arguments || [])).next());
  85. });
  86. }
  87. function __generator(thisArg, body) {
  88. var _ = { label: 0, sent: function() { if (t[0] & 1) { throw t[1]; } return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  89. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  90. function verb(n) { return function (v) { return step([n, v]); }; }
  91. function step(op) {
  92. if (f) { throw new TypeError("Generator is already executing."); }
  93. while (_) { try {
  94. 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; }
  95. if (y = 0, t) { op = [op[0] & 2, t.value]; }
  96. switch (op[0]) {
  97. case 0: case 1: t = op; break;
  98. case 4: _.label++; return { value: op[1], done: false };
  99. case 5: _.label++; y = op[1]; op = [0]; continue;
  100. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  101. default:
  102. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  103. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  104. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  105. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  106. if (t[2]) { _.ops.pop(); }
  107. _.trys.pop(); continue;
  108. }
  109. op = body.call(thisArg, _);
  110. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } }
  111. if (op[0] & 5) { throw op[1]; } return { value: op[0] ? op[1] : void 0, done: true };
  112. }
  113. }
  114. function __createBinding(o, m, k, k2) {
  115. if (k2 === undefined) { k2 = k; }
  116. o[k2] = m[k];
  117. }
  118. function __exportStar(m, exports) {
  119. for (var p in m) { if (p !== "default" && !exports.hasOwnProperty(p)) { exports[p] = m[p]; } }
  120. }
  121. function __values(o) {
  122. var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  123. if (m) { return m.call(o); }
  124. if (o && typeof o.length === "number") { return {
  125. next: function () {
  126. if (o && i >= o.length) { o = void 0; }
  127. return { value: o && o[i++], done: !o };
  128. }
  129. }; }
  130. throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
  131. }
  132. function __read(o, n) {
  133. var m = typeof Symbol === "function" && o[Symbol.iterator];
  134. if (!m) { return o; }
  135. var i = m.call(o), r, ar = [], e;
  136. try {
  137. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) { ar.push(r.value); }
  138. }
  139. catch (error) { e = { error: error }; }
  140. finally {
  141. try {
  142. if (r && !r.done && (m = i["return"])) { m.call(i); }
  143. }
  144. finally { if (e) { throw e.error; } }
  145. }
  146. return ar;
  147. }
  148. function __spread() {
  149. var arguments$1 = arguments;
  150. for (var ar = [], i = 0; i < arguments.length; i++)
  151. { ar = ar.concat(__read(arguments$1[i])); }
  152. return ar;
  153. }
  154. function __spreadArrays() {
  155. var arguments$1 = arguments;
  156. for (var s = 0, i = 0, il = arguments.length; i < il; i++) { s += arguments$1[i].length; }
  157. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  158. { for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  159. { r[k] = a[j]; } }
  160. return r;
  161. };
  162. function __await(v) {
  163. return this instanceof __await ? (this.v = v, this) : new __await(v);
  164. }
  165. function __asyncGenerator(thisArg, _arguments, generator) {
  166. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  167. var g = generator.apply(thisArg, _arguments || []), i, q = [];
  168. return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
  169. 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); }); }; } }
  170. function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
  171. function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
  172. function fulfill(value) { resume("next", value); }
  173. function reject(value) { resume("throw", value); }
  174. function settle(f, v) { if (f(v), q.shift(), q.length) { resume(q[0][0], q[0][1]); } }
  175. }
  176. function __asyncDelegator(o) {
  177. var i, p;
  178. return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
  179. 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; }
  180. }
  181. function __asyncValues(o) {
  182. if (!Symbol.asyncIterator) { throw new TypeError("Symbol.asyncIterator is not defined."); }
  183. var m = o[Symbol.asyncIterator], i;
  184. 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);
  185. 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); }); }; }
  186. function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
  187. }
  188. function __makeTemplateObject(cooked, raw) {
  189. if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  190. return cooked;
  191. };
  192. function __importStar(mod) {
  193. if (mod && mod.__esModule) { return mod; }
  194. var result = {};
  195. if (mod != null) { for (var k in mod) { if (Object.hasOwnProperty.call(mod, k)) { result[k] = mod[k]; } } }
  196. result.default = mod;
  197. return result;
  198. }
  199. function __importDefault(mod) {
  200. return (mod && mod.__esModule) ? mod : { default: mod };
  201. }
  202. function __classPrivateFieldGet(receiver, privateMap) {
  203. if (!privateMap.has(receiver)) {
  204. throw new TypeError("attempted to get private field on non-instance");
  205. }
  206. return privateMap.get(receiver);
  207. }
  208. function __classPrivateFieldSet(receiver, privateMap, value) {
  209. if (!privateMap.has(receiver)) {
  210. throw new TypeError("attempted to set private field on non-instance");
  211. }
  212. privateMap.set(receiver, value);
  213. return value;
  214. }
  215. /**
  216. * CountLimiter limits the number of items handled by a {@link PIXI.BasePrepare} to a specified
  217. * number of items per frame.
  218. * @memberof PIXI
  219. */
  220. var CountLimiter = /** @class */ (function () {
  221. /**
  222. * @param maxItemsPerFrame - The maximum number of items that can be prepared each frame.
  223. */
  224. function CountLimiter(maxItemsPerFrame) {
  225. this.maxItemsPerFrame = maxItemsPerFrame;
  226. this.itemsLeft = 0;
  227. }
  228. /** Resets any counting properties to start fresh on a new frame. */
  229. CountLimiter.prototype.beginFrame = function () {
  230. this.itemsLeft = this.maxItemsPerFrame;
  231. };
  232. /**
  233. * Checks to see if another item can be uploaded. This should only be called once per item.
  234. * @returns If the item is allowed to be uploaded.
  235. */
  236. CountLimiter.prototype.allowedToUpload = function () {
  237. return this.itemsLeft-- > 0;
  238. };
  239. return CountLimiter;
  240. }());
  241. /**
  242. * Built-in hook to find multiple textures from objects like AnimatedSprites.
  243. * @private
  244. * @param item - Display object to check
  245. * @param queue - Collection of items to upload
  246. * @returns If a PIXI.Texture object was found.
  247. */
  248. function findMultipleBaseTextures(item, queue) {
  249. var result = false;
  250. // Objects with multiple textures
  251. if (item && item._textures && item._textures.length) {
  252. for (var i = 0; i < item._textures.length; i++) {
  253. if (item._textures[i] instanceof core.Texture) {
  254. var baseTexture = item._textures[i].baseTexture;
  255. if (queue.indexOf(baseTexture) === -1) {
  256. queue.push(baseTexture);
  257. result = true;
  258. }
  259. }
  260. }
  261. }
  262. return result;
  263. }
  264. /**
  265. * Built-in hook to find BaseTextures from Texture.
  266. * @private
  267. * @param item - Display object to check
  268. * @param queue - Collection of items to upload
  269. * @returns If a PIXI.Texture object was found.
  270. */
  271. function findBaseTexture(item, queue) {
  272. if (item.baseTexture instanceof core.BaseTexture) {
  273. var texture = item.baseTexture;
  274. if (queue.indexOf(texture) === -1) {
  275. queue.push(texture);
  276. }
  277. return true;
  278. }
  279. return false;
  280. }
  281. /**
  282. * Built-in hook to find textures from objects.
  283. * @private
  284. * @param item - Display object to check
  285. * @param queue - Collection of items to upload
  286. * @returns If a PIXI.Texture object was found.
  287. */
  288. function findTexture(item, queue) {
  289. if (item._texture && item._texture instanceof core.Texture) {
  290. var texture = item._texture.baseTexture;
  291. if (queue.indexOf(texture) === -1) {
  292. queue.push(texture);
  293. }
  294. return true;
  295. }
  296. return false;
  297. }
  298. /**
  299. * Built-in hook to draw PIXI.Text to its texture.
  300. * @private
  301. * @param _helper - Not used by this upload handler
  302. * @param item - Item to check
  303. * @returns If item was uploaded.
  304. */
  305. function drawText(_helper, item) {
  306. if (item instanceof text.Text) {
  307. // updating text will return early if it is not dirty
  308. item.updateText(true);
  309. return true;
  310. }
  311. return false;
  312. }
  313. /**
  314. * Built-in hook to calculate a text style for a PIXI.Text object.
  315. * @private
  316. * @param _helper - Not used by this upload handler
  317. * @param item - Item to check
  318. * @returns If item was uploaded.
  319. */
  320. function calculateTextStyle(_helper, item) {
  321. if (item instanceof text.TextStyle) {
  322. var font = item.toFontString();
  323. text.TextMetrics.measureFont(font);
  324. return true;
  325. }
  326. return false;
  327. }
  328. /**
  329. * Built-in hook to find Text objects.
  330. * @private
  331. * @param item - Display object to check
  332. * @param queue - Collection of items to upload
  333. * @returns if a PIXI.Text object was found.
  334. */
  335. function findText(item, queue) {
  336. if (item instanceof text.Text) {
  337. // push the text style to prepare it - this can be really expensive
  338. if (queue.indexOf(item.style) === -1) {
  339. queue.push(item.style);
  340. }
  341. // also push the text object so that we can render it (to canvas/texture) if needed
  342. if (queue.indexOf(item) === -1) {
  343. queue.push(item);
  344. }
  345. // also push the Text's texture for upload to GPU
  346. var texture = item._texture.baseTexture;
  347. if (queue.indexOf(texture) === -1) {
  348. queue.push(texture);
  349. }
  350. return true;
  351. }
  352. return false;
  353. }
  354. /**
  355. * Built-in hook to find TextStyle objects.
  356. * @private
  357. * @param item - Display object to check
  358. * @param queue - Collection of items to upload
  359. * @returns If a PIXI.TextStyle object was found.
  360. */
  361. function findTextStyle(item, queue) {
  362. if (item instanceof text.TextStyle) {
  363. if (queue.indexOf(item) === -1) {
  364. queue.push(item);
  365. }
  366. return true;
  367. }
  368. return false;
  369. }
  370. /**
  371. * The prepare manager provides functionality to upload content to the GPU.
  372. *
  373. * BasePrepare handles basic queuing functionality and is extended by
  374. * {@link PIXI.Prepare} and {@link PIXI.CanvasPrepare}
  375. * to provide preparation capabilities specific to their respective renderers.
  376. * @example
  377. * // Create a sprite
  378. * const sprite = PIXI.Sprite.from('something.png');
  379. *
  380. * // Load object into GPU
  381. * app.renderer.plugins.prepare.upload(sprite, () => {
  382. *
  383. * //Texture(s) has been uploaded to GPU
  384. * app.stage.addChild(sprite);
  385. *
  386. * })
  387. * @abstract
  388. * @memberof PIXI
  389. */
  390. var BasePrepare = /** @class */ (function () {
  391. /**
  392. * @param {PIXI.AbstractRenderer} renderer - A reference to the current renderer
  393. */
  394. function BasePrepare(renderer) {
  395. var _this = this;
  396. this.limiter = new CountLimiter(settings.settings.UPLOADS_PER_FRAME);
  397. this.renderer = renderer;
  398. this.uploadHookHelper = null;
  399. this.queue = [];
  400. this.addHooks = [];
  401. this.uploadHooks = [];
  402. this.completes = [];
  403. this.ticking = false;
  404. this.delayedTick = function () {
  405. // unlikely, but in case we were destroyed between tick() and delayedTick()
  406. if (!_this.queue) {
  407. return;
  408. }
  409. _this.prepareItems();
  410. };
  411. // hooks to find the correct texture
  412. this.registerFindHook(findText);
  413. this.registerFindHook(findTextStyle);
  414. this.registerFindHook(findMultipleBaseTextures);
  415. this.registerFindHook(findBaseTexture);
  416. this.registerFindHook(findTexture);
  417. // upload hooks
  418. this.registerUploadHook(drawText);
  419. this.registerUploadHook(calculateTextStyle);
  420. }
  421. /** @ignore */
  422. BasePrepare.prototype.upload = function (item, done) {
  423. var _this = this;
  424. if (typeof item === 'function') {
  425. done = item;
  426. item = null;
  427. }
  428. if (done) {
  429. utils.deprecation('6.5.0', 'BasePrepare.upload callback is deprecated, use the return Promise instead.');
  430. }
  431. return new Promise(function (resolve) {
  432. // If a display object, search for items
  433. // that we could upload
  434. if (item) {
  435. _this.add(item);
  436. }
  437. // TODO: remove done callback and just use resolve
  438. var complete = function () {
  439. done === null || done === void 0 ? void 0 : done();
  440. resolve();
  441. };
  442. // Get the items for upload from the display
  443. if (_this.queue.length) {
  444. _this.completes.push(complete);
  445. if (!_this.ticking) {
  446. _this.ticking = true;
  447. ticker.Ticker.system.addOnce(_this.tick, _this, ticker.UPDATE_PRIORITY.UTILITY);
  448. }
  449. }
  450. else {
  451. complete();
  452. }
  453. });
  454. };
  455. /**
  456. * Handle tick update
  457. * @private
  458. */
  459. BasePrepare.prototype.tick = function () {
  460. setTimeout(this.delayedTick, 0);
  461. };
  462. /**
  463. * Actually prepare items. This is handled outside of the tick because it will take a while
  464. * and we do NOT want to block the current animation frame from rendering.
  465. * @private
  466. */
  467. BasePrepare.prototype.prepareItems = function () {
  468. this.limiter.beginFrame();
  469. // Upload the graphics
  470. while (this.queue.length && this.limiter.allowedToUpload()) {
  471. var item = this.queue[0];
  472. var uploaded = false;
  473. if (item && !item._destroyed) {
  474. for (var i = 0, len = this.uploadHooks.length; i < len; i++) {
  475. if (this.uploadHooks[i](this.uploadHookHelper, item)) {
  476. this.queue.shift();
  477. uploaded = true;
  478. break;
  479. }
  480. }
  481. }
  482. if (!uploaded) {
  483. this.queue.shift();
  484. }
  485. }
  486. // We're finished
  487. if (!this.queue.length) {
  488. this.ticking = false;
  489. var completes = this.completes.slice(0);
  490. this.completes.length = 0;
  491. for (var i = 0, len = completes.length; i < len; i++) {
  492. completes[i]();
  493. }
  494. }
  495. else {
  496. // if we are not finished, on the next rAF do this again
  497. ticker.Ticker.system.addOnce(this.tick, this, ticker.UPDATE_PRIORITY.UTILITY);
  498. }
  499. };
  500. /**
  501. * Adds hooks for finding items.
  502. * @param {Function} addHook - Function call that takes two parameters: `item:*, queue:Array`
  503. * function must return `true` if it was able to add item to the queue.
  504. * @returns Instance of plugin for chaining.
  505. */
  506. BasePrepare.prototype.registerFindHook = function (addHook) {
  507. if (addHook) {
  508. this.addHooks.push(addHook);
  509. }
  510. return this;
  511. };
  512. /**
  513. * Adds hooks for uploading items.
  514. * @param {Function} uploadHook - Function call that takes two parameters: `prepare:CanvasPrepare, item:*` and
  515. * function must return `true` if it was able to handle upload of item.
  516. * @returns Instance of plugin for chaining.
  517. */
  518. BasePrepare.prototype.registerUploadHook = function (uploadHook) {
  519. if (uploadHook) {
  520. this.uploadHooks.push(uploadHook);
  521. }
  522. return this;
  523. };
  524. /**
  525. * Manually add an item to the uploading queue.
  526. * @param {PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text|*} item - Object to
  527. * add to the queue
  528. * @returns Instance of plugin for chaining.
  529. */
  530. BasePrepare.prototype.add = function (item) {
  531. // Add additional hooks for finding elements on special
  532. // types of objects that
  533. for (var i = 0, len = this.addHooks.length; i < len; i++) {
  534. if (this.addHooks[i](item, this.queue)) {
  535. break;
  536. }
  537. }
  538. // Get children recursively
  539. if (item instanceof display.Container) {
  540. for (var i = item.children.length - 1; i >= 0; i--) {
  541. this.add(item.children[i]);
  542. }
  543. }
  544. return this;
  545. };
  546. /** Destroys the plugin, don't use after this. */
  547. BasePrepare.prototype.destroy = function () {
  548. if (this.ticking) {
  549. ticker.Ticker.system.remove(this.tick, this);
  550. }
  551. this.ticking = false;
  552. this.addHooks = null;
  553. this.uploadHooks = null;
  554. this.renderer = null;
  555. this.completes = null;
  556. this.queue = null;
  557. this.limiter = null;
  558. this.uploadHookHelper = null;
  559. };
  560. return BasePrepare;
  561. }());
  562. /**
  563. * Built-in hook to upload PIXI.Texture objects to the GPU.
  564. * @private
  565. * @param renderer - instance of the webgl renderer
  566. * @param item - Item to check
  567. * @returns If item was uploaded.
  568. */
  569. function uploadBaseTextures(renderer, item) {
  570. if (item instanceof core.BaseTexture) {
  571. // if the texture already has a GL texture, then the texture has been prepared or rendered
  572. // before now. If the texture changed, then the changer should be calling texture.update() which
  573. // reuploads the texture without need for preparing it again
  574. if (!item._glTextures[renderer.CONTEXT_UID]) {
  575. renderer.texture.bind(item);
  576. }
  577. return true;
  578. }
  579. return false;
  580. }
  581. /**
  582. * Built-in hook to upload PIXI.Graphics to the GPU.
  583. * @private
  584. * @param renderer - instance of the webgl renderer
  585. * @param item - Item to check
  586. * @returns If item was uploaded.
  587. */
  588. function uploadGraphics(renderer, item) {
  589. if (!(item instanceof graphics.Graphics)) {
  590. return false;
  591. }
  592. var geometry = item.geometry;
  593. // update dirty graphics to get batches
  594. item.finishPoly();
  595. geometry.updateBatches();
  596. var batches = geometry.batches;
  597. // upload all textures found in styles
  598. for (var i = 0; i < batches.length; i++) {
  599. var texture = batches[i].style.texture;
  600. if (texture) {
  601. uploadBaseTextures(renderer, texture.baseTexture);
  602. }
  603. }
  604. // if its not batchable - update vao for particular shader
  605. if (!geometry.batchable) {
  606. renderer.geometry.bind(geometry, item._resolveDirectShader(renderer));
  607. }
  608. return true;
  609. }
  610. /**
  611. * Built-in hook to find graphics.
  612. * @private
  613. * @param item - Display object to check
  614. * @param queue - Collection of items to upload
  615. * @returns if a PIXI.Graphics object was found.
  616. */
  617. function findGraphics(item, queue) {
  618. if (item instanceof graphics.Graphics) {
  619. queue.push(item);
  620. return true;
  621. }
  622. return false;
  623. }
  624. /**
  625. * The prepare plugin provides renderer-specific plugins for pre-rendering DisplayObjects. These plugins are useful for
  626. * asynchronously preparing and uploading to the GPU assets, textures, graphics waiting to be displayed.
  627. *
  628. * Do not instantiate this plugin directly. It is available from the `renderer.plugins` property.
  629. * See {@link PIXI.CanvasRenderer#plugins} or {@link PIXI.Renderer#plugins}.
  630. * @example
  631. * // Create a new application
  632. * const app = new PIXI.Application();
  633. * document.body.appendChild(app.view);
  634. *
  635. * // Don't start rendering right away
  636. * app.stop();
  637. *
  638. * // create a display object
  639. * const rect = new PIXI.Graphics()
  640. * .beginFill(0x00ff00)
  641. * .drawRect(40, 40, 200, 200);
  642. *
  643. * // Add to the stage
  644. * app.stage.addChild(rect);
  645. *
  646. * // Don't start rendering until the graphic is uploaded to the GPU
  647. * app.renderer.plugins.prepare.upload(app.stage, () => {
  648. * app.start();
  649. * });
  650. * @memberof PIXI
  651. */
  652. var Prepare = /** @class */ (function (_super) {
  653. __extends(Prepare, _super);
  654. /**
  655. * @param {PIXI.Renderer} renderer - A reference to the current renderer
  656. */
  657. function Prepare(renderer) {
  658. var _this = _super.call(this, renderer) || this;
  659. _this.uploadHookHelper = _this.renderer;
  660. // Add textures and graphics to upload
  661. _this.registerFindHook(findGraphics);
  662. _this.registerUploadHook(uploadBaseTextures);
  663. _this.registerUploadHook(uploadGraphics);
  664. return _this;
  665. }
  666. /** @ignore */
  667. Prepare.extension = {
  668. name: 'prepare',
  669. type: core.ExtensionType.RendererPlugin,
  670. };
  671. return Prepare;
  672. }(BasePrepare));
  673. /**
  674. * TimeLimiter limits the number of items handled by a {@link PIXI.BasePrepare} to a specified
  675. * number of milliseconds per frame.
  676. * @memberof PIXI
  677. */
  678. var TimeLimiter = /** @class */ (function () {
  679. /** @param maxMilliseconds - The maximum milliseconds that can be spent preparing items each frame. */
  680. function TimeLimiter(maxMilliseconds) {
  681. this.maxMilliseconds = maxMilliseconds;
  682. this.frameStart = 0;
  683. }
  684. /** Resets any counting properties to start fresh on a new frame. */
  685. TimeLimiter.prototype.beginFrame = function () {
  686. this.frameStart = Date.now();
  687. };
  688. /**
  689. * Checks to see if another item can be uploaded. This should only be called once per item.
  690. * @returns - If the item is allowed to be uploaded.
  691. */
  692. TimeLimiter.prototype.allowedToUpload = function () {
  693. return Date.now() - this.frameStart < this.maxMilliseconds;
  694. };
  695. return TimeLimiter;
  696. }());
  697. exports.BasePrepare = BasePrepare;
  698. exports.CountLimiter = CountLimiter;
  699. exports.Prepare = Prepare;
  700. exports.TimeLimiter = TimeLimiter;
  701. Object.defineProperty(exports, '__esModule', { value: true });
  702. return exports;
  703. })({}, PIXI, PIXI, PIXI, PIXI, PIXI, PIXI, PIXI.utils);
  704. Object.assign(this.PIXI, _pixi_prepare);
  705. //# sourceMappingURL=prepare.js.map