UNPKG

429 kBJavaScriptView Raw
1/*!
2 * @pixi/core - v6.0.0
3 * Compiled Tue, 02 Mar 2021 21:45:03 UTC
4 *
5 * @pixi/core is licensed under the MIT License.
6 * http://www.opensource.org/licenses/mit-license
7 */
8import { settings } from '@pixi/settings';
9import { ENV, ALPHA_MODES, SCALE_MODES, FORMATS, TYPES, TARGETS, MIPMAP_MODES, MSAA_QUALITY, CLEAR_MODES, DRAW_MODES, BUFFER_BITS, MASK_TYPES, PRECISION, BLEND_MODES, GC_MODES, WRAP_MODES, RENDERER_TYPE } from '@pixi/constants';
10import { isMobile, isPow2, BaseTextureCache, TextureCache, uid, EventEmitter, determineCrossOrigin, getResolutionOfUrl, deprecation, nextPow2, ProgramCache, removeItems, hex2string, hex2rgb, sayHello, isWebGLSupported, premultiplyBlendMode, log2, premultiplyTint } from '@pixi/utils';
11import { Runner } from '@pixi/runner';
12import { Ticker } from '@pixi/ticker';
13import { groupD8, Rectangle, Point, Matrix } from '@pixi/math';
14
15/**
16 * The maximum support for using WebGL. If a device does not
17 * support WebGL version, for instance WebGL 2, it will still
18 * attempt to fallback support to WebGL 1. If you want to
19 * explicitly remove feature support to target a more stable
20 * baseline, prefer a lower environment.
21 *
22 * Due to {@link https://bugs.chromium.org/p/chromium/issues/detail?id=934823|bug in chromium}
23 * we disable webgl2 by default for all non-apple mobile devices.
24 *
25 * @static
26 * @name PREFER_ENV
27 * @memberof PIXI.settings
28 * @type {number}
29 * @default PIXI.ENV.WEBGL2
30 */
31settings.PREFER_ENV = isMobile.any ? ENV.WEBGL : ENV.WEBGL2;
32/**
33 * If set to `true`, *only* Textures and BaseTexture objects stored
34 * in the caches ({@link PIXI.utils.TextureCache TextureCache} and
35 * {@link PIXI.utils.BaseTextureCache BaseTextureCache}) can be
36 * used when calling {@link PIXI.Texture.from Texture.from} or
37 * {@link PIXI.BaseTexture.from BaseTexture.from}.
38 * Otherwise, these `from` calls throw an exception. Using this property
39 * can be useful if you want to enforce preloading all assets with
40 * {@link PIXI.Loader Loader}.
41 *
42 * @static
43 * @name STRICT_TEXTURE_CACHE
44 * @memberof PIXI.settings
45 * @type {boolean}
46 * @default false
47 */
48settings.STRICT_TEXTURE_CACHE = false;
49
50/**
51 * Collection of installed resource types, class must extend {@link PIXI.Resource}.
52 * @example
53 * class CustomResource extends PIXI.Resource {
54 * // MUST have source, options constructor signature
55 * // for auto-detected resources to be created.
56 * constructor(source, options) {
57 * super();
58 * }
59 * upload(renderer, baseTexture, glTexture) {
60 * // upload with GL
61 * return true;
62 * }
63 * // used to auto-detect resource
64 * static test(source, extension) {
65 * return extension === 'xyz'|| source instanceof SomeClass;
66 * }
67 * }
68 * // Install the new resource type
69 * PIXI.INSTALLED.push(CustomResource);
70 *
71 * @memberof PIXI
72 * @type {Array<PIXI.IResourcePlugin>}
73 * @static
74 * @readonly
75 */
76var INSTALLED = [];
77/**
78 * Create a resource element from a single source element. This
79 * auto-detects which type of resource to create. All resources that
80 * are auto-detectable must have a static `test` method and a constructor
81 * with the arguments `(source, options?)`. Currently, the supported
82 * resources for auto-detection include:
83 * - {@link PIXI.ImageResource}
84 * - {@link PIXI.CanvasResource}
85 * - {@link PIXI.VideoResource}
86 * - {@link PIXI.SVGResource}
87 * - {@link PIXI.BufferResource}
88 * @static
89 * @memberof PIXI
90 * @function autoDetectResource
91 * @param {string|*} source - Resource source, this can be the URL to the resource,
92 * a typed-array (for BufferResource), HTMLVideoElement, SVG data-uri
93 * or any other resource that can be auto-detected. If not resource is
94 * detected, it's assumed to be an ImageResource.
95 * @param {object} [options] - Pass-through options to use for Resource
96 * @param {number} [options.width] - Width of BufferResource or SVG rasterization
97 * @param {number} [options.height] - Height of BufferResource or SVG rasterization
98 * @param {boolean} [options.autoLoad=true] - Image, SVG and Video flag to start loading
99 * @param {number} [options.scale=1] - SVG source scale. Overridden by width, height
100 * @param {boolean} [options.createBitmap=PIXI.settings.CREATE_IMAGE_BITMAP] - Image option to create Bitmap object
101 * @param {boolean} [options.crossorigin=true] - Image and Video option to set crossOrigin
102 * @param {boolean} [options.autoPlay=true] - Video option to start playing video immediately
103 * @param {number} [options.updateFPS=0] - Video option to update how many times a second the
104 * texture should be updated from the video. Leave at 0 to update at every render
105 * @return {PIXI.Resource} The created resource.
106 */
107function autoDetectResource(source, options) {
108 if (!source) {
109 return null;
110 }
111 var extension = '';
112 if (typeof source === 'string') {
113 // search for file extension: period, 3-4 chars, then ?, # or EOL
114 var result = (/\.(\w{3,4})(?:$|\?|#)/i).exec(source);
115 if (result) {
116 extension = result[1].toLowerCase();
117 }
118 }
119 for (var i = INSTALLED.length - 1; i >= 0; --i) {
120 var ResourcePlugin = INSTALLED[i];
121 if (ResourcePlugin.test && ResourcePlugin.test(source, extension)) {
122 return new ResourcePlugin(source, options);
123 }
124 }
125 throw new Error('Unrecognized source type to auto-detect Resource');
126}
127
128/*! *****************************************************************************
129Copyright (c) Microsoft Corporation. All rights reserved.
130Licensed under the Apache License, Version 2.0 (the "License"); you may not use
131this file except in compliance with the License. You may obtain a copy of the
132License at http://www.apache.org/licenses/LICENSE-2.0
133
134THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
135KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
136WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
137MERCHANTABLITY OR NON-INFRINGEMENT.
138
139See the Apache Version 2.0 License for specific language governing permissions
140and limitations under the License.
141***************************************************************************** */
142/* global Reflect, Promise */
143
144var extendStatics = function(d, b) {
145 extendStatics = Object.setPrototypeOf ||
146 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
147 function (d, b) { for (var p in b) { if (b.hasOwnProperty(p)) { d[p] = b[p]; } } };
148 return extendStatics(d, b);
149};
150
151function __extends(d, b) {
152 extendStatics(d, b);
153 function __() { this.constructor = d; }
154 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
155}
156
157/**
158 * Base resource class for textures that manages validation and uploading, depending on its type.
159 *
160 * Uploading of a base texture to the GPU is required.
161 *
162 * @class
163 * @memberof PIXI
164 */
165var Resource = /** @class */ (function () {
166 /**
167 * @param {number} [width=0] - Width of the resource
168 * @param {number} [height=0] - Height of the resource
169 */
170 function Resource(width, height) {
171 if (width === void 0) { width = 0; }
172 if (height === void 0) { height = 0; }
173 /**
174 * Internal width of the resource
175 * @member {number}
176 * @protected
177 */
178 this._width = width;
179 /**
180 * Internal height of the resource
181 * @member {number}
182 * @protected
183 */
184 this._height = height;
185 /**
186 * If resource has been destroyed
187 * @member {boolean}
188 * @readonly
189 * @default false
190 */
191 this.destroyed = false;
192 /**
193 * `true` if resource is created by BaseTexture
194 * useful for doing cleanup with BaseTexture destroy
195 * and not cleaning up resources that were created
196 * externally.
197 * @member {boolean}
198 * @protected
199 */
200 this.internal = false;
201 /**
202 * Mini-runner for handling resize events
203 * accepts 2 parameters: width, height
204 *
205 * @member {Runner}
206 * @private
207 */
208 this.onResize = new Runner('setRealSize');
209 /**
210 * Mini-runner for handling update events
211 *
212 * @member {Runner}
213 * @private
214 */
215 this.onUpdate = new Runner('update');
216 /**
217 * Handle internal errors, such as loading errors
218 * accepts 1 param: error
219 *
220 * @member {Runner}
221 * @private
222 */
223 this.onError = new Runner('onError');
224 }
225 /**
226 * Bind to a parent BaseTexture
227 *
228 * @param {PIXI.BaseTexture} baseTexture - Parent texture
229 */
230 Resource.prototype.bind = function (baseTexture) {
231 this.onResize.add(baseTexture);
232 this.onUpdate.add(baseTexture);
233 this.onError.add(baseTexture);
234 // Call a resize immediate if we already
235 // have the width and height of the resource
236 if (this._width || this._height) {
237 this.onResize.emit(this._width, this._height);
238 }
239 };
240 /**
241 * Unbind to a parent BaseTexture
242 *
243 * @param {PIXI.BaseTexture} baseTexture - Parent texture
244 */
245 Resource.prototype.unbind = function (baseTexture) {
246 this.onResize.remove(baseTexture);
247 this.onUpdate.remove(baseTexture);
248 this.onError.remove(baseTexture);
249 };
250 /**
251 * Trigger a resize event
252 * @param {number} width - X dimension
253 * @param {number} height - Y dimension
254 */
255 Resource.prototype.resize = function (width, height) {
256 if (width !== this._width || height !== this._height) {
257 this._width = width;
258 this._height = height;
259 this.onResize.emit(width, height);
260 }
261 };
262 Object.defineProperty(Resource.prototype, "valid", {
263 /**
264 * Has been validated
265 * @readonly
266 * @member {boolean}
267 */
268 get: function () {
269 return !!this._width && !!this._height;
270 },
271 enumerable: false,
272 configurable: true
273 });
274 /**
275 * Has been updated trigger event
276 */
277 Resource.prototype.update = function () {
278 if (!this.destroyed) {
279 this.onUpdate.emit();
280 }
281 };
282 /**
283 * This can be overridden to start preloading a resource
284 * or do any other prepare step.
285 * @protected
286 * @return {Promise<void>} Handle the validate event
287 */
288 Resource.prototype.load = function () {
289 return Promise.resolve(this);
290 };
291 Object.defineProperty(Resource.prototype, "width", {
292 /**
293 * The width of the resource.
294 *
295 * @member {number}
296 * @readonly
297 */
298 get: function () {
299 return this._width;
300 },
301 enumerable: false,
302 configurable: true
303 });
304 Object.defineProperty(Resource.prototype, "height", {
305 /**
306 * The height of the resource.
307 *
308 * @member {number}
309 * @readonly
310 */
311 get: function () {
312 return this._height;
313 },
314 enumerable: false,
315 configurable: true
316 });
317 /**
318 * Set the style, optional to override
319 *
320 * @param {PIXI.Renderer} renderer - yeah, renderer!
321 * @param {PIXI.BaseTexture} baseTexture - the texture
322 * @param {PIXI.GLTexture} glTexture - texture instance for this webgl context
323 * @returns {boolean} `true` is success
324 */
325 Resource.prototype.style = function (_renderer, _baseTexture, _glTexture) {
326 return false;
327 };
328 /**
329 * Clean up anything, this happens when destroying is ready.
330 *
331 * @protected
332 */
333 Resource.prototype.dispose = function () {
334 // override
335 };
336 /**
337 * Call when destroying resource, unbind any BaseTexture object
338 * before calling this method, as reference counts are maintained
339 * internally.
340 */
341 Resource.prototype.destroy = function () {
342 if (!this.destroyed) {
343 this.destroyed = true;
344 this.dispose();
345 this.onError.removeAll();
346 this.onError = null;
347 this.onResize.removeAll();
348 this.onResize = null;
349 this.onUpdate.removeAll();
350 this.onUpdate = null;
351 }
352 };
353 /**
354 * Abstract, used to auto-detect resource type
355 *
356 * @static
357 * @param {*} source - The source object
358 * @param {string} extension - The extension of source, if set
359 */
360 Resource.test = function (_source, _extension) {
361 return false;
362 };
363 return Resource;
364}());
365
366/**
367 * @interface SharedArrayBuffer
368 */
369/**
370 * Buffer resource with data of typed array.
371 * @class
372 * @extends PIXI.Resource
373 * @memberof PIXI
374 */
375var BufferResource = /** @class */ (function (_super) {
376 __extends(BufferResource, _super);
377 /**
378 * @param {Float32Array|Uint8Array|Uint32Array} source - Source buffer
379 * @param {object} options - Options
380 * @param {number} options.width - Width of the texture
381 * @param {number} options.height - Height of the texture
382 */
383 function BufferResource(source, options) {
384 var _this = this;
385 var _a = options || {}, width = _a.width, height = _a.height;
386 if (!width || !height) {
387 throw new Error('BufferResource width or height invalid');
388 }
389 _this = _super.call(this, width, height) || this;
390 /**
391 * Source array
392 * Cannot be ClampedUint8Array because it cant be uploaded to WebGL
393 *
394 * @member {Float32Array|Uint8Array|Uint32Array}
395 */
396 _this.data = source;
397 return _this;
398 }
399 /**
400 * Upload the texture to the GPU.
401 * @param {PIXI.Renderer} renderer - Upload to the renderer
402 * @param {PIXI.BaseTexture} baseTexture - Reference to parent texture
403 * @param {PIXI.GLTexture} glTexture - glTexture
404 * @returns {boolean} true is success
405 */
406 BufferResource.prototype.upload = function (renderer, baseTexture, glTexture) {
407 var gl = renderer.gl;
408 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, baseTexture.alphaMode === ALPHA_MODES.UNPACK);
409 if (glTexture.width === baseTexture.width && glTexture.height === baseTexture.height) {
410 gl.texSubImage2D(baseTexture.target, 0, 0, 0, baseTexture.width, baseTexture.height, baseTexture.format, baseTexture.type, this.data);
411 }
412 else {
413 glTexture.width = baseTexture.width;
414 glTexture.height = baseTexture.height;
415 gl.texImage2D(baseTexture.target, 0, glTexture.internalFormat, baseTexture.width, baseTexture.height, 0, baseTexture.format, glTexture.type, this.data);
416 }
417 return true;
418 };
419 /**
420 * Destroy and don't use after this
421 * @override
422 */
423 BufferResource.prototype.dispose = function () {
424 this.data = null;
425 };
426 /**
427 * Used to auto-detect the type of resource.
428 *
429 * @static
430 * @param {*} source - The source object
431 * @return {boolean} `true` if <canvas>
432 */
433 BufferResource.test = function (source) {
434 return source instanceof Float32Array
435 || source instanceof Uint8Array
436 || source instanceof Uint32Array;
437 };
438 return BufferResource;
439}(Resource));
440
441var defaultBufferOptions = {
442 scaleMode: SCALE_MODES.NEAREST,
443 format: FORMATS.RGBA,
444 alphaMode: ALPHA_MODES.NPM,
445};
446/**
447 * A Texture stores the information that represents an image.
448 * All textures have a base texture, which contains information about the source.
449 * Therefore you can have many textures all using a single BaseTexture
450 *
451 * @class
452 * @extends PIXI.utils.EventEmitter
453 * @memberof PIXI
454 * @typeParam R - The BaseTexture's Resource type.
455 * @typeParam RO - The options for constructing resource.
456 */
457var BaseTexture = /** @class */ (function (_super) {
458 __extends(BaseTexture, _super);
459 /**
460 * @param {PIXI.Resource|string|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [resource=null] -
461 * The current resource to use, for things that aren't Resource objects, will be converted
462 * into a Resource.
463 * @param {Object} [options] - Collection of options
464 * @param {PIXI.MIPMAP_MODES} [options.mipmap=PIXI.settings.MIPMAP_TEXTURES] - If mipmapping is enabled for texture
465 * @param {number} [options.anisotropicLevel=PIXI.settings.ANISOTROPIC_LEVEL] - Anisotropic filtering level of texture
466 * @param {PIXI.WRAP_MODES} [options.wrapMode=PIXI.settings.WRAP_MODE] - Wrap mode for textures
467 * @param {PIXI.SCALE_MODES} [options.scaleMode=PIXI.settings.SCALE_MODE] - Default scale mode, linear, nearest
468 * @param {PIXI.FORMATS} [options.format=PIXI.FORMATS.RGBA] - GL format type
469 * @param {PIXI.TYPES} [options.type=PIXI.TYPES.UNSIGNED_BYTE] - GL data type
470 * @param {PIXI.TARGETS} [options.target=PIXI.TARGETS.TEXTURE_2D] - GL texture target
471 * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.UNPACK] - Pre multiply the image alpha
472 * @param {number} [options.width=0] - Width of the texture
473 * @param {number} [options.height=0] - Height of the texture
474 * @param {number} [options.resolution] - Resolution of the base texture
475 * @param {object} [options.resourceOptions] - Optional resource options,
476 * see {@link PIXI.autoDetectResource autoDetectResource}
477 */
478 function BaseTexture(resource, options) {
479 if (resource === void 0) { resource = null; }
480 if (options === void 0) { options = null; }
481 var _this = _super.call(this) || this;
482 options = options || {};
483 var alphaMode = options.alphaMode, mipmap = options.mipmap, anisotropicLevel = options.anisotropicLevel, scaleMode = options.scaleMode, width = options.width, height = options.height, wrapMode = options.wrapMode, format = options.format, type = options.type, target = options.target, resolution = options.resolution, resourceOptions = options.resourceOptions;
484 // Convert the resource to a Resource object
485 if (resource && !(resource instanceof Resource)) {
486 resource = autoDetectResource(resource, resourceOptions);
487 resource.internal = true;
488 }
489 /**
490 * The width of the base texture set when the image has loaded
491 *
492 * @readonly
493 * @member {number}
494 */
495 _this.width = width || 0;
496 /**
497 * The height of the base texture set when the image has loaded
498 *
499 * @readonly
500 * @member {number}
501 */
502 _this.height = height || 0;
503 /**
504 * The resolution / device pixel ratio of the texture
505 *
506 * @member {number}
507 * @default PIXI.settings.RESOLUTION
508 */
509 _this.resolution = resolution || settings.RESOLUTION;
510 /**
511 * Mipmap mode of the texture, affects downscaled images
512 *
513 * @member {PIXI.MIPMAP_MODES}
514 * @default PIXI.settings.MIPMAP_TEXTURES
515 */
516 _this.mipmap = mipmap !== undefined ? mipmap : settings.MIPMAP_TEXTURES;
517 /**
518 * Anisotropic filtering level of texture
519 *
520 * @member {number}
521 * @default PIXI.settings.ANISOTROPIC_LEVEL
522 */
523 _this.anisotropicLevel = anisotropicLevel !== undefined ? anisotropicLevel : settings.ANISOTROPIC_LEVEL;
524 /**
525 * How the texture wraps
526 * @member {number}
527 */
528 _this.wrapMode = wrapMode || settings.WRAP_MODE;
529 /**
530 * The scale mode to apply when scaling this texture
531 *
532 * @member {PIXI.SCALE_MODES}
533 * @default PIXI.settings.SCALE_MODE
534 */
535 _this.scaleMode = scaleMode !== undefined ? scaleMode : settings.SCALE_MODE;
536 /**
537 * The pixel format of the texture
538 *
539 * @member {PIXI.FORMATS}
540 * @default PIXI.FORMATS.RGBA
541 */
542 _this.format = format || FORMATS.RGBA;
543 /**
544 * The type of resource data
545 *
546 * @member {PIXI.TYPES}
547 * @default PIXI.TYPES.UNSIGNED_BYTE
548 */
549 _this.type = type || TYPES.UNSIGNED_BYTE;
550 /**
551 * The target type
552 *
553 * @member {PIXI.TARGETS}
554 * @default PIXI.TARGETS.TEXTURE_2D
555 */
556 _this.target = target || TARGETS.TEXTURE_2D;
557 /**
558 * How to treat premultiplied alpha, see {@link PIXI.ALPHA_MODES}.
559 *
560 * @member {PIXI.ALPHA_MODES}
561 * @default PIXI.ALPHA_MODES.UNPACK
562 */
563 _this.alphaMode = alphaMode !== undefined ? alphaMode : ALPHA_MODES.UNPACK;
564 /**
565 * Global unique identifier for this BaseTexture
566 *
567 * @member {number}
568 * @protected
569 */
570 _this.uid = uid();
571 /**
572 * Used by automatic texture Garbage Collection, stores last GC tick when it was bound
573 *
574 * @member {number}
575 * @protected
576 */
577 _this.touched = 0;
578 /**
579 * Whether or not the texture is a power of two, try to use power of two textures as much
580 * as you can
581 *
582 * @readonly
583 * @member {boolean}
584 * @default false
585 */
586 _this.isPowerOfTwo = false;
587 _this._refreshPOT();
588 /**
589 * The map of render context textures where this is bound
590 *
591 * @member {Object}
592 * @private
593 */
594 _this._glTextures = {};
595 /**
596 * Used by TextureSystem to only update texture to the GPU when needed.
597 * Please call `update()` to increment it.
598 *
599 * @readonly
600 * @member {number}
601 */
602 _this.dirtyId = 0;
603 /**
604 * Used by TextureSystem to only update texture style when needed.
605 *
606 * @protected
607 * @member {number}
608 */
609 _this.dirtyStyleId = 0;
610 /**
611 * Currently default cache ID.
612 *
613 * @member {string}
614 */
615 _this.cacheId = null;
616 /**
617 * Generally speaking means when resource is loaded.
618 * @readonly
619 * @member {boolean}
620 */
621 _this.valid = width > 0 && height > 0;
622 /**
623 * The collection of alternative cache ids, since some BaseTextures
624 * can have more than one ID, short name and longer full URL
625 *
626 * @member {Array<string>}
627 * @readonly
628 */
629 _this.textureCacheIds = [];
630 /**
631 * Flag if BaseTexture has been destroyed.
632 *
633 * @member {boolean}
634 * @readonly
635 */
636 _this.destroyed = false;
637 /**
638 * The resource used by this BaseTexture, there can only
639 * be one resource per BaseTexture, but textures can share
640 * resources.
641 *
642 * @member {PIXI.Resource}
643 * @readonly
644 */
645 _this.resource = null;
646 /**
647 * Number of the texture batch, used by multi-texture renderers
648 *
649 * @member {number}
650 */
651 _this._batchEnabled = 0;
652 /**
653 * Location inside texture batch, used by multi-texture renderers
654 *
655 * @member {number}
656 */
657 _this._batchLocation = 0;
658 /**
659 * Whether its a part of another texture, handled by ArrayResource or CubeResource
660 *
661 * @member {PIXI.BaseTexture}
662 */
663 _this.parentTextureArray = null;
664 /**
665 * Fired when a not-immediately-available source finishes loading.
666 *
667 * @protected
668 * @event PIXI.BaseTexture#loaded
669 * @param {PIXI.BaseTexture} baseTexture - Resource loaded.
670 */
671 /**
672 * Fired when a not-immediately-available source fails to load.
673 *
674 * @protected
675 * @event PIXI.BaseTexture#error
676 * @param {PIXI.BaseTexture} baseTexture - Resource errored.
677 * @param {ErrorEvent} event - Load error event.
678 */
679 /**
680 * Fired when BaseTexture is updated.
681 *
682 * @protected
683 * @event PIXI.BaseTexture#loaded
684 * @param {PIXI.BaseTexture} baseTexture - Resource loaded.
685 */
686 /**
687 * Fired when BaseTexture is updated.
688 *
689 * @protected
690 * @event PIXI.BaseTexture#update
691 * @param {PIXI.BaseTexture} baseTexture - Instance of texture being updated.
692 */
693 /**
694 * Fired when BaseTexture is destroyed.
695 *
696 * @protected
697 * @event PIXI.BaseTexture#dispose
698 * @param {PIXI.BaseTexture} baseTexture - Instance of texture being destroyed.
699 */
700 // Set the resource
701 _this.setResource(resource);
702 return _this;
703 }
704 Object.defineProperty(BaseTexture.prototype, "realWidth", {
705 /**
706 * Pixel width of the source of this texture
707 *
708 * @readonly
709 * @member {number}
710 */
711 get: function () {
712 return Math.ceil((this.width * this.resolution) - 1e-4);
713 },
714 enumerable: false,
715 configurable: true
716 });
717 Object.defineProperty(BaseTexture.prototype, "realHeight", {
718 /**
719 * Pixel height of the source of this texture
720 *
721 * @readonly
722 * @member {number}
723 */
724 get: function () {
725 return Math.ceil((this.height * this.resolution) - 1e-4);
726 },
727 enumerable: false,
728 configurable: true
729 });
730 /**
731 * Changes style options of BaseTexture
732 *
733 * @param {PIXI.SCALE_MODES} [scaleMode] - Pixi scalemode
734 * @param {PIXI.MIPMAP_MODES} [mipmap] - enable mipmaps
735 * @returns {PIXI.BaseTexture} this
736 */
737 BaseTexture.prototype.setStyle = function (scaleMode, mipmap) {
738 var dirty;
739 if (scaleMode !== undefined && scaleMode !== this.scaleMode) {
740 this.scaleMode = scaleMode;
741 dirty = true;
742 }
743 if (mipmap !== undefined && mipmap !== this.mipmap) {
744 this.mipmap = mipmap;
745 dirty = true;
746 }
747 if (dirty) {
748 this.dirtyStyleId++;
749 }
750 return this;
751 };
752 /**
753 * Changes w/h/resolution. Texture becomes valid if width and height are greater than zero.
754 *
755 * @param {number} width - Visual width
756 * @param {number} height - Visual height
757 * @param {number} [resolution] - Optionally set resolution
758 * @returns {PIXI.BaseTexture} this
759 */
760 BaseTexture.prototype.setSize = function (width, height, resolution) {
761 this.resolution = resolution || this.resolution;
762 this.width = width;
763 this.height = height;
764 this._refreshPOT();
765 this.update();
766 return this;
767 };
768 /**
769 * Sets real size of baseTexture, preserves current resolution.
770 *
771 * @param {number} realWidth - Full rendered width
772 * @param {number} realHeight - Full rendered height
773 * @param {number} [resolution] - Optionally set resolution
774 * @returns {PIXI.BaseTexture} this
775 */
776 BaseTexture.prototype.setRealSize = function (realWidth, realHeight, resolution) {
777 this.resolution = resolution || this.resolution;
778 this.width = realWidth / this.resolution;
779 this.height = realHeight / this.resolution;
780 this._refreshPOT();
781 this.update();
782 return this;
783 };
784 /**
785 * Refresh check for isPowerOfTwo texture based on size
786 *
787 * @private
788 */
789 BaseTexture.prototype._refreshPOT = function () {
790 this.isPowerOfTwo = isPow2(this.realWidth) && isPow2(this.realHeight);
791 };
792 /**
793 * Changes resolution
794 *
795 * @param {number} resolution - res
796 * @returns {PIXI.BaseTexture} this
797 */
798 BaseTexture.prototype.setResolution = function (resolution) {
799 var oldResolution = this.resolution;
800 if (oldResolution === resolution) {
801 return this;
802 }
803 this.resolution = resolution;
804 if (this.valid) {
805 this.width = this.width * oldResolution / resolution;
806 this.height = this.height * oldResolution / resolution;
807 this.emit('update', this);
808 }
809 this._refreshPOT();
810 return this;
811 };
812 /**
813 * Sets the resource if it wasn't set. Throws error if resource already present
814 *
815 * @param {PIXI.Resource} resource - that is managing this BaseTexture
816 * @returns {PIXI.BaseTexture} this
817 */
818 BaseTexture.prototype.setResource = function (resource) {
819 if (this.resource === resource) {
820 return this;
821 }
822 if (this.resource) {
823 throw new Error('Resource can be set only once');
824 }
825 resource.bind(this);
826 this.resource = resource;
827 return this;
828 };
829 /**
830 * Invalidates the object. Texture becomes valid if width and height are greater than zero.
831 */
832 BaseTexture.prototype.update = function () {
833 if (!this.valid) {
834 if (this.width > 0 && this.height > 0) {
835 this.valid = true;
836 this.emit('loaded', this);
837 this.emit('update', this);
838 }
839 }
840 else {
841 this.dirtyId++;
842 this.dirtyStyleId++;
843 this.emit('update', this);
844 }
845 };
846 /**
847 * Handle errors with resources.
848 * @private
849 * @param {ErrorEvent} event - Error event emitted.
850 */
851 BaseTexture.prototype.onError = function (event) {
852 this.emit('error', this, event);
853 };
854 /**
855 * Destroys this base texture.
856 * The method stops if resource doesn't want this texture to be destroyed.
857 * Removes texture from all caches.
858 */
859 BaseTexture.prototype.destroy = function () {
860 // remove and destroy the resource
861 if (this.resource) {
862 this.resource.unbind(this);
863 // only destroy resourced created internally
864 if (this.resource.internal) {
865 this.resource.destroy();
866 }
867 this.resource = null;
868 }
869 if (this.cacheId) {
870 delete BaseTextureCache[this.cacheId];
871 delete TextureCache[this.cacheId];
872 this.cacheId = null;
873 }
874 // finally let the WebGL renderer know..
875 this.dispose();
876 BaseTexture.removeFromCache(this);
877 this.textureCacheIds = null;
878 this.destroyed = true;
879 };
880 /**
881 * Frees the texture from WebGL memory without destroying this texture object.
882 * This means you can still use the texture later which will upload it to GPU
883 * memory again.
884 *
885 * @fires PIXI.BaseTexture#dispose
886 */
887 BaseTexture.prototype.dispose = function () {
888 this.emit('dispose', this);
889 };
890 /**
891 * Utility function for BaseTexture|Texture cast
892 */
893 BaseTexture.prototype.castToBaseTexture = function () {
894 return this;
895 };
896 /**
897 * Helper function that creates a base texture based on the source you provide.
898 * The source can be - image url, image element, canvas element. If the
899 * source is an image url or an image element and not in the base texture
900 * cache, it will be created and loaded.
901 *
902 * @static
903 * @param {string|HTMLImageElement|HTMLCanvasElement|SVGElement|HTMLVideoElement} source - The
904 * source to create base texture from.
905 * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options.
906 * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id
907 * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}.
908 * @returns {PIXI.BaseTexture} The new base texture.
909 */
910 BaseTexture.from = function (source, options, strict) {
911 if (strict === void 0) { strict = settings.STRICT_TEXTURE_CACHE; }
912 var isFrame = typeof source === 'string';
913 var cacheId = null;
914 if (isFrame) {
915 cacheId = source;
916 }
917 else {
918 if (!source._pixiId) {
919 var prefix = (options && options.pixiIdPrefix) || 'pixiid';
920 source._pixiId = prefix + "_" + uid();
921 }
922 cacheId = source._pixiId;
923 }
924 var baseTexture = BaseTextureCache[cacheId];
925 // Strict-mode rejects invalid cacheIds
926 if (isFrame && strict && !baseTexture) {
927 throw new Error("The cacheId \"" + cacheId + "\" does not exist in BaseTextureCache.");
928 }
929 if (!baseTexture) {
930 baseTexture = new BaseTexture(source, options);
931 baseTexture.cacheId = cacheId;
932 BaseTexture.addToCache(baseTexture, cacheId);
933 }
934 return baseTexture;
935 };
936 /**
937 * Create a new BaseTexture with a BufferResource from a Float32Array.
938 * RGBA values are floats from 0 to 1.
939 * @static
940 * @param {Float32Array|Uint8Array} buffer - The optional array to use, if no data
941 * is provided, a new Float32Array is created.
942 * @param {number} width - Width of the resource
943 * @param {number} height - Height of the resource
944 * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options.
945 * @return {PIXI.BaseTexture} The resulting new BaseTexture
946 */
947 BaseTexture.fromBuffer = function (buffer, width, height, options) {
948 buffer = buffer || new Float32Array(width * height * 4);
949 var resource = new BufferResource(buffer, { width: width, height: height });
950 var type = buffer instanceof Float32Array ? TYPES.FLOAT : TYPES.UNSIGNED_BYTE;
951 return new BaseTexture(resource, Object.assign(defaultBufferOptions, options || { width: width, height: height, type: type }));
952 };
953 /**
954 * Adds a BaseTexture to the global BaseTextureCache. This cache is shared across the whole PIXI object.
955 *
956 * @static
957 * @param {PIXI.BaseTexture} baseTexture - The BaseTexture to add to the cache.
958 * @param {string} id - The id that the BaseTexture will be stored against.
959 */
960 BaseTexture.addToCache = function (baseTexture, id) {
961 if (id) {
962 if (baseTexture.textureCacheIds.indexOf(id) === -1) {
963 baseTexture.textureCacheIds.push(id);
964 }
965 if (BaseTextureCache[id]) {
966 // eslint-disable-next-line no-console
967 console.warn("BaseTexture added to the cache with an id [" + id + "] that already had an entry");
968 }
969 BaseTextureCache[id] = baseTexture;
970 }
971 };
972 /**
973 * Remove a BaseTexture from the global BaseTextureCache.
974 *
975 * @static
976 * @param {string|PIXI.BaseTexture} baseTexture - id of a BaseTexture to be removed, or a BaseTexture instance itself.
977 * @return {PIXI.BaseTexture|null} The BaseTexture that was removed.
978 */
979 BaseTexture.removeFromCache = function (baseTexture) {
980 if (typeof baseTexture === 'string') {
981 var baseTextureFromCache = BaseTextureCache[baseTexture];
982 if (baseTextureFromCache) {
983 var index = baseTextureFromCache.textureCacheIds.indexOf(baseTexture);
984 if (index > -1) {
985 baseTextureFromCache.textureCacheIds.splice(index, 1);
986 }
987 delete BaseTextureCache[baseTexture];
988 return baseTextureFromCache;
989 }
990 }
991 else if (baseTexture && baseTexture.textureCacheIds) {
992 for (var i = 0; i < baseTexture.textureCacheIds.length; ++i) {
993 delete BaseTextureCache[baseTexture.textureCacheIds[i]];
994 }
995 baseTexture.textureCacheIds.length = 0;
996 return baseTexture;
997 }
998 return null;
999 };
1000 /**
1001 * Global number of the texture batch, used by multi-texture renderers
1002 *
1003 * @static
1004 * @member {number}
1005 */
1006 BaseTexture._globalBatch = 0;
1007 return BaseTexture;
1008}(EventEmitter));
1009
1010/**
1011 * Resource that can manage several resource (items) inside.
1012 * All resources need to have the same pixel size.
1013 * Parent class for CubeResource and ArrayResource
1014 *
1015 * @class
1016 * @extends PIXI.Resource
1017 * @memberof PIXI
1018 */
1019var AbstractMultiResource = /** @class */ (function (_super) {
1020 __extends(AbstractMultiResource, _super);
1021 /**
1022 * @param {number} length
1023 * @param {object} [options] - Options to for Resource constructor
1024 * @param {number} [options.width] - Width of the resource
1025 * @param {number} [options.height] - Height of the resource
1026 */
1027 function AbstractMultiResource(length, options) {
1028 var _this = this;
1029 var _a = options || {}, width = _a.width, height = _a.height;
1030 _this = _super.call(this, width, height) || this;
1031 /**
1032 * Collection of partial baseTextures that correspond to resources
1033 * @member {Array<PIXI.BaseTexture>}
1034 * @readonly
1035 */
1036 _this.items = [];
1037 /**
1038 * Dirty IDs for each part
1039 * @member {Array<number>}
1040 * @readonly
1041 */
1042 _this.itemDirtyIds = [];
1043 for (var i = 0; i < length; i++) {
1044 var partTexture = new BaseTexture();
1045 _this.items.push(partTexture);
1046 // -2 - first run of texture array upload
1047 // -1 - texture item was allocated
1048 // >=0 - texture item uploaded , in sync with items[i].dirtyId
1049 _this.itemDirtyIds.push(-2);
1050 }
1051 /**
1052 * Number of elements in array
1053 *
1054 * @member {number}
1055 * @readonly
1056 */
1057 _this.length = length;
1058 /**
1059 * Promise when loading
1060 * @member {Promise}
1061 * @private
1062 * @default null
1063 */
1064 _this._load = null;
1065 /**
1066 * Bound baseTexture, there can only be one
1067 * @member {PIXI.BaseTexture}
1068 */
1069 _this.baseTexture = null;
1070 return _this;
1071 }
1072 /**
1073 * used from ArrayResource and CubeResource constructors
1074 * @param {Array<*>} resources - Can be resources, image elements, canvas, etc. ,
1075 * length should be same as constructor length
1076 * @param {object} [options] - detect options for resources
1077 * @protected
1078 */
1079 AbstractMultiResource.prototype.initFromArray = function (resources, options) {
1080 for (var i = 0; i < this.length; i++) {
1081 if (!resources[i]) {
1082 continue;
1083 }
1084 if (resources[i].castToBaseTexture) {
1085 this.addBaseTextureAt(resources[i].castToBaseTexture(), i);
1086 }
1087 else if (resources[i] instanceof Resource) {
1088 this.addResourceAt(resources[i], i);
1089 }
1090 else {
1091 this.addResourceAt(autoDetectResource(resources[i], options), i);
1092 }
1093 }
1094 };
1095 /**
1096 * Destroy this BaseImageResource
1097 * @override
1098 */
1099 AbstractMultiResource.prototype.dispose = function () {
1100 for (var i = 0, len = this.length; i < len; i++) {
1101 this.items[i].destroy();
1102 }
1103 this.items = null;
1104 this.itemDirtyIds = null;
1105 this._load = null;
1106 };
1107 /**
1108 * Set a resource by ID
1109 *
1110 * @param {PIXI.Resource} resource
1111 * @param {number} index - Zero-based index of resource to set
1112 * @return {PIXI.ArrayResource} Instance for chaining
1113 */
1114 AbstractMultiResource.prototype.addResourceAt = function (resource, index) {
1115 if (!this.items[index]) {
1116 throw new Error("Index " + index + " is out of bounds");
1117 }
1118 // Inherit the first resource dimensions
1119 if (resource.valid && !this.valid) {
1120 this.resize(resource.width, resource.height);
1121 }
1122 this.items[index].setResource(resource);
1123 return this;
1124 };
1125 /**
1126 * Set the parent base texture
1127 * @member {PIXI.BaseTexture}
1128 * @override
1129 */
1130 AbstractMultiResource.prototype.bind = function (baseTexture) {
1131 if (this.baseTexture !== null) {
1132 throw new Error('Only one base texture per TextureArray is allowed');
1133 }
1134 _super.prototype.bind.call(this, baseTexture);
1135 for (var i = 0; i < this.length; i++) {
1136 this.items[i].parentTextureArray = baseTexture;
1137 this.items[i].on('update', baseTexture.update, baseTexture);
1138 }
1139 };
1140 /**
1141 * Unset the parent base texture
1142 * @member {PIXI.BaseTexture}
1143 * @override
1144 */
1145 AbstractMultiResource.prototype.unbind = function (baseTexture) {
1146 _super.prototype.unbind.call(this, baseTexture);
1147 for (var i = 0; i < this.length; i++) {
1148 this.items[i].parentTextureArray = null;
1149 this.items[i].off('update', baseTexture.update, baseTexture);
1150 }
1151 };
1152 /**
1153 * Load all the resources simultaneously
1154 * @override
1155 * @return {Promise<void>} When load is resolved
1156 */
1157 AbstractMultiResource.prototype.load = function () {
1158 var _this = this;
1159 if (this._load) {
1160 return this._load;
1161 }
1162 var resources = this.items.map(function (item) { return item.resource; }).filter(function (item) { return item; });
1163 // TODO: also implement load part-by-part strategy
1164 var promises = resources.map(function (item) { return item.load(); });
1165 this._load = Promise.all(promises)
1166 .then(function () {
1167 var _a = _this.items[0], realWidth = _a.realWidth, realHeight = _a.realHeight;
1168 _this.resize(realWidth, realHeight);
1169 return Promise.resolve(_this);
1170 });
1171 return this._load;
1172 };
1173 return AbstractMultiResource;
1174}(Resource));
1175
1176/**
1177 * A resource that contains a number of sources.
1178 *
1179 * @class
1180 * @extends PIXI.Resource
1181 * @memberof PIXI
1182 */
1183var ArrayResource = /** @class */ (function (_super) {
1184 __extends(ArrayResource, _super);
1185 /**
1186 * @param {number|Array<*>} source - Number of items in array or the collection
1187 * of image URLs to use. Can also be resources, image elements, canvas, etc.
1188 * @param {object} [options] - Options to apply to {@link PIXI.autoDetectResource}
1189 * @param {number} [options.width] - Width of the resource
1190 * @param {number} [options.height] - Height of the resource
1191 */
1192 function ArrayResource(source, options) {
1193 var _this = this;
1194 var _a = options || {}, width = _a.width, height = _a.height;
1195 var urls;
1196 var length;
1197 if (Array.isArray(source)) {
1198 urls = source;
1199 length = source.length;
1200 }
1201 else {
1202 length = source;
1203 }
1204 _this = _super.call(this, length, { width: width, height: height }) || this;
1205 if (urls) {
1206 _this.initFromArray(urls, options);
1207 }
1208 return _this;
1209 }
1210 /**
1211 * Set a baseTexture by ID,
1212 * ArrayResource just takes resource from it, nothing more
1213 *
1214 * @param {PIXI.BaseTexture} baseTexture
1215 * @param {number} index - Zero-based index of resource to set
1216 * @return {PIXI.ArrayResource} Instance for chaining
1217 */
1218 ArrayResource.prototype.addBaseTextureAt = function (baseTexture, index) {
1219 if (baseTexture.resource) {
1220 this.addResourceAt(baseTexture.resource, index);
1221 }
1222 else {
1223 throw new Error('ArrayResource does not support RenderTexture');
1224 }
1225 return this;
1226 };
1227 /**
1228 * Add binding
1229 * @member {PIXI.BaseTexture}
1230 * @override
1231 */
1232 ArrayResource.prototype.bind = function (baseTexture) {
1233 _super.prototype.bind.call(this, baseTexture);
1234 baseTexture.target = TARGETS.TEXTURE_2D_ARRAY;
1235 };
1236 /**
1237 * Upload the resources to the GPU.
1238 * @param {PIXI.Renderer} renderer
1239 * @param {PIXI.BaseTexture} texture
1240 * @param {PIXI.GLTexture} glTexture
1241 * @returns {boolean} whether texture was uploaded
1242 */
1243 ArrayResource.prototype.upload = function (renderer, texture, glTexture) {
1244 var _a = this, length = _a.length, itemDirtyIds = _a.itemDirtyIds, items = _a.items;
1245 var gl = renderer.gl;
1246 if (glTexture.dirtyId < 0) {
1247 gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, texture.format, this._width, this._height, length, 0, texture.format, texture.type, null);
1248 }
1249 for (var i = 0; i < length; i++) {
1250 var item = items[i];
1251 if (itemDirtyIds[i] < item.dirtyId) {
1252 itemDirtyIds[i] = item.dirtyId;
1253 if (item.valid) {
1254 gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, // xoffset
1255 0, // yoffset
1256 i, // zoffset
1257 item.resource.width, item.resource.height, 1, texture.format, texture.type, item.resource.source);
1258 }
1259 }
1260 }
1261 return true;
1262 };
1263 return ArrayResource;
1264}(AbstractMultiResource));
1265
1266/**
1267 * Base for all the image/canvas resources
1268 * @class
1269 * @extends PIXI.Resource
1270 * @memberof PIXI
1271 */
1272var BaseImageResource = /** @class */ (function (_super) {
1273 __extends(BaseImageResource, _super);
1274 /**
1275 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|SVGElement} source
1276 */
1277 function BaseImageResource(source) {
1278 var _this = this;
1279 var sourceAny = source;
1280 var width = sourceAny.naturalWidth || sourceAny.videoWidth || sourceAny.width;
1281 var height = sourceAny.naturalHeight || sourceAny.videoHeight || sourceAny.height;
1282 _this = _super.call(this, width, height) || this;
1283 /**
1284 * The source element
1285 * @member {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|SVGElement}
1286 * @readonly
1287 */
1288 _this.source = source;
1289 /**
1290 * If set to `true`, will force `texImage2D` over `texSubImage2D` for uploading.
1291 * Certain types of media (e.g. video) using `texImage2D` is more performant.
1292 * @member {boolean}
1293 * @default false
1294 * @private
1295 */
1296 _this.noSubImage = false;
1297 return _this;
1298 }
1299 /**
1300 * Set cross origin based detecting the url and the crossorigin
1301 * @protected
1302 * @param {HTMLElement} element - Element to apply crossOrigin
1303 * @param {string} url - URL to check
1304 * @param {boolean|string} [crossorigin=true] - Cross origin value to use
1305 */
1306 BaseImageResource.crossOrigin = function (element, url, crossorigin) {
1307 if (crossorigin === undefined && url.indexOf('data:') !== 0) {
1308 element.crossOrigin = determineCrossOrigin(url);
1309 }
1310 else if (crossorigin !== false) {
1311 element.crossOrigin = typeof crossorigin === 'string' ? crossorigin : 'anonymous';
1312 }
1313 };
1314 /**
1315 * Upload the texture to the GPU.
1316 * @param {PIXI.Renderer} renderer - Upload to the renderer
1317 * @param {PIXI.BaseTexture} baseTexture - Reference to parent texture
1318 * @param {PIXI.GLTexture} glTexture
1319 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|SVGElement} [source] - (optional)
1320 * @returns {boolean} true is success
1321 */
1322 BaseImageResource.prototype.upload = function (renderer, baseTexture, glTexture, source) {
1323 var gl = renderer.gl;
1324 var width = baseTexture.realWidth;
1325 var height = baseTexture.realHeight;
1326 source = source || this.source;
1327 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, baseTexture.alphaMode === ALPHA_MODES.UNPACK);
1328 if (!this.noSubImage
1329 && baseTexture.target === gl.TEXTURE_2D
1330 && glTexture.width === width
1331 && glTexture.height === height) {
1332 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, baseTexture.format, baseTexture.type, source);
1333 }
1334 else {
1335 glTexture.width = width;
1336 glTexture.height = height;
1337 gl.texImage2D(baseTexture.target, 0, baseTexture.format, baseTexture.format, baseTexture.type, source);
1338 }
1339 return true;
1340 };
1341 /**
1342 * Checks if source width/height was changed, resize can cause extra baseTexture update.
1343 * Triggers one update in any case.
1344 */
1345 BaseImageResource.prototype.update = function () {
1346 if (this.destroyed) {
1347 return;
1348 }
1349 var source = this.source;
1350 var width = source.naturalWidth || source.videoWidth || source.width;
1351 var height = source.naturalHeight || source.videoHeight || source.height;
1352 this.resize(width, height);
1353 _super.prototype.update.call(this);
1354 };
1355 /**
1356 * Destroy this BaseImageResource
1357 * @override
1358 */
1359 BaseImageResource.prototype.dispose = function () {
1360 this.source = null;
1361 };
1362 return BaseImageResource;
1363}(Resource));
1364
1365/**
1366 * @interface OffscreenCanvas
1367 */
1368/**
1369 * Resource type for HTMLCanvasElement.
1370 * @class
1371 * @extends PIXI.BaseImageResource
1372 * @memberof PIXI
1373 */
1374var CanvasResource = /** @class */ (function (_super) {
1375 __extends(CanvasResource, _super);
1376 /**
1377 * @param {HTMLCanvasElement} source - Canvas element to use
1378 */
1379 // eslint-disable-next-line @typescript-eslint/no-useless-constructor
1380 function CanvasResource(source) {
1381 return _super.call(this, source) || this;
1382 }
1383 /**
1384 * Used to auto-detect the type of resource.
1385 *
1386 * @static
1387 * @param {HTMLCanvasElement|OffscreenCanvas} source - The source object
1388 * @return {boolean} `true` if source is HTMLCanvasElement or OffscreenCanvas
1389 */
1390 CanvasResource.test = function (source) {
1391 var OffscreenCanvas = self.OffscreenCanvas;
1392 // Check for browsers that don't yet support OffscreenCanvas
1393 if (OffscreenCanvas && source instanceof OffscreenCanvas) {
1394 return true;
1395 }
1396 return self.HTMLCanvasElement && source instanceof HTMLCanvasElement;
1397 };
1398 return CanvasResource;
1399}(BaseImageResource));
1400
1401/**
1402 * Resource for a CubeTexture which contains six resources.
1403 *
1404 * @class
1405 * @extends PIXI.ArrayResource
1406 * @memberof PIXI
1407 */
1408var CubeResource = /** @class */ (function (_super) {
1409 __extends(CubeResource, _super);
1410 /**
1411 * @param {Array<string|PIXI.Resource>} [source] - Collection of URLs or resources
1412 * to use as the sides of the cube.
1413 * @param {object} [options] - ImageResource options
1414 * @param {number} [options.width] - Width of resource
1415 * @param {number} [options.height] - Height of resource
1416 * @param {number} [options.autoLoad=true] - Whether to auto-load resources
1417 * @param {number} [options.linkBaseTexture=true] - In case BaseTextures are supplied,
1418 * whether to copy them or use
1419 */
1420 function CubeResource(source, options) {
1421 var _this = this;
1422 var _a = options || {}, width = _a.width, height = _a.height, autoLoad = _a.autoLoad, linkBaseTexture = _a.linkBaseTexture;
1423 if (source && source.length !== CubeResource.SIDES) {
1424 throw new Error("Invalid length. Got " + source.length + ", expected 6");
1425 }
1426 _this = _super.call(this, 6, { width: width, height: height }) || this;
1427 for (var i = 0; i < CubeResource.SIDES; i++) {
1428 _this.items[i].target = TARGETS.TEXTURE_CUBE_MAP_POSITIVE_X + i;
1429 }
1430 /**
1431 * In case BaseTextures are supplied, whether to use same resource or bind baseTexture itself
1432 * @member {boolean}
1433 * @protected
1434 */
1435 _this.linkBaseTexture = linkBaseTexture !== false;
1436 if (source) {
1437 _this.initFromArray(source, options);
1438 }
1439 if (autoLoad !== false) {
1440 _this.load();
1441 }
1442 return _this;
1443 }
1444 /**
1445 * Add binding
1446 *
1447 * @override
1448 * @param {PIXI.BaseTexture} baseTexture - parent base texture
1449 */
1450 CubeResource.prototype.bind = function (baseTexture) {
1451 _super.prototype.bind.call(this, baseTexture);
1452 baseTexture.target = TARGETS.TEXTURE_CUBE_MAP;
1453 };
1454 CubeResource.prototype.addBaseTextureAt = function (baseTexture, index, linkBaseTexture) {
1455 if (linkBaseTexture === undefined) {
1456 linkBaseTexture = this.linkBaseTexture;
1457 }
1458 if (!this.items[index]) {
1459 throw new Error("Index " + index + " is out of bounds");
1460 }
1461 if (!this.linkBaseTexture
1462 || baseTexture.parentTextureArray
1463 || Object.keys(baseTexture._glTextures).length > 0) {
1464 // copy mode
1465 if (baseTexture.resource) {
1466 this.addResourceAt(baseTexture.resource, index);
1467 }
1468 else {
1469 throw new Error("CubeResource does not support copying of renderTexture.");
1470 }
1471 }
1472 else {
1473 // link mode, the difficult one!
1474 baseTexture.target = TARGETS.TEXTURE_CUBE_MAP_POSITIVE_X + index;
1475 baseTexture.parentTextureArray = this.baseTexture;
1476 this.items[index] = baseTexture;
1477 }
1478 if (baseTexture.valid && !this.valid) {
1479 this.resize(baseTexture.realWidth, baseTexture.realHeight);
1480 }
1481 this.items[index] = baseTexture;
1482 return this;
1483 };
1484 /**
1485 * Upload the resource
1486 *
1487 * @returns {boolean} true is success
1488 */
1489 CubeResource.prototype.upload = function (renderer, _baseTexture, glTexture) {
1490 var dirty = this.itemDirtyIds;
1491 for (var i = 0; i < CubeResource.SIDES; i++) {
1492 var side = this.items[i];
1493 if (dirty[i] < side.dirtyId) {
1494 if (side.valid && side.resource) {
1495 side.resource.upload(renderer, side, glTexture);
1496 dirty[i] = side.dirtyId;
1497 }
1498 else if (dirty[i] < -1) {
1499 // either item is not valid yet, either its a renderTexture
1500 // allocate the memory
1501 renderer.gl.texImage2D(side.target, 0, glTexture.internalFormat, _baseTexture.realWidth, _baseTexture.realHeight, 0, _baseTexture.format, glTexture.type, null);
1502 dirty[i] = -1;
1503 }
1504 }
1505 }
1506 return true;
1507 };
1508 /**
1509 * Used to auto-detect the type of resource.
1510 *
1511 * @static
1512 * @param {object} source - The source object
1513 * @return {boolean} `true` if source is an array of 6 elements
1514 */
1515 CubeResource.test = function (source) {
1516 return Array.isArray(source) && source.length === CubeResource.SIDES;
1517 };
1518 /**
1519 * Number of texture sides to store for CubeResources
1520 *
1521 * @name PIXI.CubeResource.SIDES
1522 * @static
1523 * @member {number}
1524 * @default 6
1525 */
1526 CubeResource.SIDES = 6;
1527 return CubeResource;
1528}(AbstractMultiResource));
1529
1530/**
1531 * Resource type for HTMLImageElement.
1532 * @class
1533 * @extends PIXI.BaseImageResource
1534 * @memberof PIXI
1535 */
1536var ImageResource = /** @class */ (function (_super) {
1537 __extends(ImageResource, _super);
1538 /**
1539 * @param {HTMLImageElement|string} source - image source or URL
1540 * @param {object} [options]
1541 * @param {boolean} [options.autoLoad=true] - start loading process
1542 * @param {boolean} [options.createBitmap=PIXI.settings.CREATE_IMAGE_BITMAP] - whether its required to create
1543 * a bitmap before upload
1544 * @param {boolean} [options.crossorigin=true] - Load image using cross origin
1545 * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.UNPACK] - Premultiply image alpha in bitmap
1546 */
1547 function ImageResource(source, options) {
1548 var _this = this;
1549 options = options || {};
1550 if (!(source instanceof HTMLImageElement)) {
1551 var imageElement = new Image();
1552 BaseImageResource.crossOrigin(imageElement, source, options.crossorigin);
1553 imageElement.src = source;
1554 source = imageElement;
1555 }
1556 _this = _super.call(this, source) || this;
1557 // FireFox 68, and possibly other versions, seems like setting the HTMLImageElement#width and #height
1558 // to non-zero values before its loading completes if images are in a cache.
1559 // Because of this, need to set the `_width` and the `_height` to zero to avoid uploading incomplete images.
1560 // Please refer to the issue #5968 (https://github.com/pixijs/pixi.js/issues/5968).
1561 if (!source.complete && !!_this._width && !!_this._height) {
1562 _this._width = 0;
1563 _this._height = 0;
1564 }
1565 /**
1566 * URL of the image source
1567 * @member {string}
1568 */
1569 _this.url = source.src;
1570 /**
1571 * When process is completed
1572 * @member {Promise<void>}
1573 * @private
1574 */
1575 _this._process = null;
1576 /**
1577 * If the image should be disposed after upload
1578 * @member {boolean}
1579 * @default false
1580 */
1581 _this.preserveBitmap = false;
1582 /**
1583 * If capable, convert the image using createImageBitmap API
1584 * @member {boolean}
1585 * @default PIXI.settings.CREATE_IMAGE_BITMAP
1586 */
1587 _this.createBitmap = (options.createBitmap !== undefined
1588 ? options.createBitmap : settings.CREATE_IMAGE_BITMAP) && !!self.createImageBitmap;
1589 /**
1590 * Controls texture alphaMode field
1591 * Copies from options
1592 * Default is `null`, copies option from baseTexture
1593 *
1594 * @member {PIXI.ALPHA_MODES|null}
1595 * @readonly
1596 */
1597 _this.alphaMode = typeof options.alphaMode === 'number' ? options.alphaMode : null;
1598 /**
1599 * The ImageBitmap element created for HTMLImageElement
1600 * @member {ImageBitmap}
1601 * @default null
1602 */
1603 _this.bitmap = null;
1604 /**
1605 * Promise when loading
1606 * @member {Promise<void>}
1607 * @private
1608 * @default null
1609 */
1610 _this._load = null;
1611 if (options.autoLoad !== false) {
1612 _this.load();
1613 }
1614 return _this;
1615 }
1616 /**
1617 * returns a promise when image will be loaded and processed
1618 *
1619 * @param {boolean} [createBitmap] - whether process image into bitmap
1620 * @returns {Promise<void>}
1621 */
1622 ImageResource.prototype.load = function (createBitmap) {
1623 var _this = this;
1624 if (this._load) {
1625 return this._load;
1626 }
1627 if (createBitmap !== undefined) {
1628 this.createBitmap = createBitmap;
1629 }
1630 this._load = new Promise(function (resolve, reject) {
1631 var source = _this.source;
1632 _this.url = source.src;
1633 var completed = function () {
1634 if (_this.destroyed) {
1635 return;
1636 }
1637 source.onload = null;
1638 source.onerror = null;
1639 _this.resize(source.width, source.height);
1640 _this._load = null;
1641 if (_this.createBitmap) {
1642 resolve(_this.process());
1643 }
1644 else {
1645 resolve(_this);
1646 }
1647 };
1648 if (source.complete && source.src) {
1649 completed();
1650 }
1651 else {
1652 source.onload = completed;
1653 source.onerror = function (event) {
1654 // Avoids Promise freezing when resource broken
1655 reject(event);
1656 _this.onError.emit(event);
1657 };
1658 }
1659 });
1660 return this._load;
1661 };
1662 /**
1663 * Called when we need to convert image into BitmapImage.
1664 * Can be called multiple times, real promise is cached inside.
1665 *
1666 * @returns {Promise<void>} cached promise to fill that bitmap
1667 */
1668 ImageResource.prototype.process = function () {
1669 var _this = this;
1670 var source = this.source;
1671 if (this._process !== null) {
1672 return this._process;
1673 }
1674 if (this.bitmap !== null || !self.createImageBitmap) {
1675 return Promise.resolve(this);
1676 }
1677 this._process = self.createImageBitmap(source, 0, 0, source.width, source.height, {
1678 premultiplyAlpha: this.alphaMode === ALPHA_MODES.UNPACK ? 'premultiply' : 'none',
1679 })
1680 .then(function (bitmap) {
1681 if (_this.destroyed) {
1682 return Promise.reject();
1683 }
1684 _this.bitmap = bitmap;
1685 _this.update();
1686 _this._process = null;
1687 return Promise.resolve(_this);
1688 });
1689 return this._process;
1690 };
1691 /**
1692 * Upload the image resource to GPU.
1693 *
1694 * @param {PIXI.Renderer} renderer - Renderer to upload to
1695 * @param {PIXI.BaseTexture} baseTexture - BaseTexture for this resource
1696 * @param {PIXI.GLTexture} glTexture - GLTexture to use
1697 * @returns {boolean} true is success
1698 */
1699 ImageResource.prototype.upload = function (renderer, baseTexture, glTexture) {
1700 if (typeof this.alphaMode === 'number') {
1701 // bitmap stores unpack premultiply flag, we dont have to notify texImage2D about it
1702 baseTexture.alphaMode = this.alphaMode;
1703 }
1704 if (!this.createBitmap) {
1705 return _super.prototype.upload.call(this, renderer, baseTexture, glTexture);
1706 }
1707 if (!this.bitmap) {
1708 // yeah, ignore the output
1709 this.process();
1710 if (!this.bitmap) {
1711 return false;
1712 }
1713 }
1714 _super.prototype.upload.call(this, renderer, baseTexture, glTexture, this.bitmap);
1715 if (!this.preserveBitmap) {
1716 // checks if there are other renderers that possibly need this bitmap
1717 var flag = true;
1718 var glTextures = baseTexture._glTextures;
1719 for (var key in glTextures) {
1720 var otherTex = glTextures[key];
1721 if (otherTex !== glTexture && otherTex.dirtyId !== baseTexture.dirtyId) {
1722 flag = false;
1723 break;
1724 }
1725 }
1726 if (flag) {
1727 if (this.bitmap.close) {
1728 this.bitmap.close();
1729 }
1730 this.bitmap = null;
1731 }
1732 }
1733 return true;
1734 };
1735 /**
1736 * Destroys this texture
1737 * @override
1738 */
1739 ImageResource.prototype.dispose = function () {
1740 this.source.onload = null;
1741 this.source.onerror = null;
1742 _super.prototype.dispose.call(this);
1743 if (this.bitmap) {
1744 this.bitmap.close();
1745 this.bitmap = null;
1746 }
1747 this._process = null;
1748 this._load = null;
1749 };
1750 /**
1751 * Used to auto-detect the type of resource.
1752 *
1753 * @static
1754 * @param {string|HTMLImageElement} source - The source object
1755 * @return {boolean} `true` if source is string or HTMLImageElement
1756 */
1757 ImageResource.test = function (source) {
1758 return typeof source === 'string' || source instanceof HTMLImageElement;
1759 };
1760 return ImageResource;
1761}(BaseImageResource));
1762
1763/**
1764 * Resource type for SVG elements and graphics.
1765 * @class
1766 * @extends PIXI.BaseImageResource
1767 * @memberof PIXI
1768 */
1769var SVGResource = /** @class */ (function (_super) {
1770 __extends(SVGResource, _super);
1771 /**
1772 * @param {string} source - Base64 encoded SVG element or URL for SVG file.
1773 * @param {object} [options] - Options to use
1774 * @param {number} [options.scale=1] - Scale to apply to SVG. Overridden by...
1775 * @param {number} [options.width] - Rasterize SVG this wide. Aspect ratio preserved if height not specified.
1776 * @param {number} [options.height] - Rasterize SVG this high. Aspect ratio preserved if width not specified.
1777 * @param {boolean} [options.autoLoad=true] - Start loading right away.
1778 */
1779 function SVGResource(sourceBase64, options) {
1780 var _this = this;
1781 options = options || {};
1782 _this = _super.call(this, document.createElement('canvas')) || this;
1783 _this._width = 0;
1784 _this._height = 0;
1785 /**
1786 * Base64 encoded SVG element or URL for SVG file
1787 * @readonly
1788 * @member {string}
1789 */
1790 _this.svg = sourceBase64;
1791 /**
1792 * The source scale to apply when rasterizing on load
1793 * @readonly
1794 * @member {number}
1795 */
1796 _this.scale = options.scale || 1;
1797 /**
1798 * A width override for rasterization on load
1799 * @readonly
1800 * @member {number}
1801 */
1802 _this._overrideWidth = options.width;
1803 /**
1804 * A height override for rasterization on load
1805 * @readonly
1806 * @member {number}
1807 */
1808 _this._overrideHeight = options.height;
1809 /**
1810 * Call when completely loaded
1811 * @private
1812 * @member {function}
1813 */
1814 _this._resolve = null;
1815 /**
1816 * Cross origin value to use
1817 * @private
1818 * @member {boolean|string}
1819 */
1820 _this._crossorigin = options.crossorigin;
1821 /**
1822 * Promise when loading
1823 * @member {Promise<void>}
1824 * @private
1825 * @default null
1826 */
1827 _this._load = null;
1828 if (options.autoLoad !== false) {
1829 _this.load();
1830 }
1831 return _this;
1832 }
1833 SVGResource.prototype.load = function () {
1834 var _this = this;
1835 if (this._load) {
1836 return this._load;
1837 }
1838 this._load = new Promise(function (resolve) {
1839 // Save this until after load is finished
1840 _this._resolve = function () {
1841 _this.resize(_this.source.width, _this.source.height);
1842 resolve(_this);
1843 };
1844 // Convert SVG inline string to data-uri
1845 if ((/^\<svg/).test(_this.svg.trim())) {
1846 if (!btoa) {
1847 throw new Error('Your browser doesn\'t support base64 conversions.');
1848 }
1849 _this.svg = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(_this.svg)));
1850 }
1851 _this._loadSvg();
1852 });
1853 return this._load;
1854 };
1855 /**
1856 * Loads an SVG image from `imageUrl` or `data URL`.
1857 *
1858 * @private
1859 */
1860 SVGResource.prototype._loadSvg = function () {
1861 var _this = this;
1862 var tempImage = new Image();
1863 BaseImageResource.crossOrigin(tempImage, this.svg, this._crossorigin);
1864 tempImage.src = this.svg;
1865 tempImage.onerror = function (event) {
1866 if (!_this._resolve) {
1867 return;
1868 }
1869 tempImage.onerror = null;
1870 _this.onError.emit(event);
1871 };
1872 tempImage.onload = function () {
1873 if (!_this._resolve) {
1874 return;
1875 }
1876 var svgWidth = tempImage.width;
1877 var svgHeight = tempImage.height;
1878 if (!svgWidth || !svgHeight) {
1879 throw new Error('The SVG image must have width and height defined (in pixels), canvas API needs them.');
1880 }
1881 // Set render size
1882 var width = svgWidth * _this.scale;
1883 var height = svgHeight * _this.scale;
1884 if (_this._overrideWidth || _this._overrideHeight) {
1885 width = _this._overrideWidth || _this._overrideHeight / svgHeight * svgWidth;
1886 height = _this._overrideHeight || _this._overrideWidth / svgWidth * svgHeight;
1887 }
1888 width = Math.round(width);
1889 height = Math.round(height);
1890 // Create a canvas element
1891 var canvas = _this.source;
1892 canvas.width = width;
1893 canvas.height = height;
1894 canvas._pixiId = "canvas_" + uid();
1895 // Draw the Svg to the canvas
1896 canvas
1897 .getContext('2d')
1898 .drawImage(tempImage, 0, 0, svgWidth, svgHeight, 0, 0, width, height);
1899 _this._resolve();
1900 _this._resolve = null;
1901 };
1902 };
1903 /**
1904 * Get size from an svg string using regexp.
1905 *
1906 * @method
1907 * @param {string} svgString - a serialized svg element
1908 * @return {PIXI.ISize} image extension
1909 */
1910 SVGResource.getSize = function (svgString) {
1911 var sizeMatch = SVGResource.SVG_SIZE.exec(svgString);
1912 var size = {};
1913 if (sizeMatch) {
1914 size[sizeMatch[1]] = Math.round(parseFloat(sizeMatch[3]));
1915 size[sizeMatch[5]] = Math.round(parseFloat(sizeMatch[7]));
1916 }
1917 return size;
1918 };
1919 /**
1920 * Destroys this texture
1921 * @override
1922 */
1923 SVGResource.prototype.dispose = function () {
1924 _super.prototype.dispose.call(this);
1925 this._resolve = null;
1926 this._crossorigin = null;
1927 };
1928 /**
1929 * Used to auto-detect the type of resource.
1930 *
1931 * @static
1932 * @param {*} source - The source object
1933 * @param {string} extension - The extension of source, if set
1934 */
1935 SVGResource.test = function (source, extension) {
1936 // url file extension is SVG
1937 return extension === 'svg'
1938 // source is SVG data-uri
1939 || (typeof source === 'string' && (/^data:image\/svg\+xml(;(charset=utf8|utf8))?;base64/).test(source))
1940 // source is SVG inline
1941 || (typeof source === 'string' && source.indexOf('<svg') === 0);
1942 };
1943 /**
1944 * RegExp for SVG size.
1945 *
1946 * @static
1947 * @constant {RegExp|string} SVG_SIZE
1948 * @memberof PIXI.SVGResource
1949 * @example &lt;svg width="100" height="100"&gt;&lt;/svg&gt;
1950 */
1951 SVGResource.SVG_SIZE = /<svg[^>]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*>/i; // eslint-disable-line max-len
1952 return SVGResource;
1953}(BaseImageResource));
1954
1955/**
1956 * Resource type for HTMLVideoElement.
1957 * @class
1958 * @extends PIXI.BaseImageResource
1959 * @memberof PIXI
1960 */
1961var VideoResource = /** @class */ (function (_super) {
1962 __extends(VideoResource, _super);
1963 /**
1964 * @param {HTMLVideoElement|object|string|Array<string|object>} source - Video element to use.
1965 * @param {object} [options] - Options to use
1966 * @param {boolean} [options.autoLoad=true] - Start loading the video immediately
1967 * @param {boolean} [options.autoPlay=true] - Start playing video immediately
1968 * @param {number} [options.updateFPS=0] - How many times a second to update the texture from the video.
1969 * Leave at 0 to update at every render.
1970 * @param {boolean} [options.crossorigin=true] - Load image using cross origin
1971 */
1972 function VideoResource(source, options) {
1973 var _this = this;
1974 options = options || {};
1975 if (!(source instanceof HTMLVideoElement)) {
1976 var videoElement = document.createElement('video');
1977 // workaround for https://github.com/pixijs/pixi.js/issues/5996
1978 videoElement.setAttribute('preload', 'auto');
1979 videoElement.setAttribute('webkit-playsinline', '');
1980 videoElement.setAttribute('playsinline', '');
1981 if (typeof source === 'string') {
1982 source = [source];
1983 }
1984 var firstSrc = source[0].src || source[0];
1985 BaseImageResource.crossOrigin(videoElement, firstSrc, options.crossorigin);
1986 // array of objects or strings
1987 for (var i = 0; i < source.length; ++i) {
1988 var sourceElement = document.createElement('source');
1989 var _a = source[i], src = _a.src, mime = _a.mime;
1990 src = src || source[i];
1991 var baseSrc = src.split('?').shift().toLowerCase();
1992 var ext = baseSrc.substr(baseSrc.lastIndexOf('.') + 1);
1993 mime = mime || VideoResource.MIME_TYPES[ext] || "video/" + ext;
1994 sourceElement.src = src;
1995 sourceElement.type = mime;
1996 videoElement.appendChild(sourceElement);
1997 }
1998 // Override the source
1999 source = videoElement;
2000 }
2001 _this = _super.call(this, source) || this;
2002 _this.noSubImage = true;
2003 /**
2004 * `true` to use PIXI.Ticker.shared to auto update the base texture.
2005 *
2006 * @type {boolean}
2007 * @default true
2008 * @private
2009 */
2010 _this._autoUpdate = true;
2011 /**
2012 * `true` if the instance is currently connected to PIXI.Ticker.shared to auto update the base texture.
2013 *
2014 * @type {boolean}
2015 * @default false
2016 * @private
2017 */
2018 _this._isConnectedToTicker = false;
2019 _this._updateFPS = options.updateFPS || 0;
2020 _this._msToNextUpdate = 0;
2021 /**
2022 * When set to true will automatically play videos used by this texture once
2023 * they are loaded. If false, it will not modify the playing state.
2024 *
2025 * @member {boolean}
2026 * @default true
2027 */
2028 _this.autoPlay = options.autoPlay !== false;
2029 /**
2030 * Promise when loading
2031 * @member {Promise<void>}
2032 * @private
2033 * @default null
2034 */
2035 _this._load = null;
2036 /**
2037 * Callback when completed with load.
2038 * @member {function}
2039 * @private
2040 */
2041 _this._resolve = null;
2042 // Bind for listeners
2043 _this._onCanPlay = _this._onCanPlay.bind(_this);
2044 _this._onError = _this._onError.bind(_this);
2045 if (options.autoLoad !== false) {
2046 _this.load();
2047 }
2048 return _this;
2049 }
2050 /**
2051 * Trigger updating of the texture
2052 *
2053 * @param {number} [deltaTime=0] - time delta since last tick
2054 */
2055 VideoResource.prototype.update = function (_deltaTime) {
2056 if (!this.destroyed) {
2057 // account for if video has had its playbackRate changed
2058 var elapsedMS = Ticker.shared.elapsedMS * this.source.playbackRate;
2059 this._msToNextUpdate = Math.floor(this._msToNextUpdate - elapsedMS);
2060 if (!this._updateFPS || this._msToNextUpdate <= 0) {
2061 _super.prototype.update.call(this);
2062 this._msToNextUpdate = this._updateFPS ? Math.floor(1000 / this._updateFPS) : 0;
2063 }
2064 }
2065 };
2066 /**
2067 * Start preloading the video resource.
2068 *
2069 * @protected
2070 * @return {Promise<void>} Handle the validate event
2071 */
2072 VideoResource.prototype.load = function () {
2073 var _this = this;
2074 if (this._load) {
2075 return this._load;
2076 }
2077 var source = this.source;
2078 if ((source.readyState === source.HAVE_ENOUGH_DATA || source.readyState === source.HAVE_FUTURE_DATA)
2079 && source.width && source.height) {
2080 source.complete = true;
2081 }
2082 source.addEventListener('play', this._onPlayStart.bind(this));
2083 source.addEventListener('pause', this._onPlayStop.bind(this));
2084 if (!this._isSourceReady()) {
2085 source.addEventListener('canplay', this._onCanPlay);
2086 source.addEventListener('canplaythrough', this._onCanPlay);
2087 source.addEventListener('error', this._onError, true);
2088 }
2089 else {
2090 this._onCanPlay();
2091 }
2092 this._load = new Promise(function (resolve) {
2093 if (_this.valid) {
2094 resolve(_this);
2095 }
2096 else {
2097 _this._resolve = resolve;
2098 source.load();
2099 }
2100 });
2101 return this._load;
2102 };
2103 /**
2104 * Handle video error events.
2105 *
2106 * @private
2107 */
2108 VideoResource.prototype._onError = function (event) {
2109 this.source.removeEventListener('error', this._onError, true);
2110 this.onError.emit(event);
2111 };
2112 /**
2113 * Returns true if the underlying source is playing.
2114 *
2115 * @private
2116 * @return {boolean} True if playing.
2117 */
2118 VideoResource.prototype._isSourcePlaying = function () {
2119 var source = this.source;
2120 return (source.currentTime > 0 && source.paused === false && source.ended === false && source.readyState > 2);
2121 };
2122 /**
2123 * Returns true if the underlying source is ready for playing.
2124 *
2125 * @private
2126 * @return {boolean} True if ready.
2127 */
2128 VideoResource.prototype._isSourceReady = function () {
2129 var source = this.source;
2130 return source.readyState === 3 || source.readyState === 4;
2131 };
2132 /**
2133 * Runs the update loop when the video is ready to play
2134 *
2135 * @private
2136 */
2137 VideoResource.prototype._onPlayStart = function () {
2138 // Just in case the video has not received its can play even yet..
2139 if (!this.valid) {
2140 this._onCanPlay();
2141 }
2142 if (this.autoUpdate && !this._isConnectedToTicker) {
2143 Ticker.shared.add(this.update, this);
2144 this._isConnectedToTicker = true;
2145 }
2146 };
2147 /**
2148 * Fired when a pause event is triggered, stops the update loop
2149 *
2150 * @private
2151 */
2152 VideoResource.prototype._onPlayStop = function () {
2153 if (this._isConnectedToTicker) {
2154 Ticker.shared.remove(this.update, this);
2155 this._isConnectedToTicker = false;
2156 }
2157 };
2158 /**
2159 * Fired when the video is loaded and ready to play
2160 *
2161 * @private
2162 */
2163 VideoResource.prototype._onCanPlay = function () {
2164 var source = this.source;
2165 source.removeEventListener('canplay', this._onCanPlay);
2166 source.removeEventListener('canplaythrough', this._onCanPlay);
2167 var valid = this.valid;
2168 this.resize(source.videoWidth, source.videoHeight);
2169 // prevent multiple loaded dispatches..
2170 if (!valid && this._resolve) {
2171 this._resolve(this);
2172 this._resolve = null;
2173 }
2174 if (this._isSourcePlaying()) {
2175 this._onPlayStart();
2176 }
2177 else if (this.autoPlay) {
2178 source.play();
2179 }
2180 };
2181 /**
2182 * Destroys this texture
2183 * @override
2184 */
2185 VideoResource.prototype.dispose = function () {
2186 if (this._isConnectedToTicker) {
2187 Ticker.shared.remove(this.update, this);
2188 }
2189 var source = this.source;
2190 if (source) {
2191 source.removeEventListener('error', this._onError, true);
2192 source.pause();
2193 source.src = '';
2194 source.load();
2195 }
2196 _super.prototype.dispose.call(this);
2197 };
2198 Object.defineProperty(VideoResource.prototype, "autoUpdate", {
2199 /**
2200 * Should the base texture automatically update itself, set to true by default
2201 *
2202 * @member {boolean}
2203 */
2204 get: function () {
2205 return this._autoUpdate;
2206 },
2207 set: function (value) {
2208 if (value !== this._autoUpdate) {
2209 this._autoUpdate = value;
2210 if (!this._autoUpdate && this._isConnectedToTicker) {
2211 Ticker.shared.remove(this.update, this);
2212 this._isConnectedToTicker = false;
2213 }
2214 else if (this._autoUpdate && !this._isConnectedToTicker && this._isSourcePlaying()) {
2215 Ticker.shared.add(this.update, this);
2216 this._isConnectedToTicker = true;
2217 }
2218 }
2219 },
2220 enumerable: false,
2221 configurable: true
2222 });
2223 Object.defineProperty(VideoResource.prototype, "updateFPS", {
2224 /**
2225 * How many times a second to update the texture from the video. Leave at 0 to update at every render.
2226 * A lower fps can help performance, as updating the texture at 60fps on a 30ps video may not be efficient.
2227 *
2228 * @member {number}
2229 */
2230 get: function () {
2231 return this._updateFPS;
2232 },
2233 set: function (value) {
2234 if (value !== this._updateFPS) {
2235 this._updateFPS = value;
2236 }
2237 },
2238 enumerable: false,
2239 configurable: true
2240 });
2241 /**
2242 * Used to auto-detect the type of resource.
2243 *
2244 * @static
2245 * @param {*} source - The source object
2246 * @param {string} extension - The extension of source, if set
2247 * @return {boolean} `true` if video source
2248 */
2249 VideoResource.test = function (source, extension) {
2250 return (self.HTMLVideoElement && source instanceof HTMLVideoElement)
2251 || VideoResource.TYPES.indexOf(extension) > -1;
2252 };
2253 /**
2254 * List of common video file extensions supported by VideoResource.
2255 * @constant
2256 * @member {Array<string>}
2257 * @static
2258 * @readonly
2259 */
2260 VideoResource.TYPES = ['mp4', 'm4v', 'webm', 'ogg', 'ogv', 'h264', 'avi', 'mov'];
2261 /**
2262 * Map of video MIME types that can't be directly derived from file extensions.
2263 * @constant
2264 * @member {object}
2265 * @static
2266 * @readonly
2267 */
2268 VideoResource.MIME_TYPES = {
2269 ogv: 'video/ogg',
2270 mov: 'video/quicktime',
2271 m4v: 'video/mp4',
2272 };
2273 return VideoResource;
2274}(BaseImageResource));
2275
2276/**
2277 * Resource type for ImageBitmap.
2278 * @class
2279 * @extends PIXI.BaseImageResource
2280 * @memberof PIXI
2281 */
2282var ImageBitmapResource = /** @class */ (function (_super) {
2283 __extends(ImageBitmapResource, _super);
2284 /**
2285 * @param {ImageBitmap} source - Image element to use
2286 */
2287 // eslint-disable-next-line @typescript-eslint/no-useless-constructor
2288 function ImageBitmapResource(source) {
2289 return _super.call(this, source) || this;
2290 }
2291 /**
2292 * Used to auto-detect the type of resource.
2293 *
2294 * @static
2295 * @param {ImageBitmap} source - The source object
2296 * @return {boolean} `true` if source is an ImageBitmap
2297 */
2298 ImageBitmapResource.test = function (source) {
2299 return !!self.createImageBitmap && source instanceof ImageBitmap;
2300 };
2301 return ImageBitmapResource;
2302}(BaseImageResource));
2303
2304INSTALLED.push(ImageResource, ImageBitmapResource, CanvasResource, VideoResource, SVGResource, BufferResource, CubeResource, ArrayResource);
2305
2306var _resources = {
2307 __proto__: null,
2308 Resource: Resource,
2309 BaseImageResource: BaseImageResource,
2310 INSTALLED: INSTALLED,
2311 autoDetectResource: autoDetectResource,
2312 AbstractMultiResource: AbstractMultiResource,
2313 ArrayResource: ArrayResource,
2314 BufferResource: BufferResource,
2315 CanvasResource: CanvasResource,
2316 CubeResource: CubeResource,
2317 ImageResource: ImageResource,
2318 SVGResource: SVGResource,
2319 VideoResource: VideoResource,
2320 ImageBitmapResource: ImageBitmapResource
2321};
2322
2323/**
2324 * System is a base class used for extending systems used by the {@link PIXI.Renderer}
2325 *
2326 * @see PIXI.Renderer#addSystem
2327 * @class
2328 * @memberof PIXI
2329 */
2330var System = /** @class */ (function () {
2331 /**
2332 * @param {Renderer} renderer - The renderer this manager works for.
2333 */
2334 function System(renderer) {
2335 /**
2336 * The renderer this manager works for.
2337 *
2338 * @member {PIXI.Renderer}
2339 */
2340 this.renderer = renderer;
2341 }
2342 /**
2343 * Generic destroy methods to be overridden by the subclass
2344 */
2345 System.prototype.destroy = function () {
2346 this.renderer = null;
2347 };
2348 return System;
2349}());
2350
2351/**
2352 * Resource type for DepthTexture.
2353 * @class
2354 * @extends PIXI.BufferResource
2355 * @memberof PIXI
2356 */
2357var DepthResource = /** @class */ (function (_super) {
2358 __extends(DepthResource, _super);
2359 function DepthResource() {
2360 return _super !== null && _super.apply(this, arguments) || this;
2361 }
2362 /**
2363 * Upload the texture to the GPU.
2364 * @param {PIXI.Renderer} renderer - Upload to the renderer
2365 * @param {PIXI.BaseTexture} baseTexture - Reference to parent texture
2366 * @param {PIXI.GLTexture} glTexture - glTexture
2367 * @returns {boolean} true is success
2368 */
2369 DepthResource.prototype.upload = function (renderer, baseTexture, glTexture) {
2370 var gl = renderer.gl;
2371 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, baseTexture.alphaMode === ALPHA_MODES.UNPACK);
2372 if (glTexture.width === baseTexture.width && glTexture.height === baseTexture.height) {
2373 gl.texSubImage2D(baseTexture.target, 0, 0, 0, baseTexture.width, baseTexture.height, baseTexture.format, baseTexture.type, this.data);
2374 }
2375 else {
2376 glTexture.width = baseTexture.width;
2377 glTexture.height = baseTexture.height;
2378 gl.texImage2D(baseTexture.target, 0,
2379 // gl.DEPTH_COMPONENT16 Needed for depth to render properly in webgl2.0
2380 renderer.context.webGLVersion === 1 ? gl.DEPTH_COMPONENT : gl.DEPTH_COMPONENT16, baseTexture.width, baseTexture.height, 0, baseTexture.format, baseTexture.type, this.data);
2381 }
2382 return true;
2383 };
2384 return DepthResource;
2385}(BufferResource));
2386
2387/**
2388 * A framebuffer can be used to render contents off of the screen. {@link PIXI.BaseRenderTexture} uses
2389 * one internally to render into itself. You can attach a depth or stencil buffer to a framebuffer.
2390 *
2391 * On WebGL 2 machines, shaders can output to multiple textures simultaneously with GLSL 300 ES.
2392 *
2393 * @class
2394 * @memberof PIXI
2395 */
2396var Framebuffer = /** @class */ (function () {
2397 /**
2398 * @param {number} width - Width of the frame buffer
2399 * @param {number} height - Height of the frame buffer
2400 */
2401 function Framebuffer(width, height) {
2402 /**
2403 * Width of framebuffer in pixels
2404 * @member {number}
2405 */
2406 this.width = Math.ceil(width || 100);
2407 /**
2408 * Height of framebuffer in pixels
2409 * @member {number}
2410 */
2411 this.height = Math.ceil(height || 100);
2412 this.stencil = false;
2413 this.depth = false;
2414 this.dirtyId = 0;
2415 this.dirtyFormat = 0;
2416 this.dirtySize = 0;
2417 this.depthTexture = null;
2418 this.colorTextures = [];
2419 this.glFramebuffers = {};
2420 this.disposeRunner = new Runner('disposeFramebuffer');
2421 /**
2422 * Desired number of samples for antialiasing. 0 means AA should not be used.
2423 *
2424 * Experimental WebGL2 feature, allows to use antialiasing in individual renderTextures.
2425 * Antialiasing is the same as for main buffer with renderer `antialias:true` options.
2426 * Seriously affects GPU memory consumption and GPU performance.
2427 *
2428 *```js
2429 * renderTexture.framebuffer.multisample = PIXI.MSAA_QUALITY.HIGH;
2430 * //...
2431 * renderer.render(myContainer, {renderTexture});
2432 * renderer.framebuffer.blit(); // copies data from MSAA framebuffer to texture
2433 * ```
2434 *
2435 * @member {PIXI.MSAA_QUALITY}
2436 * @default PIXI.MSAA_QUALITY.NONE
2437 */
2438 this.multisample = MSAA_QUALITY.NONE;
2439 }
2440 Object.defineProperty(Framebuffer.prototype, "colorTexture", {
2441 /**
2442 * Reference to the colorTexture.
2443 *
2444 * @member {PIXI.BaseTexture[]}
2445 * @readonly
2446 */
2447 get: function () {
2448 return this.colorTextures[0];
2449 },
2450 enumerable: false,
2451 configurable: true
2452 });
2453 /**
2454 * Add texture to the colorTexture array
2455 *
2456 * @param {number} [index=0] - Index of the array to add the texture to
2457 * @param {PIXI.BaseTexture} [texture] - Texture to add to the array
2458 */
2459 Framebuffer.prototype.addColorTexture = function (index, texture) {
2460 if (index === void 0) { index = 0; }
2461 // TODO add some validation to the texture - same width / height etc?
2462 this.colorTextures[index] = texture || new BaseTexture(null, {
2463 scaleMode: SCALE_MODES.NEAREST,
2464 resolution: 1,
2465 mipmap: MIPMAP_MODES.OFF,
2466 width: this.width,
2467 height: this.height,
2468 });
2469 this.dirtyId++;
2470 this.dirtyFormat++;
2471 return this;
2472 };
2473 /**
2474 * Add a depth texture to the frame buffer
2475 *
2476 * @param {PIXI.BaseTexture} [texture] - Texture to add
2477 */
2478 Framebuffer.prototype.addDepthTexture = function (texture) {
2479 /* eslint-disable max-len */
2480 this.depthTexture = texture || new BaseTexture(new DepthResource(null, { width: this.width, height: this.height }), {
2481 scaleMode: SCALE_MODES.NEAREST,
2482 resolution: 1,
2483 width: this.width,
2484 height: this.height,
2485 mipmap: MIPMAP_MODES.OFF,
2486 format: FORMATS.DEPTH_COMPONENT,
2487 type: TYPES.UNSIGNED_SHORT,
2488 });
2489 this.dirtyId++;
2490 this.dirtyFormat++;
2491 return this;
2492 };
2493 /**
2494 * Enable depth on the frame buffer
2495 */
2496 Framebuffer.prototype.enableDepth = function () {
2497 this.depth = true;
2498 this.dirtyId++;
2499 this.dirtyFormat++;
2500 return this;
2501 };
2502 /**
2503 * Enable stencil on the frame buffer
2504 */
2505 Framebuffer.prototype.enableStencil = function () {
2506 this.stencil = true;
2507 this.dirtyId++;
2508 this.dirtyFormat++;
2509 return this;
2510 };
2511 /**
2512 * Resize the frame buffer
2513 *
2514 * @param {number} width - Width of the frame buffer to resize to
2515 * @param {number} height - Height of the frame buffer to resize to
2516 */
2517 Framebuffer.prototype.resize = function (width, height) {
2518 width = Math.ceil(width);
2519 height = Math.ceil(height);
2520 if (width === this.width && height === this.height)
2521 { return; }
2522 this.width = width;
2523 this.height = height;
2524 this.dirtyId++;
2525 this.dirtySize++;
2526 for (var i = 0; i < this.colorTextures.length; i++) {
2527 var texture = this.colorTextures[i];
2528 var resolution = texture.resolution;
2529 // take into account the fact the texture may have a different resolution..
2530 texture.setSize(width / resolution, height / resolution);
2531 }
2532 if (this.depthTexture) {
2533 var resolution = this.depthTexture.resolution;
2534 this.depthTexture.setSize(width / resolution, height / resolution);
2535 }
2536 };
2537 /**
2538 * Disposes WebGL resources that are connected to this geometry
2539 */
2540 Framebuffer.prototype.dispose = function () {
2541 this.disposeRunner.emit(this, false);
2542 };
2543 /**
2544 * Destroys and removes the depth texture added to this framebuffer.
2545 */
2546 Framebuffer.prototype.destroyDepthTexture = function () {
2547 if (this.depthTexture) {
2548 this.depthTexture.destroy();
2549 this.depthTexture = null;
2550 ++this.dirtyId;
2551 ++this.dirtyFormat;
2552 }
2553 };
2554 return Framebuffer;
2555}());
2556
2557/**
2558 * A BaseRenderTexture is a special texture that allows any PixiJS display object to be rendered to it.
2559 *
2560 * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded
2561 * otherwise black rectangles will be drawn instead.
2562 *
2563 * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position
2564 * and rotation of the given Display Objects is ignored. For example:
2565 *
2566 * ```js
2567 * let renderer = PIXI.autoDetectRenderer();
2568 * let baseRenderTexture = new PIXI.BaseRenderTexture({ width: 800, height: 600 });
2569 * let renderTexture = new PIXI.RenderTexture(baseRenderTexture);
2570 * let sprite = PIXI.Sprite.from("spinObj_01.png");
2571 *
2572 * sprite.position.x = 800/2;
2573 * sprite.position.y = 600/2;
2574 * sprite.anchor.x = 0.5;
2575 * sprite.anchor.y = 0.5;
2576 *
2577 * renderer.render(sprite, {renderTexture});
2578 * ```
2579 *
2580 * The Sprite in this case will be rendered using its local transform. To render this sprite at 0,0
2581 * you can clear the transform
2582 *
2583 * ```js
2584 *
2585 * sprite.setTransform()
2586 *
2587 * let baseRenderTexture = new PIXI.BaseRenderTexture({ width: 100, height: 100 });
2588 * let renderTexture = new PIXI.RenderTexture(baseRenderTexture);
2589 *
2590 * renderer.render(sprite, {renderTexture}); // Renders to center of RenderTexture
2591 * ```
2592 *
2593 * @class
2594 * @extends PIXI.BaseTexture
2595 * @memberof PIXI
2596 */
2597var BaseRenderTexture = /** @class */ (function (_super) {
2598 __extends(BaseRenderTexture, _super);
2599 /**
2600 * @param {object} [options]
2601 * @param {number} [options.width=100] - The width of the base render texture.
2602 * @param {number} [options.height=100] - The height of the base render texture.
2603 * @param {PIXI.SCALE_MODES} [options.scaleMode] - See {@link PIXI.SCALE_MODES} for possible values.
2604 * @param {number} [options.resolution=1] - The resolution / device pixel ratio of the texture being generated.
2605 */
2606 function BaseRenderTexture(options) {
2607 var _this = this;
2608 if (typeof options === 'number') {
2609 /* eslint-disable prefer-rest-params */
2610 // Backward compatibility of signature
2611 var width_1 = arguments[0];
2612 var height_1 = arguments[1];
2613 var scaleMode = arguments[2];
2614 var resolution = arguments[3];
2615 options = { width: width_1, height: height_1, scaleMode: scaleMode, resolution: resolution };
2616 /* eslint-enable prefer-rest-params */
2617 }
2618 _this = _super.call(this, null, options) || this;
2619 var _a = options || {}, width = _a.width, height = _a.height;
2620 // Set defaults
2621 _this.mipmap = 0;
2622 _this.width = Math.ceil(width) || 100;
2623 _this.height = Math.ceil(height) || 100;
2624 _this.valid = true;
2625 _this.clearColor = [0, 0, 0, 0];
2626 _this.framebuffer = new Framebuffer(_this.width * _this.resolution, _this.height * _this.resolution)
2627 .addColorTexture(0, _this);
2628 // TODO - could this be added the systems?
2629 /**
2630 * The data structure for the stencil masks.
2631 *
2632 * @member {PIXI.MaskData[]}
2633 */
2634 _this.maskStack = [];
2635 /**
2636 * The data structure for the filters.
2637 *
2638 * @member {Object[]}
2639 */
2640 _this.filterStack = [{}];
2641 return _this;
2642 }
2643 /**
2644 * Resizes the BaseRenderTexture.
2645 *
2646 * @param {number} width - The width to resize to.
2647 * @param {number} height - The height to resize to.
2648 */
2649 BaseRenderTexture.prototype.resize = function (width, height) {
2650 width = Math.ceil(width);
2651 height = Math.ceil(height);
2652 this.framebuffer.resize(width * this.resolution, height * this.resolution);
2653 };
2654 /**
2655 * Frees the texture and framebuffer from WebGL memory without destroying this texture object.
2656 * This means you can still use the texture later which will upload it to GPU
2657 * memory again.
2658 *
2659 * @fires PIXI.BaseTexture#dispose
2660 */
2661 BaseRenderTexture.prototype.dispose = function () {
2662 this.framebuffer.dispose();
2663 _super.prototype.dispose.call(this);
2664 };
2665 /**
2666 * Destroys this texture.
2667 */
2668 BaseRenderTexture.prototype.destroy = function () {
2669 _super.prototype.destroy.call(this);
2670 this.framebuffer.destroyDepthTexture();
2671 this.framebuffer = null;
2672 };
2673 return BaseRenderTexture;
2674}(BaseTexture));
2675
2676/**
2677 * Stores a texture's frame in UV coordinates, in
2678 * which everything lies in the rectangle `[(0,0), (1,0),
2679 * (1,1), (0,1)]`.
2680 *
2681 * | Corner | Coordinates |
2682 * |--------------|-------------|
2683 * | Top-Left | `(x0,y0)` |
2684 * | Top-Right | `(x1,y1)` |
2685 * | Bottom-Right | `(x2,y2)` |
2686 * | Bottom-Left | `(x3,y3)` |
2687 *
2688 * @class
2689 * @protected
2690 * @memberof PIXI
2691 */
2692var TextureUvs = /** @class */ (function () {
2693 function TextureUvs() {
2694 /**
2695 * X-component of top-left corner `(x0,y0)`.
2696 *
2697 * @member {number}
2698 */
2699 this.x0 = 0;
2700 /**
2701 * Y-component of top-left corner `(x0,y0)`.
2702 *
2703 * @member {number}
2704 */
2705 this.y0 = 0;
2706 /**
2707 * X-component of top-right corner `(x1,y1)`.
2708 *
2709 * @member {number}
2710 */
2711 this.x1 = 1;
2712 /**
2713 * Y-component of top-right corner `(x1,y1)`.
2714 *
2715 * @member {number}
2716 */
2717 this.y1 = 0;
2718 /**
2719 * X-component of bottom-right corner `(x2,y2)`.
2720 *
2721 * @member {number}
2722 */
2723 this.x2 = 1;
2724 /**
2725 * Y-component of bottom-right corner `(x2,y2)`.
2726 *
2727 * @member {number}
2728 */
2729 this.y2 = 1;
2730 /**
2731 * X-component of bottom-left corner `(x3,y3)`.
2732 *
2733 * @member {number}
2734 */
2735 this.x3 = 0;
2736 /**
2737 * Y-component of bottom-right corner `(x3,y3)`.
2738 *
2739 * @member {number}
2740 */
2741 this.y3 = 1;
2742 this.uvsFloat32 = new Float32Array(8);
2743 }
2744 /**
2745 * Sets the texture Uvs based on the given frame information.
2746 *
2747 * @protected
2748 * @param {PIXI.Rectangle} frame - The frame of the texture
2749 * @param {PIXI.Rectangle} baseFrame - The base frame of the texture
2750 * @param {number} rotate - Rotation of frame, see {@link PIXI.groupD8}
2751 */
2752 TextureUvs.prototype.set = function (frame, baseFrame, rotate) {
2753 var tw = baseFrame.width;
2754 var th = baseFrame.height;
2755 if (rotate) {
2756 // width and height div 2 div baseFrame size
2757 var w2 = frame.width / 2 / tw;
2758 var h2 = frame.height / 2 / th;
2759 // coordinates of center
2760 var cX = (frame.x / tw) + w2;
2761 var cY = (frame.y / th) + h2;
2762 rotate = groupD8.add(rotate, groupD8.NW); // NW is top-left corner
2763 this.x0 = cX + (w2 * groupD8.uX(rotate));
2764 this.y0 = cY + (h2 * groupD8.uY(rotate));
2765 rotate = groupD8.add(rotate, 2); // rotate 90 degrees clockwise
2766 this.x1 = cX + (w2 * groupD8.uX(rotate));
2767 this.y1 = cY + (h2 * groupD8.uY(rotate));
2768 rotate = groupD8.add(rotate, 2);
2769 this.x2 = cX + (w2 * groupD8.uX(rotate));
2770 this.y2 = cY + (h2 * groupD8.uY(rotate));
2771 rotate = groupD8.add(rotate, 2);
2772 this.x3 = cX + (w2 * groupD8.uX(rotate));
2773 this.y3 = cY + (h2 * groupD8.uY(rotate));
2774 }
2775 else {
2776 this.x0 = frame.x / tw;
2777 this.y0 = frame.y / th;
2778 this.x1 = (frame.x + frame.width) / tw;
2779 this.y1 = frame.y / th;
2780 this.x2 = (frame.x + frame.width) / tw;
2781 this.y2 = (frame.y + frame.height) / th;
2782 this.x3 = frame.x / tw;
2783 this.y3 = (frame.y + frame.height) / th;
2784 }
2785 this.uvsFloat32[0] = this.x0;
2786 this.uvsFloat32[1] = this.y0;
2787 this.uvsFloat32[2] = this.x1;
2788 this.uvsFloat32[3] = this.y1;
2789 this.uvsFloat32[4] = this.x2;
2790 this.uvsFloat32[5] = this.y2;
2791 this.uvsFloat32[6] = this.x3;
2792 this.uvsFloat32[7] = this.y3;
2793 };
2794 TextureUvs.prototype.toString = function () {
2795 return "[@pixi/core:TextureUvs "
2796 + ("x0=" + this.x0 + " y0=" + this.y0 + " ")
2797 + ("x1=" + this.x1 + " y1=" + this.y1 + " x2=" + this.x2 + " ")
2798 + ("y2=" + this.y2 + " x3=" + this.x3 + " y3=" + this.y3)
2799 + "]";
2800 };
2801 return TextureUvs;
2802}());
2803
2804var DEFAULT_UVS = new TextureUvs();
2805/**
2806 * A texture stores the information that represents an image or part of an image.
2807 *
2808 * It cannot be added to the display list directly; instead use it as the texture for a Sprite.
2809 * If no frame is provided for a texture, then the whole image is used.
2810 *
2811 * You can directly create a texture from an image and then reuse it multiple times like this :
2812 *
2813 * ```js
2814 * let texture = PIXI.Texture.from('assets/image.png');
2815 * let sprite1 = new PIXI.Sprite(texture);
2816 * let sprite2 = new PIXI.Sprite(texture);
2817 * ```
2818 *
2819 * If you didnt pass the texture frame to constructor, it enables `noFrame` mode:
2820 * it subscribes on baseTexture events, it automatically resizes at the same time as baseTexture.
2821 *
2822 * Textures made from SVGs, loaded or not, cannot be used before the file finishes processing.
2823 * You can check for this by checking the sprite's _textureID property.
2824 * ```js
2825 * var texture = PIXI.Texture.from('assets/image.svg');
2826 * var sprite1 = new PIXI.Sprite(texture);
2827 * //sprite1._textureID should not be undefined if the texture has finished processing the SVG file
2828 * ```
2829 * You can use a ticker or rAF to ensure your sprites load the finished textures after processing. See issue #3068.
2830 *
2831 * @class
2832 * @extends PIXI.utils.EventEmitter
2833 * @memberof PIXI
2834 * @typeParam R - The BaseTexture's Resource type.
2835 */
2836var Texture = /** @class */ (function (_super) {
2837 __extends(Texture, _super);
2838 /**
2839 * @param {PIXI.BaseTexture} baseTexture - The base texture source to create the texture from
2840 * @param {PIXI.Rectangle} [frame] - The rectangle frame of the texture to show
2841 * @param {PIXI.Rectangle} [orig] - The area of original texture
2842 * @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
2843 * @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.groupD8}
2844 * @param {PIXI.IPointData} [anchor] - Default anchor point used for sprite placement / rotation
2845 */
2846 function Texture(baseTexture, frame, orig, trim, rotate, anchor) {
2847 var _this = _super.call(this) || this;
2848 /**
2849 * Does this Texture have any frame data assigned to it?
2850 *
2851 * This mode is enabled automatically if no frame was passed inside constructor.
2852 *
2853 * In this mode texture is subscribed to baseTexture events, and fires `update` on any change.
2854 *
2855 * Beware, after loading or resize of baseTexture event can fired two times!
2856 * If you want more control, subscribe on baseTexture itself.
2857 *
2858 * ```js
2859 * texture.on('update', () => {});
2860 * ```
2861 *
2862 * Any assignment of `frame` switches off `noFrame` mode.
2863 *
2864 * @member {boolean}
2865 */
2866 _this.noFrame = false;
2867 if (!frame) {
2868 _this.noFrame = true;
2869 frame = new Rectangle(0, 0, 1, 1);
2870 }
2871 if (baseTexture instanceof Texture) {
2872 baseTexture = baseTexture.baseTexture;
2873 }
2874 /**
2875 * The base texture that this texture uses.
2876 *
2877 * @member {PIXI.BaseTexture}
2878 */
2879 _this.baseTexture = baseTexture;
2880 /**
2881 * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
2882 * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
2883 *
2884 * @member {PIXI.Rectangle}
2885 */
2886 _this._frame = frame;
2887 /**
2888 * This is the trimmed area of original texture, before it was put in atlas
2889 * Please call `updateUvs()` after you change coordinates of `trim` manually.
2890 *
2891 * @member {PIXI.Rectangle}
2892 */
2893 _this.trim = trim;
2894 /**
2895 * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
2896 *
2897 * @member {boolean}
2898 */
2899 _this.valid = false;
2900 /**
2901 * The WebGL UV data cache. Can be used as quad UV
2902 *
2903 * @member {PIXI.TextureUvs}
2904 * @protected
2905 */
2906 _this._uvs = DEFAULT_UVS;
2907 /**
2908 * Default TextureMatrix instance for this texture
2909 * By default that object is not created because its heavy
2910 *
2911 * @member {PIXI.TextureMatrix}
2912 */
2913 _this.uvMatrix = null;
2914 /**
2915 * This is the area of original texture, before it was put in atlas
2916 *
2917 * @member {PIXI.Rectangle}
2918 */
2919 _this.orig = orig || frame; // new Rectangle(0, 0, 1, 1);
2920 _this._rotate = Number(rotate || 0);
2921 if (rotate === true) {
2922 // this is old texturepacker legacy, some games/libraries are passing "true" for rotated textures
2923 _this._rotate = 2;
2924 }
2925 else if (_this._rotate % 2 !== 0) {
2926 throw new Error('attempt to use diamond-shaped UVs. If you are sure, set rotation manually');
2927 }
2928 /**
2929 * Anchor point that is used as default if sprite is created with this texture.
2930 * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
2931 * @member {PIXI.Point}
2932 * @default {0,0}
2933 */
2934 _this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
2935 /**
2936 * Update ID is observed by sprites and TextureMatrix instances.
2937 * Call updateUvs() to increment it.
2938 *
2939 * @member {number}
2940 * @protected
2941 */
2942 _this._updateID = 0;
2943 /**
2944 * The ids under which this Texture has been added to the texture cache. This is
2945 * automatically set as long as Texture.addToCache is used, but may not be set if a
2946 * Texture is added directly to the TextureCache array.
2947 *
2948 * @member {string[]}
2949 */
2950 _this.textureCacheIds = [];
2951 if (!baseTexture.valid) {
2952 baseTexture.once('loaded', _this.onBaseTextureUpdated, _this);
2953 }
2954 else if (_this.noFrame) {
2955 // if there is no frame we should monitor for any base texture changes..
2956 if (baseTexture.valid) {
2957 _this.onBaseTextureUpdated(baseTexture);
2958 }
2959 }
2960 else {
2961 _this.frame = frame;
2962 }
2963 if (_this.noFrame) {
2964 baseTexture.on('update', _this.onBaseTextureUpdated, _this);
2965 }
2966 return _this;
2967 }
2968 /**
2969 * Updates this texture on the gpu.
2970 *
2971 * Calls the TextureResource update.
2972 *
2973 * If you adjusted `frame` manually, please call `updateUvs()` instead.
2974 *
2975 */
2976 Texture.prototype.update = function () {
2977 if (this.baseTexture.resource) {
2978 this.baseTexture.resource.update();
2979 }
2980 };
2981 /**
2982 * Called when the base texture is updated
2983 *
2984 * @protected
2985 * @param {PIXI.BaseTexture} baseTexture - The base texture.
2986 */
2987 Texture.prototype.onBaseTextureUpdated = function (baseTexture) {
2988 if (this.noFrame) {
2989 if (!this.baseTexture.valid) {
2990 return;
2991 }
2992 this._frame.width = baseTexture.width;
2993 this._frame.height = baseTexture.height;
2994 this.valid = true;
2995 this.updateUvs();
2996 }
2997 else {
2998 // TODO this code looks confusing.. boo to abusing getters and setters!
2999 // if user gave us frame that has bigger size than resized texture it can be a problem
3000 this.frame = this._frame;
3001 }
3002 this.emit('update', this);
3003 };
3004 /**
3005 * Destroys this texture
3006 *
3007 * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well
3008 */
3009 Texture.prototype.destroy = function (destroyBase) {
3010 if (this.baseTexture) {
3011 if (destroyBase) {
3012 var resource = this.baseTexture.resource;
3013 // delete the texture if it exists in the texture cache..
3014 // this only needs to be removed if the base texture is actually destroyed too..
3015 if (resource && resource.url && TextureCache[resource.url]) {
3016 Texture.removeFromCache(resource.url);
3017 }
3018 this.baseTexture.destroy();
3019 }
3020 this.baseTexture.off('loaded', this.onBaseTextureUpdated, this);
3021 this.baseTexture.off('update', this.onBaseTextureUpdated, this);
3022 this.baseTexture = null;
3023 }
3024 this._frame = null;
3025 this._uvs = null;
3026 this.trim = null;
3027 this.orig = null;
3028 this.valid = false;
3029 Texture.removeFromCache(this);
3030 this.textureCacheIds = null;
3031 };
3032 /**
3033 * Creates a new texture object that acts the same as this one.
3034 *
3035 * @return {PIXI.Texture} The new texture
3036 */
3037 Texture.prototype.clone = function () {
3038 return new Texture(this.baseTexture, this.frame.clone(), this.orig.clone(), this.trim && this.trim.clone(), this.rotate, this.defaultAnchor);
3039 };
3040 /**
3041 * Updates the internal WebGL UV cache. Use it after you change `frame` or `trim` of the texture.
3042 * Call it after changing the frame
3043 */
3044 Texture.prototype.updateUvs = function () {
3045 if (this._uvs === DEFAULT_UVS) {
3046 this._uvs = new TextureUvs();
3047 }
3048 this._uvs.set(this._frame, this.baseTexture, this.rotate);
3049 this._updateID++;
3050 };
3051 /**
3052 * Helper function that creates a new Texture based on the source you provide.
3053 * The source can be - frame id, image url, video url, canvas element, video element, base texture
3054 *
3055 * @static
3056 * @param {string|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|PIXI.BaseTexture} source -
3057 * Source to create texture from
3058 * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options.
3059 * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id
3060 * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}.
3061 * @return {PIXI.Texture} The newly created texture
3062 */
3063 Texture.from = function (source, options, strict) {
3064 if (options === void 0) { options = {}; }
3065 if (strict === void 0) { strict = settings.STRICT_TEXTURE_CACHE; }
3066 var isFrame = typeof source === 'string';
3067 var cacheId = null;
3068 if (isFrame) {
3069 cacheId = source;
3070 }
3071 else {
3072 if (!source._pixiId) {
3073 var prefix = (options && options.pixiIdPrefix) || 'pixiid';
3074 source._pixiId = prefix + "_" + uid();
3075 }
3076 cacheId = source._pixiId;
3077 }
3078 var texture = TextureCache[cacheId];
3079 // Strict-mode rejects invalid cacheIds
3080 if (isFrame && strict && !texture) {
3081 throw new Error("The cacheId \"" + cacheId + "\" does not exist in TextureCache.");
3082 }
3083 if (!texture) {
3084 if (!options.resolution) {
3085 options.resolution = getResolutionOfUrl(source);
3086 }
3087 texture = new Texture(new BaseTexture(source, options));
3088 texture.baseTexture.cacheId = cacheId;
3089 BaseTexture.addToCache(texture.baseTexture, cacheId);
3090 Texture.addToCache(texture, cacheId);
3091 }
3092 // lets assume its a base texture!
3093 return texture;
3094 };
3095 /**
3096 * Useful for loading textures via URLs. Use instead of `Texture.from` because
3097 * it does a better job of handling failed URLs more effectively. This also ignores
3098 * `PIXI.settings.STRICT_TEXTURE_CACHE`. Works for Videos, SVGs, Images.
3099 * @param {string} url - The remote URL to load.
3100 * @param {object} [options] - Optional options to include
3101 * @return {Promise<PIXI.Texture>} A Promise that resolves to a Texture.
3102 */
3103 Texture.fromURL = function (url, options) {
3104 var resourceOptions = Object.assign({ autoLoad: false }, options === null || options === void 0 ? void 0 : options.resourceOptions);
3105 var texture = Texture.from(url, Object.assign({ resourceOptions: resourceOptions }, options), false);
3106 var resource = texture.baseTexture.resource;
3107 // The texture was already loaded
3108 if (texture.baseTexture.valid) {
3109 return Promise.resolve(texture);
3110 }
3111 // Manually load the texture, this should allow users to handle load errors
3112 return resource.load().then(function () { return Promise.resolve(texture); });
3113 };
3114 /**
3115 * Create a new Texture with a BufferResource from a Float32Array.
3116 * RGBA values are floats from 0 to 1.
3117 * @static
3118 * @param {Float32Array|Uint8Array} buffer - The optional array to use, if no data
3119 * is provided, a new Float32Array is created.
3120 * @param {number} width - Width of the resource
3121 * @param {number} height - Height of the resource
3122 * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options.
3123 * @return {PIXI.Texture} The resulting new BaseTexture
3124 */
3125 Texture.fromBuffer = function (buffer, width, height, options) {
3126 return new Texture(BaseTexture.fromBuffer(buffer, width, height, options));
3127 };
3128 /**
3129 * Create a texture from a source and add to the cache.
3130 *
3131 * @static
3132 * @param {HTMLImageElement|HTMLCanvasElement|string} source - The input source.
3133 * @param {String} imageUrl - File name of texture, for cache and resolving resolution.
3134 * @param {String} [name] - Human readable name for the texture cache. If no name is
3135 * specified, only `imageUrl` will be used as the cache ID.
3136 * @return {PIXI.Texture} Output texture
3137 */
3138 Texture.fromLoader = function (source, imageUrl, name, options) {
3139 var baseTexture = new BaseTexture(source, Object.assign({
3140 scaleMode: settings.SCALE_MODE,
3141 resolution: getResolutionOfUrl(imageUrl),
3142 }, options));
3143 var resource = baseTexture.resource;
3144 if (resource instanceof ImageResource) {
3145 resource.url = imageUrl;
3146 }
3147 var texture = new Texture(baseTexture);
3148 // No name, use imageUrl instead
3149 if (!name) {
3150 name = imageUrl;
3151 }
3152 // lets also add the frame to pixi's global cache for 'fromLoader' function
3153 BaseTexture.addToCache(texture.baseTexture, name);
3154 Texture.addToCache(texture, name);
3155 // also add references by url if they are different.
3156 if (name !== imageUrl) {
3157 BaseTexture.addToCache(texture.baseTexture, imageUrl);
3158 Texture.addToCache(texture, imageUrl);
3159 }
3160 // Generally images are valid right away
3161 if (texture.baseTexture.valid) {
3162 return Promise.resolve(texture);
3163 }
3164 // SVG assets need to be parsed async, let's wait
3165 return new Promise(function (resolve) {
3166 texture.baseTexture.once('loaded', function () { return resolve(texture); });
3167 });
3168 };
3169 /**
3170 * Adds a Texture to the global TextureCache. This cache is shared across the whole PIXI object.
3171 *
3172 * @static
3173 * @param {PIXI.Texture} texture - The Texture to add to the cache.
3174 * @param {string} id - The id that the Texture will be stored against.
3175 */
3176 Texture.addToCache = function (texture, id) {
3177 if (id) {
3178 if (texture.textureCacheIds.indexOf(id) === -1) {
3179 texture.textureCacheIds.push(id);
3180 }
3181 if (TextureCache[id]) {
3182 // eslint-disable-next-line no-console
3183 console.warn("Texture added to the cache with an id [" + id + "] that already had an entry");
3184 }
3185 TextureCache[id] = texture;
3186 }
3187 };
3188 /**
3189 * Remove a Texture from the global TextureCache.
3190 *
3191 * @static
3192 * @param {string|PIXI.Texture} texture - id of a Texture to be removed, or a Texture instance itself
3193 * @return {PIXI.Texture|null} The Texture that was removed
3194 */
3195 Texture.removeFromCache = function (texture) {
3196 if (typeof texture === 'string') {
3197 var textureFromCache = TextureCache[texture];
3198 if (textureFromCache) {
3199 var index = textureFromCache.textureCacheIds.indexOf(texture);
3200 if (index > -1) {
3201 textureFromCache.textureCacheIds.splice(index, 1);
3202 }
3203 delete TextureCache[texture];
3204 return textureFromCache;
3205 }
3206 }
3207 else if (texture && texture.textureCacheIds) {
3208 for (var i = 0; i < texture.textureCacheIds.length; ++i) {
3209 // Check that texture matches the one being passed in before deleting it from the cache.
3210 if (TextureCache[texture.textureCacheIds[i]] === texture) {
3211 delete TextureCache[texture.textureCacheIds[i]];
3212 }
3213 }
3214 texture.textureCacheIds.length = 0;
3215 return texture;
3216 }
3217 return null;
3218 };
3219 Object.defineProperty(Texture.prototype, "resolution", {
3220 /**
3221 * Returns resolution of baseTexture
3222 *
3223 * @member {number}
3224 * @readonly
3225 */
3226 get: function () {
3227 return this.baseTexture.resolution;
3228 },
3229 enumerable: false,
3230 configurable: true
3231 });
3232 Object.defineProperty(Texture.prototype, "frame", {
3233 /**
3234 * The frame specifies the region of the base texture that this texture uses.
3235 * Please call `updateUvs()` after you change coordinates of `frame` manually.
3236 *
3237 * @member {PIXI.Rectangle}
3238 */
3239 get: function () {
3240 return this._frame;
3241 },
3242 set: function (frame) {
3243 this._frame = frame;
3244 this.noFrame = false;
3245 var x = frame.x, y = frame.y, width = frame.width, height = frame.height;
3246 var xNotFit = x + width > this.baseTexture.width;
3247 var yNotFit = y + height > this.baseTexture.height;
3248 if (xNotFit || yNotFit) {
3249 var relationship = xNotFit && yNotFit ? 'and' : 'or';
3250 var errorX = "X: " + x + " + " + width + " = " + (x + width) + " > " + this.baseTexture.width;
3251 var errorY = "Y: " + y + " + " + height + " = " + (y + height) + " > " + this.baseTexture.height;
3252 throw new Error('Texture Error: frame does not fit inside the base Texture dimensions: '
3253 + (errorX + " " + relationship + " " + errorY));
3254 }
3255 this.valid = width && height && this.baseTexture.valid;
3256 if (!this.trim && !this.rotate) {
3257 this.orig = frame;
3258 }
3259 if (this.valid) {
3260 this.updateUvs();
3261 }
3262 },
3263 enumerable: false,
3264 configurable: true
3265 });
3266 Object.defineProperty(Texture.prototype, "rotate", {
3267 /**
3268 * Indicates whether the texture is rotated inside the atlas
3269 * set to 2 to compensate for texture packer rotation
3270 * set to 6 to compensate for spine packer rotation
3271 * can be used to rotate or mirror sprites
3272 * See {@link PIXI.groupD8} for explanation
3273 *
3274 * @member {number}
3275 */
3276 get: function () {
3277 return this._rotate;
3278 },
3279 set: function (rotate) {
3280 this._rotate = rotate;
3281 if (this.valid) {
3282 this.updateUvs();
3283 }
3284 },
3285 enumerable: false,
3286 configurable: true
3287 });
3288 Object.defineProperty(Texture.prototype, "width", {
3289 /**
3290 * The width of the Texture in pixels.
3291 *
3292 * @member {number}
3293 */
3294 get: function () {
3295 return this.orig.width;
3296 },
3297 enumerable: false,
3298 configurable: true
3299 });
3300 Object.defineProperty(Texture.prototype, "height", {
3301 /**
3302 * The height of the Texture in pixels.
3303 *
3304 * @member {number}
3305 */
3306 get: function () {
3307 return this.orig.height;
3308 },
3309 enumerable: false,
3310 configurable: true
3311 });
3312 /**
3313 * Utility function for BaseTexture|Texture cast
3314 */
3315 Texture.prototype.castToBaseTexture = function () {
3316 return this.baseTexture;
3317 };
3318 return Texture;
3319}(EventEmitter));
3320function createWhiteTexture() {
3321 var canvas = document.createElement('canvas');
3322 canvas.width = 16;
3323 canvas.height = 16;
3324 var context = canvas.getContext('2d');
3325 context.fillStyle = 'white';
3326 context.fillRect(0, 0, 16, 16);
3327 return new Texture(new BaseTexture(new CanvasResource(canvas)));
3328}
3329function removeAllHandlers(tex) {
3330 tex.destroy = function _emptyDestroy() { };
3331 tex.on = function _emptyOn() { };
3332 tex.once = function _emptyOnce() { };
3333 tex.emit = function _emptyEmit() { };
3334}
3335/**
3336 * An empty texture, used often to not have to create multiple empty textures.
3337 * Can not be destroyed.
3338 *
3339 * @static
3340 * @constant
3341 * @member {PIXI.Texture}
3342 */
3343Texture.EMPTY = new Texture(new BaseTexture());
3344removeAllHandlers(Texture.EMPTY);
3345removeAllHandlers(Texture.EMPTY.baseTexture);
3346/**
3347 * A white texture of 16x16 size, used for graphics and other things
3348 * Can not be destroyed.
3349 *
3350 * @static
3351 * @constant
3352 * @member {PIXI.Texture}
3353 */
3354Texture.WHITE = createWhiteTexture();
3355removeAllHandlers(Texture.WHITE);
3356removeAllHandlers(Texture.WHITE.baseTexture);
3357
3358/**
3359 * A RenderTexture is a special texture that allows any PixiJS display object to be rendered to it.
3360 *
3361 * __Hint__: All DisplayObjects (i.e. Sprites) that render to a RenderTexture should be preloaded
3362 * otherwise black rectangles will be drawn instead.
3363 *
3364 * __Hint-2__: The actual memory allocation will happen on first render.
3365 * You shouldn't create renderTextures each frame just to delete them after, try to reuse them.
3366 *
3367 * A RenderTexture takes a snapshot of any Display Object given to its render method. For example:
3368 *
3369 * ```js
3370 * let renderer = PIXI.autoDetectRenderer();
3371 * let renderTexture = PIXI.RenderTexture.create({ width: 800, height: 600 });
3372 * let sprite = PIXI.Sprite.from("spinObj_01.png");
3373 *
3374 * sprite.position.x = 800/2;
3375 * sprite.position.y = 600/2;
3376 * sprite.anchor.x = 0.5;
3377 * sprite.anchor.y = 0.5;
3378 *
3379 * renderer.render(sprite, {renderTexture});
3380 * ```
3381 * Note that you should not create a new renderer, but reuse the same one as the rest of the application.
3382 *
3383 * The Sprite in this case will be rendered using its local transform. To render this sprite at 0,0
3384 * you can clear the transform
3385 *
3386 * ```js
3387 *
3388 * sprite.setTransform()
3389 *
3390 * let renderTexture = new PIXI.RenderTexture.create({ width: 100, height: 100 });
3391 *
3392 * renderer.render(sprite, {renderTexture}); // Renders to center of RenderTexture
3393 * ```
3394 *
3395 * @class
3396 * @extends PIXI.Texture
3397 * @memberof PIXI
3398 */
3399var RenderTexture = /** @class */ (function (_super) {
3400 __extends(RenderTexture, _super);
3401 /**
3402 * @param {PIXI.BaseRenderTexture} baseRenderTexture - The base texture object that this texture uses
3403 * @param {PIXI.Rectangle} [frame] - The rectangle frame of the texture to show
3404 */
3405 function RenderTexture(baseRenderTexture, frame) {
3406 var _this = _super.call(this, baseRenderTexture, frame) || this;
3407 /**
3408 * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
3409 *
3410 * @member {boolean}
3411 */
3412 _this.valid = true;
3413 /**
3414 * Stores `sourceFrame` when this texture is inside current filter stack.
3415 * You can read it inside filters.
3416 *
3417 * @readonly
3418 * @member {PIXI.Rectangle}
3419 */
3420 _this.filterFrame = null;
3421 /**
3422 * The key for pooled texture of FilterSystem
3423 * @protected
3424 * @member {string}
3425 */
3426 _this.filterPoolKey = null;
3427 _this.updateUvs();
3428 return _this;
3429 }
3430 Object.defineProperty(RenderTexture.prototype, "framebuffer", {
3431 /**
3432 * Shortcut to `this.baseTexture.framebuffer`, saves baseTexture cast.
3433 * @member {PIXI.Framebuffer}
3434 * @readonly
3435 */
3436 get: function () {
3437 return this.baseTexture.framebuffer;
3438 },
3439 enumerable: false,
3440 configurable: true
3441 });
3442 /**
3443 * Resizes the RenderTexture.
3444 *
3445 * @param {number} width - The width to resize to.
3446 * @param {number} height - The height to resize to.
3447 * @param {boolean} [resizeBaseTexture=true] - Should the baseTexture.width and height values be resized as well?
3448 */
3449 RenderTexture.prototype.resize = function (width, height, resizeBaseTexture) {
3450 if (resizeBaseTexture === void 0) { resizeBaseTexture = true; }
3451 width = Math.ceil(width);
3452 height = Math.ceil(height);
3453 // TODO - could be not required..
3454 this.valid = (width > 0 && height > 0);
3455 this._frame.width = this.orig.width = width;
3456 this._frame.height = this.orig.height = height;
3457 if (resizeBaseTexture) {
3458 this.baseTexture.resize(width, height);
3459 }
3460 this.updateUvs();
3461 };
3462 /**
3463 * Changes the resolution of baseTexture, but does not change framebuffer size.
3464 *
3465 * @param {number} resolution - The new resolution to apply to RenderTexture
3466 */
3467 RenderTexture.prototype.setResolution = function (resolution) {
3468 var baseTexture = this.baseTexture;
3469 if (baseTexture.resolution === resolution) {
3470 return;
3471 }
3472 baseTexture.setResolution(resolution);
3473 this.resize(baseTexture.width, baseTexture.height, false);
3474 };
3475 RenderTexture.create = function (options) {
3476 var arguments$1 = arguments;
3477
3478 var rest = [];
3479 for (var _i = 1; _i < arguments.length; _i++) {
3480 rest[_i - 1] = arguments$1[_i];
3481 }
3482 // @deprecated fallback, old-style: create(width, height, scaleMode, resolution)
3483 if (typeof options === 'number') {
3484 deprecation('6.0.0', 'Arguments (width, height, scaleMode, resolution) have been deprecated.');
3485 /* eslint-disable prefer-rest-params */
3486 options = {
3487 width: options,
3488 height: rest[0],
3489 scaleMode: rest[1],
3490 resolution: rest[2],
3491 };
3492 /* eslint-enable prefer-rest-params */
3493 }
3494 return new RenderTexture(new BaseRenderTexture(options));
3495 };
3496 return RenderTexture;
3497}(Texture));
3498
3499/**
3500 * Experimental!
3501 *
3502 * Texture pool, used by FilterSystem and plugins
3503 * Stores collection of temporary pow2 or screen-sized renderTextures
3504 *
3505 * If you use custom RenderTexturePool for your filters, you can use methods
3506 * `getFilterTexture` and `returnFilterTexture` same as in
3507 *
3508 * @class
3509 * @memberof PIXI
3510 */
3511var RenderTexturePool = /** @class */ (function () {
3512 /**
3513 * @param {object} [textureOptions] - options that will be passed to BaseRenderTexture constructor
3514 * @param {PIXI.SCALE_MODES} [textureOptions.scaleMode] - See {@link PIXI.SCALE_MODES} for possible values.
3515 */
3516 function RenderTexturePool(textureOptions) {
3517 this.texturePool = {};
3518 this.textureOptions = textureOptions || {};
3519 /**
3520 * Allow renderTextures of the same size as screen, not just pow2
3521 *
3522 * Automatically sets to true after `setScreenSize`
3523 *
3524 * @member {boolean}
3525 * @default false
3526 */
3527 this.enableFullScreen = false;
3528 this._pixelsWidth = 0;
3529 this._pixelsHeight = 0;
3530 }
3531 /**
3532 * creates of texture with params that were specified in pool constructor
3533 *
3534 * @param {number} realWidth - width of texture in pixels
3535 * @param {number} realHeight - height of texture in pixels
3536 * @returns {RenderTexture}
3537 */
3538 RenderTexturePool.prototype.createTexture = function (realWidth, realHeight) {
3539 var baseRenderTexture = new BaseRenderTexture(Object.assign({
3540 width: realWidth,
3541 height: realHeight,
3542 resolution: 1,
3543 }, this.textureOptions));
3544 return new RenderTexture(baseRenderTexture);
3545 };
3546 /**
3547 * Gets a Power-of-Two render texture or fullScreen texture
3548 *
3549 * @protected
3550 * @param {number} minWidth - The minimum width of the render texture in real pixels.
3551 * @param {number} minHeight - The minimum height of the render texture in real pixels.
3552 * @param {number} [resolution=1] - The resolution of the render texture.
3553 * @return {PIXI.RenderTexture} The new render texture.
3554 */
3555 RenderTexturePool.prototype.getOptimalTexture = function (minWidth, minHeight, resolution) {
3556 if (resolution === void 0) { resolution = 1; }
3557 var key = RenderTexturePool.SCREEN_KEY;
3558 minWidth *= resolution;
3559 minHeight *= resolution;
3560 if (!this.enableFullScreen || minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) {
3561 minWidth = nextPow2(minWidth);
3562 minHeight = nextPow2(minHeight);
3563 key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF);
3564 }
3565 if (!this.texturePool[key]) {
3566 this.texturePool[key] = [];
3567 }
3568 var renderTexture = this.texturePool[key].pop();
3569 if (!renderTexture) {
3570 renderTexture = this.createTexture(minWidth, minHeight);
3571 }
3572 renderTexture.filterPoolKey = key;
3573 renderTexture.setResolution(resolution);
3574 return renderTexture;
3575 };
3576 /**
3577 * Gets extra texture of the same size as input renderTexture
3578 *
3579 * `getFilterTexture(input, 0.5)` or `getFilterTexture(0.5, input)`
3580 *
3581 * @param {PIXI.RenderTexture} input - renderTexture from which size and resolution will be copied
3582 * @param {number} [resolution] - override resolution of the renderTexture
3583 * It overrides, it does not multiply
3584 * @returns {PIXI.RenderTexture}
3585 */
3586 RenderTexturePool.prototype.getFilterTexture = function (input, resolution) {
3587 var filterTexture = this.getOptimalTexture(input.width, input.height, resolution || input.resolution);
3588 filterTexture.filterFrame = input.filterFrame;
3589 return filterTexture;
3590 };
3591 /**
3592 * Place a render texture back into the pool.
3593 * @param {PIXI.RenderTexture} renderTexture - The renderTexture to free
3594 */
3595 RenderTexturePool.prototype.returnTexture = function (renderTexture) {
3596 var key = renderTexture.filterPoolKey;
3597 renderTexture.filterFrame = null;
3598 this.texturePool[key].push(renderTexture);
3599 };
3600 /**
3601 * Alias for returnTexture, to be compliant with FilterSystem interface
3602 * @param {PIXI.RenderTexture} renderTexture - The renderTexture to free
3603 */
3604 RenderTexturePool.prototype.returnFilterTexture = function (renderTexture) {
3605 this.returnTexture(renderTexture);
3606 };
3607 /**
3608 * Clears the pool
3609 *
3610 * @param {boolean} [destroyTextures=true] - destroy all stored textures
3611 */
3612 RenderTexturePool.prototype.clear = function (destroyTextures) {
3613 destroyTextures = destroyTextures !== false;
3614 if (destroyTextures) {
3615 for (var i in this.texturePool) {
3616 var textures = this.texturePool[i];
3617 if (textures) {
3618 for (var j = 0; j < textures.length; j++) {
3619 textures[j].destroy(true);
3620 }
3621 }
3622 }
3623 }
3624 this.texturePool = {};
3625 };
3626 /**
3627 * If screen size was changed, drops all screen-sized textures,
3628 * sets new screen size, sets `enableFullScreen` to true
3629 *
3630 * Size is measured in pixels, `renderer.view` can be passed here, not `renderer.screen`
3631 *
3632 * @param {PIXI.ISize} size - Initial size of screen
3633 */
3634 RenderTexturePool.prototype.setScreenSize = function (size) {
3635 if (size.width === this._pixelsWidth
3636 && size.height === this._pixelsHeight) {
3637 return;
3638 }
3639 var screenKey = RenderTexturePool.SCREEN_KEY;
3640 var textures = this.texturePool[screenKey];
3641 this.enableFullScreen = size.width > 0 && size.height > 0;
3642 if (textures) {
3643 for (var j = 0; j < textures.length; j++) {
3644 textures[j].destroy(true);
3645 }
3646 }
3647 this.texturePool[screenKey] = [];
3648 this._pixelsWidth = size.width;
3649 this._pixelsHeight = size.height;
3650 };
3651 /**
3652 * Key that is used to store fullscreen renderTextures in a pool
3653 *
3654 * @static
3655 * @const {string}
3656 */
3657 RenderTexturePool.SCREEN_KEY = 'screen';
3658 return RenderTexturePool;
3659}());
3660
3661/* eslint-disable max-len */
3662/**
3663 * Holds the information for a single attribute structure required to render geometry.
3664 *
3665 * This does not contain the actual data, but instead has a buffer id that maps to a {@link PIXI.Buffer}
3666 * This can include anything from positions, uvs, normals, colors etc.
3667 *
3668 * @class
3669 * @memberof PIXI
3670 */
3671var Attribute = /** @class */ (function () {
3672 /**
3673 * @param {string} buffer - the id of the buffer that this attribute will look for
3674 * @param {Number} [size=0] - the size of the attribute. If you have 2 floats per vertex (eg position x and y) this would be 2.
3675 * @param {Boolean} [normalized=false] - should the data be normalized.
3676 * @param {Number} [type=PIXI.TYPES.FLOAT] - what type of number is the attribute. Check {@link PIXI.TYPES} to see the ones available
3677 * @param {Number} [stride=0] - How far apart (in floats) the start of each value is. (used for interleaving data)
3678 * @param {Number} [start=0] - How far into the array to start reading values (used for interleaving data)
3679 */
3680 function Attribute(buffer, size, normalized, type, stride, start, instance) {
3681 if (size === void 0) { size = 0; }
3682 if (normalized === void 0) { normalized = false; }
3683 if (type === void 0) { type = 5126; }
3684 this.buffer = buffer;
3685 this.size = size;
3686 this.normalized = normalized;
3687 this.type = type;
3688 this.stride = stride;
3689 this.start = start;
3690 this.instance = instance;
3691 }
3692 /**
3693 * Destroys the Attribute.
3694 */
3695 Attribute.prototype.destroy = function () {
3696 this.buffer = null;
3697 };
3698 /**
3699 * Helper function that creates an Attribute based on the information provided
3700 *
3701 * @static
3702 * @param {string} buffer - the id of the buffer that this attribute will look for
3703 * @param {Number} [size=0] - the size of the attribute. If you have 2 floats per vertex (eg position x and y) this would be 2
3704 * @param {Boolean} [normalized=false] - should the data be normalized.
3705 * @param {Number} [type=PIXI.TYPES.FLOAT] - what type of number is the attribute. Check {@link PIXI.TYPES} to see the ones available
3706 * @param {Number} [stride=0] - How far apart (in floats) the start of each value is. (used for interleaving data)
3707 *
3708 * @returns {PIXI.Attribute} A new {@link PIXI.Attribute} based on the information provided
3709 */
3710 Attribute.from = function (buffer, size, normalized, type, stride) {
3711 return new Attribute(buffer, size, normalized, type, stride);
3712 };
3713 return Attribute;
3714}());
3715
3716var UID = 0;
3717/**
3718 * A wrapper for data so that it can be used and uploaded by WebGL
3719 *
3720 * @class
3721 * @memberof PIXI
3722 */
3723var Buffer = /** @class */ (function () {
3724 /**
3725 * @param {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} data - the data to store in the buffer.
3726 * @param {boolean} [_static=true] - `true` for static buffer
3727 * @param {boolean} [index=false] - `true` for index buffer
3728 */
3729 function Buffer(data, _static, index) {
3730 if (_static === void 0) { _static = true; }
3731 if (index === void 0) { index = false; }
3732 /**
3733 * The data in the buffer, as a typed array
3734 *
3735 * @member {ArrayBuffer| SharedArrayBuffer | ArrayBufferView}
3736 */
3737 this.data = (data || new Float32Array(1));
3738 /**
3739 * A map of renderer IDs to webgl buffer
3740 *
3741 * @private
3742 * @member {object<number, GLBuffer>}
3743 */
3744 this._glBuffers = {};
3745 this._updateID = 0;
3746 this.index = index;
3747 this.static = _static;
3748 this.id = UID++;
3749 this.disposeRunner = new Runner('disposeBuffer');
3750 }
3751 // TODO could explore flagging only a partial upload?
3752 /**
3753 * flags this buffer as requiring an upload to the GPU
3754 * @param {ArrayBuffer|SharedArrayBuffer|ArrayBufferView} [data] - the data to update in the buffer.
3755 */
3756 Buffer.prototype.update = function (data) {
3757 this.data = data || this.data;
3758 this._updateID++;
3759 };
3760 /**
3761 * disposes WebGL resources that are connected to this geometry
3762 */
3763 Buffer.prototype.dispose = function () {
3764 this.disposeRunner.emit(this, false);
3765 };
3766 /**
3767 * Destroys the buffer
3768 */
3769 Buffer.prototype.destroy = function () {
3770 this.dispose();
3771 this.data = null;
3772 };
3773 /**
3774 * Helper function that creates a buffer based on an array or TypedArray
3775 *
3776 * @static
3777 * @param {ArrayBufferView | number[]} data - the TypedArray that the buffer will store. If this is a regular Array it will be converted to a Float32Array.
3778 * @return {PIXI.Buffer} A new Buffer based on the data provided.
3779 */
3780 Buffer.from = function (data) {
3781 if (data instanceof Array) {
3782 data = new Float32Array(data);
3783 }
3784 return new Buffer(data);
3785 };
3786 return Buffer;
3787}());
3788
3789function getBufferType(array) {
3790 if (array.BYTES_PER_ELEMENT === 4) {
3791 if (array instanceof Float32Array) {
3792 return 'Float32Array';
3793 }
3794 else if (array instanceof Uint32Array) {
3795 return 'Uint32Array';
3796 }
3797 return 'Int32Array';
3798 }
3799 else if (array.BYTES_PER_ELEMENT === 2) {
3800 if (array instanceof Uint16Array) {
3801 return 'Uint16Array';
3802 }
3803 }
3804 else if (array.BYTES_PER_ELEMENT === 1) {
3805 if (array instanceof Uint8Array) {
3806 return 'Uint8Array';
3807 }
3808 }
3809 // TODO map out the rest of the array elements!
3810 return null;
3811}
3812
3813/* eslint-disable object-shorthand */
3814var map = {
3815 Float32Array: Float32Array,
3816 Uint32Array: Uint32Array,
3817 Int32Array: Int32Array,
3818 Uint8Array: Uint8Array,
3819};
3820function interleaveTypedArrays(arrays, sizes) {
3821 var outSize = 0;
3822 var stride = 0;
3823 var views = {};
3824 for (var i = 0; i < arrays.length; i++) {
3825 stride += sizes[i];
3826 outSize += arrays[i].length;
3827 }
3828 var buffer = new ArrayBuffer(outSize * 4);
3829 var out = null;
3830 var littleOffset = 0;
3831 for (var i = 0; i < arrays.length; i++) {
3832 var size = sizes[i];
3833 var array = arrays[i];
3834 var type = getBufferType(array);
3835 if (!views[type]) {
3836 views[type] = new map[type](buffer);
3837 }
3838 out = views[type];
3839 for (var j = 0; j < array.length; j++) {
3840 var indexStart = ((j / size | 0) * stride) + littleOffset;
3841 var index = j % size;
3842 out[indexStart + index] = array[j];
3843 }
3844 littleOffset += size;
3845 }
3846 return new Float32Array(buffer);
3847}
3848
3849var byteSizeMap = { 5126: 4, 5123: 2, 5121: 1 };
3850var UID$1 = 0;
3851/* eslint-disable object-shorthand */
3852var map$1 = {
3853 Float32Array: Float32Array,
3854 Uint32Array: Uint32Array,
3855 Int32Array: Int32Array,
3856 Uint8Array: Uint8Array,
3857 Uint16Array: Uint16Array,
3858};
3859/* eslint-disable max-len */
3860/**
3861 * The Geometry represents a model. It consists of two components:
3862 * - GeometryStyle - The structure of the model such as the attributes layout
3863 * - GeometryData - the data of the model - this consists of buffers.
3864 * This can include anything from positions, uvs, normals, colors etc.
3865 *
3866 * Geometry can be defined without passing in a style or data if required (thats how I prefer!)
3867 *
3868 * ```js
3869 * let geometry = new PIXI.Geometry();
3870 *
3871 * geometry.addAttribute('positions', [0, 0, 100, 0, 100, 100, 0, 100], 2);
3872 * geometry.addAttribute('uvs', [0,0,1,0,1,1,0,1],2)
3873 * geometry.addIndex([0,1,2,1,3,2])
3874 *
3875 * ```
3876 * @class
3877 * @memberof PIXI
3878 */
3879var Geometry = /** @class */ (function () {
3880 /**
3881 * @param {PIXI.Buffer[]} [buffers] - an array of buffers. optional.
3882 * @param {object} [attributes] - of the geometry, optional structure of the attributes layout
3883 */
3884 function Geometry(buffers, attributes) {
3885 if (buffers === void 0) { buffers = []; }
3886 if (attributes === void 0) { attributes = {}; }
3887 this.buffers = buffers;
3888 this.indexBuffer = null;
3889 this.attributes = attributes;
3890 /**
3891 * A map of renderer IDs to webgl VAOs
3892 *
3893 * @protected
3894 * @type {object}
3895 */
3896 this.glVertexArrayObjects = {};
3897 this.id = UID$1++;
3898 this.instanced = false;
3899 /**
3900 * Number of instances in this geometry, pass it to `GeometrySystem.draw()`
3901 * @member {number}
3902 * @default 1
3903 */
3904 this.instanceCount = 1;
3905 this.disposeRunner = new Runner('disposeGeometry');
3906 /**
3907 * Count of existing (not destroyed) meshes that reference this geometry
3908 * @member {number}
3909 */
3910 this.refCount = 0;
3911 }
3912 /**
3913 *
3914 * Adds an attribute to the geometry
3915 * Note: `stride` and `start` should be `undefined` if you dont know them, not 0!
3916 *
3917 * @param {String} id - the name of the attribute (matching up to a shader)
3918 * @param {PIXI.Buffer|number[]} buffer - the buffer that holds the data of the attribute . You can also provide an Array and a buffer will be created from it.
3919 * @param {Number} [size=0] - the size of the attribute. If you have 2 floats per vertex (eg position x and y) this would be 2
3920 * @param {Boolean} [normalized=false] - should the data be normalized.
3921 * @param {Number} [type=PIXI.TYPES.FLOAT] - what type of number is the attribute. Check {PIXI.TYPES} to see the ones available
3922 * @param {Number} [stride] - How far apart (in floats) the start of each value is. (used for interleaving data)
3923 * @param {Number} [start] - How far into the array to start reading values (used for interleaving data)
3924 * @param {boolean} [instance=false] - Instancing flag
3925 *
3926 * @return {PIXI.Geometry} returns self, useful for chaining.
3927 */
3928 Geometry.prototype.addAttribute = function (id, buffer, size, normalized, type, stride, start, instance) {
3929 if (size === void 0) { size = 0; }
3930 if (normalized === void 0) { normalized = false; }
3931 if (instance === void 0) { instance = false; }
3932 if (!buffer) {
3933 throw new Error('You must pass a buffer when creating an attribute');
3934 }
3935 // check if this is a buffer!
3936 if (!(buffer instanceof Buffer)) {
3937 // its an array!
3938 if (buffer instanceof Array) {
3939 buffer = new Float32Array(buffer);
3940 }
3941 buffer = new Buffer(buffer);
3942 }
3943 var ids = id.split('|');
3944 if (ids.length > 1) {
3945 for (var i = 0; i < ids.length; i++) {
3946 this.addAttribute(ids[i], buffer, size, normalized, type);
3947 }
3948 return this;
3949 }
3950 var bufferIndex = this.buffers.indexOf(buffer);
3951 if (bufferIndex === -1) {
3952 this.buffers.push(buffer);
3953 bufferIndex = this.buffers.length - 1;
3954 }
3955 this.attributes[id] = new Attribute(bufferIndex, size, normalized, type, stride, start, instance);
3956 // assuming that if there is instanced data then this will be drawn with instancing!
3957 this.instanced = this.instanced || instance;
3958 return this;
3959 };
3960 /**
3961 * returns the requested attribute
3962 *
3963 * @param {String} id - the name of the attribute required
3964 * @return {PIXI.Attribute} the attribute requested.
3965 */
3966 Geometry.prototype.getAttribute = function (id) {
3967 return this.attributes[id];
3968 };
3969 /**
3970 * returns the requested buffer
3971 *
3972 * @param {String} id - the name of the buffer required
3973 * @return {PIXI.Buffer} the buffer requested.
3974 */
3975 Geometry.prototype.getBuffer = function (id) {
3976 return this.buffers[this.getAttribute(id).buffer];
3977 };
3978 /**
3979 *
3980 * Adds an index buffer to the geometry
3981 * The index buffer contains integers, three for each triangle in the geometry, which reference the various attribute buffers (position, colour, UV coordinates, other UV coordinates, normal, …). There is only ONE index buffer.
3982 *
3983 * @param {PIXI.Buffer|number[]} [buffer] - the buffer that holds the data of the index buffer. You can also provide an Array and a buffer will be created from it.
3984 * @return {PIXI.Geometry} returns self, useful for chaining.
3985 */
3986 Geometry.prototype.addIndex = function (buffer) {
3987 if (!(buffer instanceof Buffer)) {
3988 // its an array!
3989 if (buffer instanceof Array) {
3990 buffer = new Uint16Array(buffer);
3991 }
3992 buffer = new Buffer(buffer);
3993 }
3994 buffer.index = true;
3995 this.indexBuffer = buffer;
3996 if (this.buffers.indexOf(buffer) === -1) {
3997 this.buffers.push(buffer);
3998 }
3999 return this;
4000 };
4001 /**
4002 * returns the index buffer
4003 *
4004 * @return {PIXI.Buffer} the index buffer.
4005 */
4006 Geometry.prototype.getIndex = function () {
4007 return this.indexBuffer;
4008 };
4009 /**
4010 * this function modifies the structure so that all current attributes become interleaved into a single buffer
4011 * This can be useful if your model remains static as it offers a little performance boost
4012 *
4013 * @return {PIXI.Geometry} returns self, useful for chaining.
4014 */
4015 Geometry.prototype.interleave = function () {
4016 // a simple check to see if buffers are already interleaved..
4017 if (this.buffers.length === 1 || (this.buffers.length === 2 && this.indexBuffer))
4018 { return this; }
4019 // assume already that no buffers are interleaved
4020 var arrays = [];
4021 var sizes = [];
4022 var interleavedBuffer = new Buffer();
4023 var i;
4024 for (i in this.attributes) {
4025 var attribute = this.attributes[i];
4026 var buffer = this.buffers[attribute.buffer];
4027 arrays.push(buffer.data);
4028 sizes.push((attribute.size * byteSizeMap[attribute.type]) / 4);
4029 attribute.buffer = 0;
4030 }
4031 interleavedBuffer.data = interleaveTypedArrays(arrays, sizes);
4032 for (i = 0; i < this.buffers.length; i++) {
4033 if (this.buffers[i] !== this.indexBuffer) {
4034 this.buffers[i].destroy();
4035 }
4036 }
4037 this.buffers = [interleavedBuffer];
4038 if (this.indexBuffer) {
4039 this.buffers.push(this.indexBuffer);
4040 }
4041 return this;
4042 };
4043 Geometry.prototype.getSize = function () {
4044 for (var i in this.attributes) {
4045 var attribute = this.attributes[i];
4046 var buffer = this.buffers[attribute.buffer];
4047 return buffer.data.length / ((attribute.stride / 4) || attribute.size);
4048 }
4049 return 0;
4050 };
4051 /**
4052 * disposes WebGL resources that are connected to this geometry
4053 */
4054 Geometry.prototype.dispose = function () {
4055 this.disposeRunner.emit(this, false);
4056 };
4057 /**
4058 * Destroys the geometry.
4059 */
4060 Geometry.prototype.destroy = function () {
4061 this.dispose();
4062 this.buffers = null;
4063 this.indexBuffer = null;
4064 this.attributes = null;
4065 };
4066 /**
4067 * returns a clone of the geometry
4068 *
4069 * @returns {PIXI.Geometry} a new clone of this geometry
4070 */
4071 Geometry.prototype.clone = function () {
4072 var geometry = new Geometry();
4073 for (var i = 0; i < this.buffers.length; i++) {
4074 geometry.buffers[i] = new Buffer(this.buffers[i].data.slice(0));
4075 }
4076 for (var i in this.attributes) {
4077 var attrib = this.attributes[i];
4078 geometry.attributes[i] = new Attribute(attrib.buffer, attrib.size, attrib.normalized, attrib.type, attrib.stride, attrib.start, attrib.instance);
4079 }
4080 if (this.indexBuffer) {
4081 geometry.indexBuffer = geometry.buffers[this.buffers.indexOf(this.indexBuffer)];
4082 geometry.indexBuffer.index = true;
4083 }
4084 return geometry;
4085 };
4086 /**
4087 * merges an array of geometries into a new single one
4088 * geometry attribute styles must match for this operation to work
4089 *
4090 * @param {PIXI.Geometry[]} geometries - array of geometries to merge
4091 * @returns {PIXI.Geometry} shiny new geometry!
4092 */
4093 Geometry.merge = function (geometries) {
4094 // todo add a geometry check!
4095 // also a size check.. cant be too big!]
4096 var geometryOut = new Geometry();
4097 var arrays = [];
4098 var sizes = [];
4099 var offsets = [];
4100 var geometry;
4101 // pass one.. get sizes..
4102 for (var i = 0; i < geometries.length; i++) {
4103 geometry = geometries[i];
4104 for (var j = 0; j < geometry.buffers.length; j++) {
4105 sizes[j] = sizes[j] || 0;
4106 sizes[j] += geometry.buffers[j].data.length;
4107 offsets[j] = 0;
4108 }
4109 }
4110 // build the correct size arrays..
4111 for (var i = 0; i < geometry.buffers.length; i++) {
4112 // TODO types!
4113 arrays[i] = new map$1[getBufferType(geometry.buffers[i].data)](sizes[i]);
4114 geometryOut.buffers[i] = new Buffer(arrays[i]);
4115 }
4116 // pass to set data..
4117 for (var i = 0; i < geometries.length; i++) {
4118 geometry = geometries[i];
4119 for (var j = 0; j < geometry.buffers.length; j++) {
4120 arrays[j].set(geometry.buffers[j].data, offsets[j]);
4121 offsets[j] += geometry.buffers[j].data.length;
4122 }
4123 }
4124 geometryOut.attributes = geometry.attributes;
4125 if (geometry.indexBuffer) {
4126 geometryOut.indexBuffer = geometryOut.buffers[geometry.buffers.indexOf(geometry.indexBuffer)];
4127 geometryOut.indexBuffer.index = true;
4128 var offset = 0;
4129 var stride = 0;
4130 var offset2 = 0;
4131 var bufferIndexToCount = 0;
4132 // get a buffer
4133 for (var i = 0; i < geometry.buffers.length; i++) {
4134 if (geometry.buffers[i] !== geometry.indexBuffer) {
4135 bufferIndexToCount = i;
4136 break;
4137 }
4138 }
4139 // figure out the stride of one buffer..
4140 for (var i in geometry.attributes) {
4141 var attribute = geometry.attributes[i];
4142 if ((attribute.buffer | 0) === bufferIndexToCount) {
4143 stride += ((attribute.size * byteSizeMap[attribute.type]) / 4);
4144 }
4145 }
4146 // time to off set all indexes..
4147 for (var i = 0; i < geometries.length; i++) {
4148 var indexBufferData = geometries[i].indexBuffer.data;
4149 for (var j = 0; j < indexBufferData.length; j++) {
4150 geometryOut.indexBuffer.data[j + offset2] += offset;
4151 }
4152 offset += geometry.buffers[bufferIndexToCount].data.length / (stride);
4153 offset2 += indexBufferData.length;
4154 }
4155 }
4156 return geometryOut;
4157 };
4158 return Geometry;
4159}());
4160
4161/**
4162 * Helper class to create a quad
4163 *
4164 * @class
4165 * @memberof PIXI
4166 */
4167var Quad = /** @class */ (function (_super) {
4168 __extends(Quad, _super);
4169 function Quad() {
4170 var _this = _super.call(this) || this;
4171 _this.addAttribute('aVertexPosition', new Float32Array([
4172 0, 0,
4173 1, 0,
4174 1, 1,
4175 0, 1 ]))
4176 .addIndex([0, 1, 3, 2]);
4177 return _this;
4178 }
4179 return Quad;
4180}(Geometry));
4181
4182/**
4183 * Helper class to create a quad with uvs like in v4
4184 *
4185 * @class
4186 * @memberof PIXI
4187 * @extends PIXI.Geometry
4188 */
4189var QuadUv = /** @class */ (function (_super) {
4190 __extends(QuadUv, _super);
4191 function QuadUv() {
4192 var _this = _super.call(this) || this;
4193 /**
4194 * An array of vertices
4195 *
4196 * @member {Float32Array}
4197 */
4198 _this.vertices = new Float32Array([
4199 -1, -1,
4200 1, -1,
4201 1, 1,
4202 -1, 1 ]);
4203 /**
4204 * The Uvs of the quad
4205 *
4206 * @member {Float32Array}
4207 */
4208 _this.uvs = new Float32Array([
4209 0, 0,
4210 1, 0,
4211 1, 1,
4212 0, 1 ]);
4213 _this.vertexBuffer = new Buffer(_this.vertices);
4214 _this.uvBuffer = new Buffer(_this.uvs);
4215 _this.addAttribute('aVertexPosition', _this.vertexBuffer)
4216 .addAttribute('aTextureCoord', _this.uvBuffer)
4217 .addIndex([0, 1, 2, 0, 2, 3]);
4218 return _this;
4219 }
4220 /**
4221 * Maps two Rectangle to the quad.
4222 *
4223 * @param {PIXI.Rectangle} targetTextureFrame - the first rectangle
4224 * @param {PIXI.Rectangle} destinationFrame - the second rectangle
4225 * @return {PIXI.Quad} Returns itself.
4226 */
4227 QuadUv.prototype.map = function (targetTextureFrame, destinationFrame) {
4228 var x = 0; // destinationFrame.x / targetTextureFrame.width;
4229 var y = 0; // destinationFrame.y / targetTextureFrame.height;
4230 this.uvs[0] = x;
4231 this.uvs[1] = y;
4232 this.uvs[2] = x + (destinationFrame.width / targetTextureFrame.width);
4233 this.uvs[3] = y;
4234 this.uvs[4] = x + (destinationFrame.width / targetTextureFrame.width);
4235 this.uvs[5] = y + (destinationFrame.height / targetTextureFrame.height);
4236 this.uvs[6] = x;
4237 this.uvs[7] = y + (destinationFrame.height / targetTextureFrame.height);
4238 x = destinationFrame.x;
4239 y = destinationFrame.y;
4240 this.vertices[0] = x;
4241 this.vertices[1] = y;
4242 this.vertices[2] = x + destinationFrame.width;
4243 this.vertices[3] = y;
4244 this.vertices[4] = x + destinationFrame.width;
4245 this.vertices[5] = y + destinationFrame.height;
4246 this.vertices[6] = x;
4247 this.vertices[7] = y + destinationFrame.height;
4248 this.invalidate();
4249 return this;
4250 };
4251 /**
4252 * legacy upload method, just marks buffers dirty
4253 * @returns {PIXI.QuadUv} Returns itself.
4254 */
4255 QuadUv.prototype.invalidate = function () {
4256 this.vertexBuffer._updateID++;
4257 this.uvBuffer._updateID++;
4258 return this;
4259 };
4260 return QuadUv;
4261}(Geometry));
4262
4263var UID$2 = 0;
4264/**
4265 * Uniform group holds uniform map and some ID's for work
4266 *
4267 * @class
4268 * @memberof PIXI
4269 */
4270var UniformGroup = /** @class */ (function () {
4271 /**
4272 * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones.
4273 * @param {boolean} [_static] - Uniforms wont be changed after creation
4274 */
4275 function UniformGroup(uniforms, _static) {
4276 /**
4277 * uniform values
4278 * @member {object}
4279 * @readonly
4280 */
4281 this.uniforms = uniforms;
4282 /**
4283 * Its a group and not a single uniforms
4284 * @member {boolean}
4285 * @readonly
4286 * @default true
4287 */
4288 this.group = true;
4289 // lets generate this when the shader ?
4290 this.syncUniforms = {};
4291 /**
4292 * dirty version
4293 * @protected
4294 * @member {number}
4295 */
4296 this.dirtyId = 0;
4297 /**
4298 * unique id
4299 * @protected
4300 * @member {number}
4301 */
4302 this.id = UID$2++;
4303 /**
4304 * Uniforms wont be changed after creation
4305 * @member {boolean}
4306 */
4307 this.static = !!_static;
4308 }
4309 UniformGroup.prototype.update = function () {
4310 this.dirtyId++;
4311 };
4312 UniformGroup.prototype.add = function (name, uniforms, _static) {
4313 this.uniforms[name] = new UniformGroup(uniforms, _static);
4314 };
4315 UniformGroup.from = function (uniforms, _static) {
4316 return new UniformGroup(uniforms, _static);
4317 };
4318 return UniformGroup;
4319}());
4320
4321/**
4322 * System plugin to the renderer to manage filter states.
4323 *
4324 * @class
4325 * @private
4326 */
4327var FilterState = /** @class */ (function () {
4328 function FilterState() {
4329 this.renderTexture = null;
4330 /**
4331 * Target of the filters
4332 * We store for case when custom filter wants to know the element it was applied on
4333 * @member {PIXI.DisplayObject}
4334 * @private
4335 */
4336 this.target = null;
4337 /**
4338 * Compatibility with PixiJS v4 filters
4339 * @member {boolean}
4340 * @default false
4341 * @private
4342 */
4343 this.legacy = false;
4344 /**
4345 * Resolution of filters
4346 * @member {number}
4347 * @default 1
4348 * @private
4349 */
4350 this.resolution = 1;
4351 // next three fields are created only for root
4352 // re-assigned for everything else
4353 /**
4354 * Source frame
4355 * @member {PIXI.Rectangle}
4356 * @private
4357 */
4358 this.sourceFrame = new Rectangle();
4359 /**
4360 * Destination frame
4361 * @member {PIXI.Rectangle}
4362 * @private
4363 */
4364 this.destinationFrame = new Rectangle();
4365 /**
4366 * Original render-target source frame
4367 * @private
4368 */
4369 this.bindingSourceFrame = new Rectangle();
4370 /**
4371 * Original render-target destination frame
4372 * @private
4373 */
4374 this.bindingDestinationFrame = new Rectangle();
4375 /**
4376 * Collection of filters
4377 * @member {PIXI.Filter[]}
4378 * @private
4379 */
4380 this.filters = [];
4381 /**
4382 * Projection system transform saved by link.
4383 * @member {PIXI.Matrix}
4384 * @private
4385 */
4386 this.transform = null;
4387 }
4388 /**
4389 * clears the state
4390 * @private
4391 */
4392 FilterState.prototype.clear = function () {
4393 this.target = null;
4394 this.filters = null;
4395 this.renderTexture = null;
4396 };
4397 return FilterState;
4398}());
4399
4400var tempPoints = [new Point(), new Point(), new Point(), new Point()];
4401var tempMatrix = new Matrix();
4402/**
4403 * System plugin to the renderer to manage filters.
4404 *
4405 * ## Pipeline
4406 *
4407 * The FilterSystem executes the filtering pipeline by rendering the display-object into a texture, applying its
4408 * [filters]{@link PIXI.Filter} in series, and the last filter outputs into the final render-target.
4409 *
4410 * The filter-frame is the rectangle in world space being filtered, and those contents are mapped into
4411 * `(0, 0, filterFrame.width, filterFrame.height)` into the filter render-texture. The filter-frame is also called
4412 * the source-frame, as it is used to bind the filter render-textures. The last filter outputs to the `filterFrame`
4413 * in the final render-target.
4414 *
4415 * ## Usage
4416 *
4417 * {@link PIXI.Container#renderAdvanced} is an example of how to use the filter system. It is a 3 step process:
4418 *
4419 * * **push**: Use {@link PIXI.FilterSystem#push} to push the set of filters to be applied on a filter-target.
4420 * * **render**: Render the contents to be filtered using the renderer. The filter-system will only capture the contents
4421 * inside the bounds of the filter-target. NOTE: Using {@link PIXI.Renderer#render} is
4422 * illegal during an existing render cycle, and it may reset the filter system.
4423 * * **pop**: Use {@link PIXI.FilterSystem#pop} to pop & execute the filters you initially pushed. It will apply them
4424 * serially and output to the bounds of the filter-target.
4425 *
4426 * @class
4427 * @memberof PIXI
4428 * @extends PIXI.System
4429 */
4430var FilterSystem = /** @class */ (function (_super) {
4431 __extends(FilterSystem, _super);
4432 /**
4433 * @param {PIXI.Renderer} renderer - The renderer this System works for.
4434 */
4435 function FilterSystem(renderer) {
4436 var _this = _super.call(this, renderer) || this;
4437 /**
4438 * List of filters for the FilterSystem
4439 * @member {Object[]}
4440 * @readonly
4441 */
4442 _this.defaultFilterStack = [{}];
4443 /**
4444 * stores a bunch of PO2 textures used for filtering
4445 * @member {Object}
4446 */
4447 _this.texturePool = new RenderTexturePool();
4448 _this.texturePool.setScreenSize(renderer.view);
4449 /**
4450 * a pool for storing filter states, save us creating new ones each tick
4451 * @member {Object[]}
4452 */
4453 _this.statePool = [];
4454 /**
4455 * A very simple geometry used when drawing a filter effect to the screen
4456 * @member {PIXI.Quad}
4457 */
4458 _this.quad = new Quad();
4459 /**
4460 * Quad UVs
4461 * @member {PIXI.QuadUv}
4462 */
4463 _this.quadUv = new QuadUv();
4464 /**
4465 * Temporary rect for maths
4466 * @type {PIXI.Rectangle}
4467 */
4468 _this.tempRect = new Rectangle();
4469 /**
4470 * Active state
4471 * @member {object}
4472 */
4473 _this.activeState = {};
4474 /**
4475 * This uniform group is attached to filter uniforms when used
4476 * @member {PIXI.UniformGroup}
4477 * @property {PIXI.Rectangle} outputFrame
4478 * @property {Float32Array} inputSize
4479 * @property {Float32Array} inputPixel
4480 * @property {Float32Array} inputClamp
4481 * @property {Number} resolution
4482 * @property {Float32Array} filterArea
4483 * @property {Float32Array} filterClamp
4484 */
4485 _this.globalUniforms = new UniformGroup({
4486 outputFrame: new Rectangle(),
4487 inputSize: new Float32Array(4),
4488 inputPixel: new Float32Array(4),
4489 inputClamp: new Float32Array(4),
4490 resolution: 1,
4491 // legacy variables
4492 filterArea: new Float32Array(4),
4493 filterClamp: new Float32Array(4),
4494 }, true);
4495 /**
4496 * Whether to clear output renderTexture in AUTO/BLIT mode. See {@link PIXI.CLEAR_MODES}
4497 * @member {boolean}
4498 */
4499 _this.forceClear = false;
4500 /**
4501 * Old padding behavior is to use the max amount instead of sum padding.
4502 * Use this flag if you need the old behavior.
4503 * @member {boolean}
4504 * @default false
4505 */
4506 _this.useMaxPadding = false;
4507 return _this;
4508 }
4509 /**
4510 * Pushes a set of filters to be applied later to the system. This will redirect further rendering into an
4511 * input render-texture for the rest of the filtering pipeline.
4512 *
4513 * @param {PIXI.DisplayObject} target - The target of the filter to render.
4514 * @param {PIXI.Filter[]} filters - The filters to apply.
4515 */
4516 FilterSystem.prototype.push = function (target, filters) {
4517 var renderer = this.renderer;
4518 var filterStack = this.defaultFilterStack;
4519 var state = this.statePool.pop() || new FilterState();
4520 var renderTextureSystem = this.renderer.renderTexture;
4521 var resolution = filters[0].resolution;
4522 var padding = filters[0].padding;
4523 var autoFit = filters[0].autoFit;
4524 var legacy = filters[0].legacy;
4525 for (var i = 1; i < filters.length; i++) {
4526 var filter = filters[i];
4527 // lets use the lowest resolution..
4528 resolution = Math.min(resolution, filter.resolution);
4529 // figure out the padding required for filters
4530 padding = this.useMaxPadding
4531 // old behavior: use largest amount of padding!
4532 ? Math.max(padding, filter.padding)
4533 // new behavior: sum the padding
4534 : padding + filter.padding;
4535 // only auto fit if all filters are autofit
4536 autoFit = autoFit && filter.autoFit;
4537 legacy = legacy || filter.legacy;
4538 }
4539 if (filterStack.length === 1) {
4540 this.defaultFilterStack[0].renderTexture = renderTextureSystem.current;
4541 }
4542 filterStack.push(state);
4543 state.resolution = resolution;
4544 state.legacy = legacy;
4545 state.target = target;
4546 state.sourceFrame.copyFrom(target.filterArea || target.getBounds(true));
4547 state.sourceFrame.pad(padding);
4548 if (autoFit) {
4549 var sourceFrameProjected = this.tempRect.copyFrom(renderTextureSystem.sourceFrame);
4550 // Project source frame into world space (if projection is applied)
4551 if (renderer.projection.transform) {
4552 this.transformAABB(tempMatrix.copyFrom(renderer.projection.transform).invert(), sourceFrameProjected);
4553 }
4554 state.sourceFrame.fit(sourceFrameProjected);
4555 }
4556 // Round sourceFrame in screen space based on render-texture.
4557 this.roundFrame(state.sourceFrame, renderTextureSystem.current ? renderTextureSystem.current.resolution : renderer.resolution, renderTextureSystem.sourceFrame, renderTextureSystem.destinationFrame, renderer.projection.transform);
4558 state.renderTexture = this.getOptimalFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution);
4559 state.filters = filters;
4560 state.destinationFrame.width = state.renderTexture.width;
4561 state.destinationFrame.height = state.renderTexture.height;
4562 var destinationFrame = this.tempRect;
4563 destinationFrame.x = 0;
4564 destinationFrame.y = 0;
4565 destinationFrame.width = state.sourceFrame.width;
4566 destinationFrame.height = state.sourceFrame.height;
4567 state.renderTexture.filterFrame = state.sourceFrame;
4568 state.bindingSourceFrame.copyFrom(renderTextureSystem.sourceFrame);
4569 state.bindingDestinationFrame.copyFrom(renderTextureSystem.destinationFrame);
4570 state.transform = renderer.projection.transform;
4571 renderer.projection.transform = null;
4572 renderTextureSystem.bind(state.renderTexture, state.sourceFrame, destinationFrame);
4573 renderer.framebuffer.clear(0, 0, 0, 0);
4574 };
4575 /**
4576 * Pops off the filter and applies it.
4577 */
4578 FilterSystem.prototype.pop = function () {
4579 var filterStack = this.defaultFilterStack;
4580 var state = filterStack.pop();
4581 var filters = state.filters;
4582 this.activeState = state;
4583 var globalUniforms = this.globalUniforms.uniforms;
4584 globalUniforms.outputFrame = state.sourceFrame;
4585 globalUniforms.resolution = state.resolution;
4586 var inputSize = globalUniforms.inputSize;
4587 var inputPixel = globalUniforms.inputPixel;
4588 var inputClamp = globalUniforms.inputClamp;
4589 inputSize[0] = state.destinationFrame.width;
4590 inputSize[1] = state.destinationFrame.height;
4591 inputSize[2] = 1.0 / inputSize[0];
4592 inputSize[3] = 1.0 / inputSize[1];
4593 inputPixel[0] = inputSize[0] * state.resolution;
4594 inputPixel[1] = inputSize[1] * state.resolution;
4595 inputPixel[2] = 1.0 / inputPixel[0];
4596 inputPixel[3] = 1.0 / inputPixel[1];
4597 inputClamp[0] = 0.5 * inputPixel[2];
4598 inputClamp[1] = 0.5 * inputPixel[3];
4599 inputClamp[2] = (state.sourceFrame.width * inputSize[2]) - (0.5 * inputPixel[2]);
4600 inputClamp[3] = (state.sourceFrame.height * inputSize[3]) - (0.5 * inputPixel[3]);
4601 // only update the rect if its legacy..
4602 if (state.legacy) {
4603 var filterArea = globalUniforms.filterArea;
4604 filterArea[0] = state.destinationFrame.width;
4605 filterArea[1] = state.destinationFrame.height;
4606 filterArea[2] = state.sourceFrame.x;
4607 filterArea[3] = state.sourceFrame.y;
4608 globalUniforms.filterClamp = globalUniforms.inputClamp;
4609 }
4610 this.globalUniforms.update();
4611 var lastState = filterStack[filterStack.length - 1];
4612 if (state.renderTexture.framebuffer.multisample > 1) {
4613 this.renderer.framebuffer.blit();
4614 }
4615 if (filters.length === 1) {
4616 filters[0].apply(this, state.renderTexture, lastState.renderTexture, CLEAR_MODES.BLEND, state);
4617 this.returnFilterTexture(state.renderTexture);
4618 }
4619 else {
4620 var flip = state.renderTexture;
4621 var flop = this.getOptimalFilterTexture(flip.width, flip.height, state.resolution);
4622 flop.filterFrame = flip.filterFrame;
4623 var i = 0;
4624 for (i = 0; i < filters.length - 1; ++i) {
4625 filters[i].apply(this, flip, flop, CLEAR_MODES.CLEAR, state);
4626 var t = flip;
4627 flip = flop;
4628 flop = t;
4629 }
4630 filters[i].apply(this, flip, lastState.renderTexture, CLEAR_MODES.BLEND, state);
4631 this.returnFilterTexture(flip);
4632 this.returnFilterTexture(flop);
4633 }
4634 state.clear();
4635 this.statePool.push(state);
4636 };
4637 /**
4638 * Binds a renderTexture with corresponding `filterFrame`, clears it if mode corresponds.
4639 *
4640 * @param {PIXI.RenderTexture} filterTexture - renderTexture to bind, should belong to filter pool or filter stack
4641 * @param {PIXI.CLEAR_MODES} [clearMode] - clearMode, by default its CLEAR/YES. See {@link PIXI.CLEAR_MODES}
4642 */
4643 FilterSystem.prototype.bindAndClear = function (filterTexture, clearMode) {
4644 if (clearMode === void 0) { clearMode = CLEAR_MODES.CLEAR; }
4645 var _a = this.renderer, renderTextureSystem = _a.renderTexture, stateSystem = _a.state;
4646 if (filterTexture === this.defaultFilterStack[this.defaultFilterStack.length - 1].renderTexture) {
4647 // Restore projection transform if rendering into the output render-target.
4648 this.renderer.projection.transform = this.activeState.transform;
4649 }
4650 else {
4651 // Prevent projection within filtering pipeline.
4652 this.renderer.projection.transform = null;
4653 }
4654 if (filterTexture && filterTexture.filterFrame) {
4655 var destinationFrame = this.tempRect;
4656 destinationFrame.x = 0;
4657 destinationFrame.y = 0;
4658 destinationFrame.width = filterTexture.filterFrame.width;
4659 destinationFrame.height = filterTexture.filterFrame.height;
4660 renderTextureSystem.bind(filterTexture, filterTexture.filterFrame, destinationFrame);
4661 }
4662 else if (filterTexture !== this.defaultFilterStack[this.defaultFilterStack.length - 1].renderTexture) {
4663 renderTextureSystem.bind(filterTexture);
4664 }
4665 else {
4666 // Restore binding for output render-target.
4667 this.renderer.renderTexture.bind(filterTexture, this.activeState.bindingSourceFrame, this.activeState.bindingDestinationFrame);
4668 }
4669 // Clear the texture in BLIT mode if blending is disabled or the forceClear flag is set. The blending
4670 // is stored in the 0th bit of the state.
4671 var autoClear = (stateSystem.stateId & 1) || this.forceClear;
4672 if (clearMode === CLEAR_MODES.CLEAR
4673 || (clearMode === CLEAR_MODES.BLIT && autoClear)) {
4674 // Use framebuffer.clear because we want to clear the whole filter texture, not just the filtering
4675 // area over which the shaders are run. This is because filters may sampling outside of it (e.g. blur)
4676 // instead of clamping their arithmetic.
4677 this.renderer.framebuffer.clear(0, 0, 0, 0);
4678 }
4679 };
4680 /**
4681 * Draws a filter.
4682 *
4683 * @param {PIXI.Filter} filter - The filter to draw.
4684 * @param {PIXI.RenderTexture} input - The input render target.
4685 * @param {PIXI.RenderTexture} output - The target to output to.
4686 * @param {PIXI.CLEAR_MODES} [clearMode] - Should the output be cleared before rendering to it
4687 */
4688 FilterSystem.prototype.applyFilter = function (filter, input, output, clearMode) {
4689 var renderer = this.renderer;
4690 // Set state before binding, so bindAndClear gets the blend mode.
4691 renderer.state.set(filter.state);
4692 this.bindAndClear(output, clearMode);
4693 // set the uniforms..
4694 filter.uniforms.uSampler = input;
4695 filter.uniforms.filterGlobals = this.globalUniforms;
4696 // TODO make it so that the order of this does not matter..
4697 // because it does at the moment cos of global uniforms.
4698 // they need to get resynced
4699 renderer.shader.bind(filter);
4700 if (filter.legacy) {
4701 this.quadUv.map(input._frame, input.filterFrame);
4702 renderer.geometry.bind(this.quadUv);
4703 renderer.geometry.draw(DRAW_MODES.TRIANGLES);
4704 }
4705 else {
4706 renderer.geometry.bind(this.quad);
4707 renderer.geometry.draw(DRAW_MODES.TRIANGLE_STRIP);
4708 }
4709 };
4710 /**
4711 * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_.
4712 *
4713 * Use `outputMatrix * vTextureCoord` in the shader.
4714 *
4715 * @param {PIXI.Matrix} outputMatrix - The matrix to output to.
4716 * @param {PIXI.Sprite} sprite - The sprite to map to.
4717 * @return {PIXI.Matrix} The mapped matrix.
4718 */
4719 FilterSystem.prototype.calculateSpriteMatrix = function (outputMatrix, sprite) {
4720 var _a = this.activeState, sourceFrame = _a.sourceFrame, destinationFrame = _a.destinationFrame;
4721 var orig = sprite._texture.orig;
4722 var mappedMatrix = outputMatrix.set(destinationFrame.width, 0, 0, destinationFrame.height, sourceFrame.x, sourceFrame.y);
4723 var worldTransform = sprite.worldTransform.copyTo(Matrix.TEMP_MATRIX);
4724 worldTransform.invert();
4725 mappedMatrix.prepend(worldTransform);
4726 mappedMatrix.scale(1.0 / orig.width, 1.0 / orig.height);
4727 mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);
4728 return mappedMatrix;
4729 };
4730 /**
4731 * Destroys this Filter System.
4732 */
4733 FilterSystem.prototype.destroy = function () {
4734 // Those textures has to be destroyed by RenderTextureSystem or FramebufferSystem
4735 this.texturePool.clear(false);
4736 };
4737 /**
4738 * Gets a Power-of-Two render texture or fullScreen texture
4739 *
4740 * @protected
4741 * @param {number} minWidth - The minimum width of the render texture in real pixels.
4742 * @param {number} minHeight - The minimum height of the render texture in real pixels.
4743 * @param {number} [resolution=1] - The resolution of the render texture.
4744 * @return {PIXI.RenderTexture} The new render texture.
4745 */
4746 FilterSystem.prototype.getOptimalFilterTexture = function (minWidth, minHeight, resolution) {
4747 if (resolution === void 0) { resolution = 1; }
4748 return this.texturePool.getOptimalTexture(minWidth, minHeight, resolution);
4749 };
4750 /**
4751 * Gets extra render texture to use inside current filter
4752 * To be compliant with older filters, you can use params in any order
4753 *
4754 * @param {PIXI.RenderTexture} [input] - renderTexture from which size and resolution will be copied
4755 * @param {number} [resolution] - override resolution of the renderTexture
4756 * @returns {PIXI.RenderTexture}
4757 */
4758 FilterSystem.prototype.getFilterTexture = function (input, resolution) {
4759 if (typeof input === 'number') {
4760 var swap = input;
4761 input = resolution;
4762 resolution = swap;
4763 }
4764 input = input || this.activeState.renderTexture;
4765 var filterTexture = this.texturePool.getOptimalTexture(input.width, input.height, resolution || input.resolution);
4766 filterTexture.filterFrame = input.filterFrame;
4767 return filterTexture;
4768 };
4769 /**
4770 * Frees a render texture back into the pool.
4771 *
4772 * @param {PIXI.RenderTexture} renderTexture - The renderTarget to free
4773 */
4774 FilterSystem.prototype.returnFilterTexture = function (renderTexture) {
4775 this.texturePool.returnTexture(renderTexture);
4776 };
4777 /**
4778 * Empties the texture pool.
4779 */
4780 FilterSystem.prototype.emptyPool = function () {
4781 this.texturePool.clear(true);
4782 };
4783 /**
4784 * calls `texturePool.resize()`, affects fullScreen renderTextures
4785 */
4786 FilterSystem.prototype.resize = function () {
4787 this.texturePool.setScreenSize(this.renderer.view);
4788 };
4789 /**
4790 * @param {PIXI.Matrix} matrix - first param
4791 * @param {PIXI.Rectangle} rect - second param
4792 */
4793 FilterSystem.prototype.transformAABB = function (matrix, rect) {
4794 var lt = tempPoints[0];
4795 var lb = tempPoints[1];
4796 var rt = tempPoints[2];
4797 var rb = tempPoints[3];
4798 lt.set(rect.left, rect.top);
4799 lb.set(rect.left, rect.bottom);
4800 rt.set(rect.right, rect.top);
4801 rb.set(rect.right, rect.bottom);
4802 matrix.apply(lt, lt);
4803 matrix.apply(lb, lb);
4804 matrix.apply(rt, rt);
4805 matrix.apply(rb, rb);
4806 var x0 = Math.min(lt.x, lb.x, rt.x, rb.x);
4807 var y0 = Math.min(lt.y, lb.y, rt.y, rb.y);
4808 var x1 = Math.max(lt.x, lb.x, rt.x, rb.x);
4809 var y1 = Math.max(lt.y, lb.y, rt.y, rb.y);
4810 rect.x = x0;
4811 rect.y = y0;
4812 rect.width = x1 - x0;
4813 rect.height = y1 - y0;
4814 };
4815 FilterSystem.prototype.roundFrame = function (frame, resolution, bindingSourceFrame, bindingDestinationFrame, transform) {
4816 if (transform) {
4817 var a = transform.a, b = transform.b, c = transform.c, d = transform.d;
4818 // Skip if skew/rotation present in matrix, except for multiple of 90° rotation. If rotation
4819 // is a multiple of 90°, then either pair of (b,c) or (a,d) will be (0,0).
4820 if ((b !== 0 || c !== 0) && (a !== 0 || d !== 0)) {
4821 return;
4822 }
4823 }
4824 transform = transform ? tempMatrix.copyFrom(transform) : tempMatrix.identity();
4825 // Get forward transform from world space to screen space
4826 transform
4827 .translate(-bindingSourceFrame.x, -bindingSourceFrame.y)
4828 .scale(bindingDestinationFrame.width / bindingSourceFrame.width, bindingDestinationFrame.height / bindingSourceFrame.height)
4829 .translate(bindingDestinationFrame.x, bindingDestinationFrame.y);
4830 // Convert frame to screen space
4831 this.transformAABB(transform, frame);
4832 // Round frame in screen space
4833 frame.ceil(resolution);
4834 // Project back into world space.
4835 this.transformAABB(transform.invert(), frame);
4836 };
4837 return FilterSystem;
4838}(System));
4839
4840/**
4841 * Base for a common object renderer that can be used as a
4842 * system renderer plugin.
4843 *
4844 * @class
4845 * @extends PIXI.System
4846 * @memberof PIXI
4847 */
4848var ObjectRenderer = /** @class */ (function () {
4849 /**
4850 * @param {PIXI.Renderer} renderer - The renderer this manager works for.
4851 */
4852 function ObjectRenderer(renderer) {
4853 /**
4854 * The renderer this manager works for.
4855 *
4856 * @member {PIXI.Renderer}
4857 */
4858 this.renderer = renderer;
4859 }
4860 /**
4861 * Stub method that should be used to empty the current
4862 * batch by rendering objects now.
4863 */
4864 ObjectRenderer.prototype.flush = function () {
4865 // flush!
4866 };
4867 /**
4868 * Generic destruction method that frees all resources. This
4869 * should be called by subclasses.
4870 */
4871 ObjectRenderer.prototype.destroy = function () {
4872 this.renderer = null;
4873 };
4874 /**
4875 * Stub method that initializes any state required before
4876 * rendering starts. It is different from the `prerender`
4877 * signal, which occurs every frame, in that it is called
4878 * whenever an object requests _this_ renderer specifically.
4879 */
4880 ObjectRenderer.prototype.start = function () {
4881 // set the shader..
4882 };
4883 /**
4884 * Stops the renderer. It should free up any state and
4885 * become dormant.
4886 */
4887 ObjectRenderer.prototype.stop = function () {
4888 this.flush();
4889 };
4890 /**
4891 * Keeps the object to render. It doesn't have to be
4892 * rendered immediately.
4893 *
4894 * @param {PIXI.DisplayObject} object - The object to render.
4895 */
4896 ObjectRenderer.prototype.render = function (_object) {
4897 // render the object
4898 };
4899 return ObjectRenderer;
4900}());
4901
4902/**
4903 * System plugin to the renderer to manage batching.
4904 *
4905 * @class
4906 * @extends PIXI.System
4907 * @memberof PIXI
4908 */
4909var BatchSystem = /** @class */ (function (_super) {
4910 __extends(BatchSystem, _super);
4911 /**
4912 * @param {PIXI.Renderer} renderer - The renderer this System works for.
4913 */
4914 function BatchSystem(renderer) {
4915 var _this = _super.call(this, renderer) || this;
4916 /**
4917 * An empty renderer.
4918 *
4919 * @member {PIXI.ObjectRenderer}
4920 */
4921 _this.emptyRenderer = new ObjectRenderer(renderer);
4922 /**
4923 * The currently active ObjectRenderer.
4924 *
4925 * @member {PIXI.ObjectRenderer}
4926 */
4927 _this.currentRenderer = _this.emptyRenderer;
4928 return _this;
4929 }
4930 /**
4931 * Changes the current renderer to the one given in parameter
4932 *
4933 * @param {PIXI.ObjectRenderer} objectRenderer - The object renderer to use.
4934 */
4935 BatchSystem.prototype.setObjectRenderer = function (objectRenderer) {
4936 if (this.currentRenderer === objectRenderer) {
4937 return;
4938 }
4939 this.currentRenderer.stop();
4940 this.currentRenderer = objectRenderer;
4941 this.currentRenderer.start();
4942 };
4943 /**
4944 * This should be called if you wish to do some custom rendering
4945 * It will basically render anything that may be batched up such as sprites
4946 */
4947 BatchSystem.prototype.flush = function () {
4948 this.setObjectRenderer(this.emptyRenderer);
4949 };
4950 /**
4951 * Reset the system to an empty renderer
4952 */
4953 BatchSystem.prototype.reset = function () {
4954 this.setObjectRenderer(this.emptyRenderer);
4955 };
4956 /**
4957 * Handy function for batch renderers: copies bound textures in first maxTextures locations to array
4958 * sets actual _batchLocation for them
4959 *
4960 * @param {PIXI.BaseTexture[]} arr - arr copy destination
4961 * @param {number} maxTextures - number of copied elements
4962 */
4963 BatchSystem.prototype.copyBoundTextures = function (arr, maxTextures) {
4964 var boundTextures = this.renderer.texture.boundTextures;
4965 for (var i = maxTextures - 1; i >= 0; --i) {
4966 arr[i] = boundTextures[i] || null;
4967 if (arr[i]) {
4968 arr[i]._batchLocation = i;
4969 }
4970 }
4971 };
4972 /**
4973 * Assigns batch locations to textures in array based on boundTextures state.
4974 * All textures in texArray should have `_batchEnabled = _batchId`,
4975 * and their count should be less than `maxTextures`.
4976 *
4977 * @param {PIXI.BatchTextureArray} texArray - textures to bound
4978 * @param {PIXI.BaseTexture[]} boundTextures - current state of bound textures
4979 * @param {number} batchId - marker for _batchEnabled param of textures in texArray
4980 * @param {number} maxTextures - number of texture locations to manipulate
4981 */
4982 BatchSystem.prototype.boundArray = function (texArray, boundTextures, batchId, maxTextures) {
4983 var elements = texArray.elements, ids = texArray.ids, count = texArray.count;
4984 var j = 0;
4985 for (var i = 0; i < count; i++) {
4986 var tex = elements[i];
4987 var loc = tex._batchLocation;
4988 if (loc >= 0 && loc < maxTextures
4989 && boundTextures[loc] === tex) {
4990 ids[i] = loc;
4991 continue;
4992 }
4993 while (j < maxTextures) {
4994 var bound = boundTextures[j];
4995 if (bound && bound._batchEnabled === batchId
4996 && bound._batchLocation === j) {
4997 j++;
4998 continue;
4999 }
5000 ids[i] = j;
5001 tex._batchLocation = j;
5002 boundTextures[j] = tex;
5003 break;
5004 }
5005 }
5006 };
5007 return BatchSystem;
5008}(System));
5009
5010var CONTEXT_UID_COUNTER = 0;
5011/**
5012 * System plugin to the renderer to manage the context.
5013 *
5014 * @class
5015 * @extends PIXI.System
5016 * @memberof PIXI
5017 */
5018var ContextSystem = /** @class */ (function (_super) {
5019 __extends(ContextSystem, _super);
5020 /**
5021 * @param {PIXI.Renderer} renderer - The renderer this System works for.
5022 */
5023 function ContextSystem(renderer) {
5024 var _this = _super.call(this, renderer) || this;
5025 /**
5026 * Either 1 or 2 to reflect the WebGL version being used
5027 * @member {number}
5028 * @readonly
5029 */
5030 _this.webGLVersion = 1;
5031 /**
5032 * Extensions being used
5033 * @member {object}
5034 * @readonly
5035 * @property {WEBGL_draw_buffers} drawBuffers - WebGL v1 extension
5036 * @property {WEBGL_depth_texture} depthTexture - WebGL v1 extension
5037 * @property {OES_texture_float} floatTexture - WebGL v1 extension
5038 * @property {WEBGL_lose_context} loseContext - WebGL v1 extension
5039 * @property {OES_vertex_array_object} vertexArrayObject - WebGL v1 extension
5040 * @property {EXT_texture_filter_anisotropic} anisotropicFiltering - WebGL v1 and v2 extension
5041 */
5042 _this.extensions = {};
5043 /**
5044 * Features supported by current context
5045 * @member {object}
5046 * @private
5047 * @readonly
5048 * @property {boolean} uint32Indices - Supports of 32-bit indices buffer
5049 */
5050 _this.supports = {
5051 uint32Indices: false,
5052 };
5053 // Bind functions
5054 _this.handleContextLost = _this.handleContextLost.bind(_this);
5055 _this.handleContextRestored = _this.handleContextRestored.bind(_this);
5056 renderer.view.addEventListener('webglcontextlost', _this.handleContextLost, false);
5057 renderer.view.addEventListener('webglcontextrestored', _this.handleContextRestored, false);
5058 return _this;
5059 }
5060 Object.defineProperty(ContextSystem.prototype, "isLost", {
5061 /**
5062 * `true` if the context is lost
5063 * @member {boolean}
5064 * @readonly
5065 */
5066 get: function () {
5067 return (!this.gl || this.gl.isContextLost());
5068 },
5069 enumerable: false,
5070 configurable: true
5071 });
5072 /**
5073 * Handle the context change event
5074 * @param {WebGLRenderingContext} gl - new webgl context
5075 */
5076 ContextSystem.prototype.contextChange = function (gl) {
5077 this.gl = gl;
5078 this.renderer.gl = gl;
5079 this.renderer.CONTEXT_UID = CONTEXT_UID_COUNTER++;
5080 // restore a context if it was previously lost
5081 if (gl.isContextLost() && gl.getExtension('WEBGL_lose_context')) {
5082 gl.getExtension('WEBGL_lose_context').restoreContext();
5083 }
5084 };
5085 /**
5086 * Initialize the context
5087 *
5088 * @protected
5089 * @param {WebGLRenderingContext} gl - WebGL context
5090 */
5091 ContextSystem.prototype.initFromContext = function (gl) {
5092 this.gl = gl;
5093 this.validateContext(gl);
5094 this.renderer.gl = gl;
5095 this.renderer.CONTEXT_UID = CONTEXT_UID_COUNTER++;
5096 this.renderer.runners.contextChange.emit(gl);
5097 };
5098 /**
5099 * Initialize from context options
5100 *
5101 * @protected
5102 * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
5103 * @param {object} options - context attributes
5104 */
5105 ContextSystem.prototype.initFromOptions = function (options) {
5106 var gl = this.createContext(this.renderer.view, options);
5107 this.initFromContext(gl);
5108 };
5109 /**
5110 * Helper class to create a WebGL Context
5111 *
5112 * @param {HTMLCanvasElement} canvas - the canvas element that we will get the context from
5113 * @param {object} options - An options object that gets passed in to the canvas element containing the
5114 * context attributes
5115 * @see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext
5116 * @return {WebGLRenderingContext} the WebGL context
5117 */
5118 ContextSystem.prototype.createContext = function (canvas, options) {
5119 var gl;
5120 if (settings.PREFER_ENV >= ENV.WEBGL2) {
5121 gl = canvas.getContext('webgl2', options);
5122 }
5123 if (gl) {
5124 this.webGLVersion = 2;
5125 }
5126 else {
5127 this.webGLVersion = 1;
5128 gl = canvas.getContext('webgl', options)
5129 || canvas.getContext('experimental-webgl', options);
5130 if (!gl) {
5131 // fail, not able to get a context
5132 throw new Error('This browser does not support WebGL. Try using the canvas renderer');
5133 }
5134 }
5135 this.gl = gl;
5136 this.getExtensions();
5137 return this.gl;
5138 };
5139 /**
5140 * Auto-populate the extensions
5141 *
5142 * @protected
5143 */
5144 ContextSystem.prototype.getExtensions = function () {
5145 // time to set up default extensions that Pixi uses.
5146 var gl = this.gl;
5147 var common = {
5148 anisotropicFiltering: gl.getExtension('EXT_texture_filter_anisotropic'),
5149 floatTextureLinear: gl.getExtension('OES_texture_float_linear'),
5150 s3tc: gl.getExtension('WEBGL_compressed_texture_s3tc'),
5151 s3tc_sRGB: gl.getExtension('WEBGL_compressed_texture_s3tc_srgb'),
5152 etc: gl.getExtension('WEBGL_compressed_texture_etc'),
5153 etc1: gl.getExtension('WEBGL_compressed_texture_etc1'),
5154 pvrtc: gl.getExtension('WEBGL_compressed_texture_pvrtc')
5155 || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc'),
5156 atc: gl.getExtension('WEBGL_compressed_texture_atc'),
5157 astc: gl.getExtension('WEBGL_compressed_texture_astc')
5158 };
5159 if (this.webGLVersion === 1) {
5160 Object.assign(this.extensions, common, {
5161 drawBuffers: gl.getExtension('WEBGL_draw_buffers'),
5162 depthTexture: gl.getExtension('WEBGL_depth_texture'),
5163 loseContext: gl.getExtension('WEBGL_lose_context'),
5164 vertexArrayObject: gl.getExtension('OES_vertex_array_object')
5165 || gl.getExtension('MOZ_OES_vertex_array_object')
5166 || gl.getExtension('WEBKIT_OES_vertex_array_object'),
5167 uint32ElementIndex: gl.getExtension('OES_element_index_uint'),
5168 // Floats and half-floats
5169 floatTexture: gl.getExtension('OES_texture_float'),
5170 floatTextureLinear: gl.getExtension('OES_texture_float_linear'),
5171 textureHalfFloat: gl.getExtension('OES_texture_half_float'),
5172 textureHalfFloatLinear: gl.getExtension('OES_texture_half_float_linear'),
5173 });
5174 }
5175 else if (this.webGLVersion === 2) {
5176 Object.assign(this.extensions, common, {
5177 // Floats and half-floats
5178 colorBufferFloat: gl.getExtension('EXT_color_buffer_float')
5179 });
5180 }
5181 };
5182 /**
5183 * Handles a lost webgl context
5184 *
5185 * @protected
5186 * @param {WebGLContextEvent} event - The context lost event.
5187 */
5188 ContextSystem.prototype.handleContextLost = function (event) {
5189 event.preventDefault();
5190 };
5191 /**
5192 * Handles a restored webgl context
5193 *
5194 * @protected
5195 */
5196 ContextSystem.prototype.handleContextRestored = function () {
5197 this.renderer.runners.contextChange.emit(this.gl);
5198 };
5199 ContextSystem.prototype.destroy = function () {
5200 var view = this.renderer.view;
5201 // remove listeners
5202 view.removeEventListener('webglcontextlost', this.handleContextLost);
5203 view.removeEventListener('webglcontextrestored', this.handleContextRestored);
5204 this.gl.useProgram(null);
5205 if (this.extensions.loseContext) {
5206 this.extensions.loseContext.loseContext();
5207 }
5208 };
5209 /**
5210 * Handle the post-render runner event
5211 *
5212 * @protected
5213 */
5214 ContextSystem.prototype.postrender = function () {
5215 if (this.renderer.renderingToScreen) {
5216 this.gl.flush();
5217 }
5218 };
5219 /**
5220 * Validate context
5221 *
5222 * @protected
5223 * @param {WebGLRenderingContext} gl - Render context
5224 */
5225 ContextSystem.prototype.validateContext = function (gl) {
5226 var attributes = gl.getContextAttributes();
5227 var isWebGl2 = 'WebGL2RenderingContext' in self && gl instanceof self.WebGL2RenderingContext;
5228 if (isWebGl2) {
5229 this.webGLVersion = 2;
5230 }
5231 // this is going to be fairly simple for now.. but at least we have room to grow!
5232 if (!attributes.stencil) {
5233 /* eslint-disable max-len, no-console */
5234 console.warn('Provided WebGL context does not have a stencil buffer, masks may not render correctly');
5235 /* eslint-enable max-len, no-console */
5236 }
5237 var hasuint32 = isWebGl2 || !!gl.getExtension('OES_element_index_uint');
5238 this.supports.uint32Indices = hasuint32;
5239 if (!hasuint32) {
5240 /* eslint-disable max-len, no-console */
5241 console.warn('Provided WebGL context does not support 32 index buffer, complex graphics may not render correctly');
5242 /* eslint-enable max-len, no-console */
5243 }
5244 };
5245 return ContextSystem;
5246}(System));
5247
5248/**
5249 * Internal framebuffer for WebGL context
5250 * @class
5251 * @memberof PIXI
5252 */
5253var GLFramebuffer = /** @class */ (function () {
5254 function GLFramebuffer(framebuffer) {
5255 /**
5256 * The WebGL framebuffer
5257 * @member {WebGLFramebuffer}
5258 */
5259 this.framebuffer = framebuffer;
5260 /**
5261 * stencil+depth , usually costs 32bits per pixel
5262 * @member {WebGLRenderbuffer}
5263 */
5264 this.stencil = null;
5265 /**
5266 * latest known version of framebuffer
5267 * @member {number}
5268 * @protected
5269 */
5270 this.dirtyId = 0;
5271 /**
5272 * latest known version of framebuffer format
5273 * @member {number}
5274 * @protected
5275 */
5276 this.dirtyFormat = 0;
5277 /**
5278 * latest known version of framebuffer size
5279 * @member {number}
5280 * @protected
5281 */
5282 this.dirtySize = 0;
5283 /**
5284 * Detected AA samples number
5285 * @member {PIXI.MSAA_QUALITY}
5286 */
5287 this.multisample = MSAA_QUALITY.NONE;
5288 /**
5289 * In case MSAA, we use this Renderbuffer instead of colorTextures[0] when we write info
5290 * @member {WebGLRenderbuffer}
5291 */
5292 this.msaaBuffer = null;
5293 /**
5294 * In case we use MSAA, this is actual framebuffer that has colorTextures[0]
5295 * The contents of that framebuffer are read when we use that renderTexture in sprites
5296 * @member {PIXI.Framebuffer}
5297 */
5298 this.blitFramebuffer = null;
5299 }
5300 return GLFramebuffer;
5301}());
5302
5303var tempRectangle = new Rectangle();
5304/**
5305 * System plugin to the renderer to manage framebuffers.
5306 *
5307 * @class
5308 * @extends PIXI.System
5309 * @memberof PIXI
5310 */
5311var FramebufferSystem = /** @class */ (function (_super) {
5312 __extends(FramebufferSystem, _super);
5313 /**
5314 * @param {PIXI.Renderer} renderer - The renderer this System works for.
5315 */
5316 function FramebufferSystem(renderer) {
5317 var _this = _super.call(this, renderer) || this;
5318 /**
5319 * A list of managed framebuffers
5320 * @member {PIXI.Framebuffer[]}
5321 * @readonly
5322 */
5323 _this.managedFramebuffers = [];
5324 /**
5325 * Framebuffer value that shows that we don't know what is bound
5326 * @member {Framebuffer}
5327 * @readonly
5328 */
5329 _this.unknownFramebuffer = new Framebuffer(10, 10);
5330 _this.msaaSamples = null;
5331 return _this;
5332 }
5333 /**
5334 * Sets up the renderer context and necessary buffers.
5335 */
5336 FramebufferSystem.prototype.contextChange = function () {
5337 var gl = this.gl = this.renderer.gl;
5338 this.CONTEXT_UID = this.renderer.CONTEXT_UID;
5339 this.current = this.unknownFramebuffer;
5340 this.viewport = new Rectangle();
5341 this.hasMRT = true;
5342 this.writeDepthTexture = true;
5343 this.disposeAll(true);
5344 // webgl2
5345 if (this.renderer.context.webGLVersion === 1) {
5346 // webgl 1!
5347 var nativeDrawBuffersExtension_1 = this.renderer.context.extensions.drawBuffers;
5348 var nativeDepthTextureExtension = this.renderer.context.extensions.depthTexture;
5349 if (settings.PREFER_ENV === ENV.WEBGL_LEGACY) {
5350 nativeDrawBuffersExtension_1 = null;
5351 nativeDepthTextureExtension = null;
5352 }
5353 if (nativeDrawBuffersExtension_1) {
5354 gl.drawBuffers = function (activeTextures) {
5355 return nativeDrawBuffersExtension_1.drawBuffersWEBGL(activeTextures);
5356 };
5357 }
5358 else {
5359 this.hasMRT = false;
5360 gl.drawBuffers = function () {
5361 // empty
5362 };
5363 }
5364 if (!nativeDepthTextureExtension) {
5365 this.writeDepthTexture = false;
5366 }
5367 }
5368 else {
5369 // WebGL2
5370 // cache possible MSAA samples
5371 this.msaaSamples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);
5372 }
5373 };
5374 /**
5375 * Bind a framebuffer
5376 *
5377 * @param {PIXI.Framebuffer} [framebuffer]
5378 * @param {PIXI.Rectangle} [frame] - frame, default is framebuffer size
5379 */
5380 FramebufferSystem.prototype.bind = function (framebuffer, frame) {
5381 var gl = this.gl;
5382 if (framebuffer) {
5383 // TODO caching layer!
5384 var fbo = framebuffer.glFramebuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer);
5385 if (this.current !== framebuffer) {
5386 this.current = framebuffer;
5387 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer);
5388 }
5389 // make sure all textures are unbound..
5390 // now check for updates...
5391 if (fbo.dirtyId !== framebuffer.dirtyId) {
5392 fbo.dirtyId = framebuffer.dirtyId;
5393 if (fbo.dirtyFormat !== framebuffer.dirtyFormat) {
5394 fbo.dirtyFormat = framebuffer.dirtyFormat;
5395 this.updateFramebuffer(framebuffer);
5396 }
5397 else if (fbo.dirtySize !== framebuffer.dirtySize) {
5398 fbo.dirtySize = framebuffer.dirtySize;
5399 this.resizeFramebuffer(framebuffer);
5400 }
5401 }
5402 for (var i = 0; i < framebuffer.colorTextures.length; i++) {
5403 var tex = framebuffer.colorTextures[i];
5404 this.renderer.texture.unbind(tex.parentTextureArray || tex);
5405 }
5406 if (framebuffer.depthTexture) {
5407 this.renderer.texture.unbind(framebuffer.depthTexture);
5408 }
5409 if (frame) {
5410 this.setViewport(frame.x, frame.y, frame.width, frame.height);
5411 }
5412 else {
5413 this.setViewport(0, 0, framebuffer.width, framebuffer.height);
5414 }
5415 }
5416 else {
5417 if (this.current) {
5418 this.current = null;
5419 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
5420 }
5421 if (frame) {
5422 this.setViewport(frame.x, frame.y, frame.width, frame.height);
5423 }
5424 else {
5425 this.setViewport(0, 0, this.renderer.width, this.renderer.height);
5426 }
5427 }
5428 };
5429 /**
5430 * Set the WebGLRenderingContext's viewport.
5431 *
5432 * @param {Number} x - X position of viewport
5433 * @param {Number} y - Y position of viewport
5434 * @param {Number} width - Width of viewport
5435 * @param {Number} height - Height of viewport
5436 */
5437 FramebufferSystem.prototype.setViewport = function (x, y, width, height) {
5438 var v = this.viewport;
5439 if (v.width !== width || v.height !== height || v.x !== x || v.y !== y) {
5440 v.x = x;
5441 v.y = y;
5442 v.width = width;
5443 v.height = height;
5444 this.gl.viewport(x, y, width, height);
5445 }
5446 };
5447 Object.defineProperty(FramebufferSystem.prototype, "size", {
5448 /**
5449 * Get the size of the current width and height. Returns object with `width` and `height` values.
5450 *
5451 * @member {object}
5452 * @readonly
5453 */
5454 get: function () {
5455 if (this.current) {
5456 // TODO store temp
5457 return { x: 0, y: 0, width: this.current.width, height: this.current.height };
5458 }
5459 return { x: 0, y: 0, width: this.renderer.width, height: this.renderer.height };
5460 },
5461 enumerable: false,
5462 configurable: true
5463 });
5464 /**
5465 * Clear the color of the context
5466 *
5467 * @param {Number} r - Red value from 0 to 1
5468 * @param {Number} g - Green value from 0 to 1
5469 * @param {Number} b - Blue value from 0 to 1
5470 * @param {Number} a - Alpha value from 0 to 1
5471 * @param {PIXI.BUFFER_BITS} [mask=BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH] - Bitwise OR of masks
5472 * that indicate the buffers to be cleared, by default COLOR and DEPTH buffers.
5473 */
5474 FramebufferSystem.prototype.clear = function (r, g, b, a, mask) {
5475 if (mask === void 0) { mask = BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH; }
5476 var gl = this.gl;
5477 // TODO clear color can be set only one right?
5478 gl.clearColor(r, g, b, a);
5479 gl.clear(mask);
5480 };
5481 /**
5482 * Initialize framebuffer for this context
5483 *
5484 * @protected
5485 * @param {PIXI.Framebuffer} framebuffer
5486 * @returns {PIXI.GLFramebuffer} created GLFramebuffer
5487 */
5488 FramebufferSystem.prototype.initFramebuffer = function (framebuffer) {
5489 var gl = this.gl;
5490 var fbo = new GLFramebuffer(gl.createFramebuffer());
5491 fbo.multisample = this.detectSamples(framebuffer.multisample);
5492 framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo;
5493 this.managedFramebuffers.push(framebuffer);
5494 framebuffer.disposeRunner.add(this);
5495 return fbo;
5496 };
5497 /**
5498 * Resize the framebuffer
5499 *
5500 * @protected
5501 * @param {PIXI.Framebuffer} framebuffer
5502 */
5503 FramebufferSystem.prototype.resizeFramebuffer = function (framebuffer) {
5504 var gl = this.gl;
5505 var fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];
5506 if (fbo.stencil) {
5507 gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil);
5508 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, framebuffer.width, framebuffer.height);
5509 }
5510 var colorTextures = framebuffer.colorTextures;
5511 for (var i = 0; i < colorTextures.length; i++) {
5512 this.renderer.texture.bind(colorTextures[i], 0);
5513 }
5514 if (framebuffer.depthTexture) {
5515 this.renderer.texture.bind(framebuffer.depthTexture, 0);
5516 }
5517 };
5518 /**
5519 * Update the framebuffer
5520 *
5521 * @protected
5522 * @param {PIXI.Framebuffer} framebuffer
5523 */
5524 FramebufferSystem.prototype.updateFramebuffer = function (framebuffer) {
5525 var gl = this.gl;
5526 var fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];
5527 // bind the color texture
5528 var colorTextures = framebuffer.colorTextures;
5529 var count = colorTextures.length;
5530 if (!gl.drawBuffers) {
5531 count = Math.min(count, 1);
5532 }
5533 if (fbo.multisample > 1) {
5534 fbo.msaaBuffer = gl.createRenderbuffer();
5535 gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer);
5536 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, fbo.multisample, gl.RGBA8, framebuffer.width, framebuffer.height);
5537 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, fbo.msaaBuffer);
5538 }
5539 var activeTextures = [];
5540 for (var i = 0; i < count; i++) {
5541 if (i === 0 && fbo.multisample > 1) {
5542 continue;
5543 }
5544 var texture = framebuffer.colorTextures[i];
5545 var parentTexture = texture.parentTextureArray || texture;
5546 this.renderer.texture.bind(parentTexture, 0);
5547 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, texture.target, parentTexture._glTextures[this.CONTEXT_UID].texture, 0);
5548 activeTextures.push(gl.COLOR_ATTACHMENT0 + i);
5549 }
5550 if (activeTextures.length > 1) {
5551 gl.drawBuffers(activeTextures);
5552 }
5553 if (framebuffer.depthTexture) {
5554 var writeDepthTexture = this.writeDepthTexture;
5555 if (writeDepthTexture) {
5556 var depthTexture = framebuffer.depthTexture;
5557 this.renderer.texture.bind(depthTexture, 0);
5558 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture._glTextures[this.CONTEXT_UID].texture, 0);
5559 }
5560 }
5561 if (!fbo.stencil && (framebuffer.stencil || framebuffer.depth)) {
5562 fbo.stencil = gl.createRenderbuffer();
5563 gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil);
5564 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, framebuffer.width, framebuffer.height);
5565 // TODO.. this is depth AND stencil?
5566 if (!framebuffer.depthTexture) { // you can't have both, so one should take priority if enabled
5567 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, fbo.stencil);
5568 }
5569 }
5570 };
5571 /**
5572 * Detects number of samples that is not more than a param but as close to it as possible
5573 *
5574 * @param {PIXI.MSAA_QUALITY} samples - number of samples
5575 * @returns {PIXI.MSAA_QUALITY} - recommended number of samples
5576 */
5577 FramebufferSystem.prototype.detectSamples = function (samples) {
5578 var msaaSamples = this.msaaSamples;
5579 var res = MSAA_QUALITY.NONE;
5580 if (samples <= 1 || msaaSamples === null) {
5581 return res;
5582 }
5583 for (var i = 0; i < msaaSamples.length; i++) {
5584 if (msaaSamples[i] <= samples) {
5585 res = msaaSamples[i];
5586 break;
5587 }
5588 }
5589 if (res === 1) {
5590 res = MSAA_QUALITY.NONE;
5591 }
5592 return res;
5593 };
5594 /**
5595 * Only works with WebGL2
5596 *
5597 * blits framebuffer to another of the same or bigger size
5598 * after that target framebuffer is bound
5599 *
5600 * Fails with WebGL warning if blits multisample framebuffer to different size
5601 *
5602 * @param {PIXI.Framebuffer} [framebuffer] - by default it blits "into itself", from renderBuffer to texture.
5603 * @param {PIXI.Rectangle} [sourcePixels] - source rectangle in pixels
5604 * @param {PIXI.Rectangle} [destPixels] - dest rectangle in pixels, assumed to be the same as sourcePixels
5605 */
5606 FramebufferSystem.prototype.blit = function (framebuffer, sourcePixels, destPixels) {
5607 var _a = this, current = _a.current, renderer = _a.renderer, gl = _a.gl, CONTEXT_UID = _a.CONTEXT_UID;
5608 if (renderer.context.webGLVersion !== 2) {
5609 return;
5610 }
5611 if (!current) {
5612 return;
5613 }
5614 var fbo = current.glFramebuffers[CONTEXT_UID];
5615 if (!fbo) {
5616 return;
5617 }
5618 if (!framebuffer) {
5619 if (fbo.multisample <= 1) {
5620 return;
5621 }
5622 if (!fbo.blitFramebuffer) {
5623 fbo.blitFramebuffer = new Framebuffer(current.width, current.height);
5624 fbo.blitFramebuffer.addColorTexture(0, current.colorTextures[0]);
5625 }
5626 framebuffer = fbo.blitFramebuffer;
5627 framebuffer.width = current.width;
5628 framebuffer.height = current.height;
5629 }
5630 if (!sourcePixels) {
5631 sourcePixels = tempRectangle;
5632 sourcePixels.width = current.width;
5633 sourcePixels.height = current.height;
5634 }
5635 if (!destPixels) {
5636 destPixels = sourcePixels;
5637 }
5638 var sameSize = sourcePixels.width === destPixels.width && sourcePixels.height === destPixels.height;
5639 this.bind(framebuffer);
5640 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo.framebuffer);
5641 gl.blitFramebuffer(sourcePixels.x, sourcePixels.y, sourcePixels.width, sourcePixels.height, destPixels.x, destPixels.y, destPixels.width, destPixels.height, gl.COLOR_BUFFER_BIT, sameSize ? gl.NEAREST : gl.LINEAR);
5642 };
5643 /**
5644 * Disposes framebuffer
5645 * @param {PIXI.Framebuffer} framebuffer - framebuffer that has to be disposed of
5646 * @param {boolean} [contextLost=false] - If context was lost, we suppress all delete function calls
5647 */
5648 FramebufferSystem.prototype.disposeFramebuffer = function (framebuffer, contextLost) {
5649 var fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];
5650 var gl = this.gl;
5651 if (!fbo) {
5652 return;
5653 }
5654 delete framebuffer.glFramebuffers[this.CONTEXT_UID];
5655 var index = this.managedFramebuffers.indexOf(framebuffer);
5656 if (index >= 0) {
5657 this.managedFramebuffers.splice(index, 1);
5658 }
5659 framebuffer.disposeRunner.remove(this);
5660 if (!contextLost) {
5661 gl.deleteFramebuffer(fbo.framebuffer);
5662 if (fbo.stencil) {
5663 gl.deleteRenderbuffer(fbo.stencil);
5664 }
5665 }
5666 };
5667 /**
5668 * Disposes all framebuffers, but not textures bound to them
5669 * @param {boolean} [contextLost=false] - If context was lost, we suppress all delete function calls
5670 */
5671 FramebufferSystem.prototype.disposeAll = function (contextLost) {
5672 var list = this.managedFramebuffers;
5673 this.managedFramebuffers = [];
5674 for (var i = 0; i < list.length; i++) {
5675 this.disposeFramebuffer(list[i], contextLost);
5676 }
5677 };
5678 /**
5679 * Forcing creation of stencil buffer for current framebuffer, if it wasn't done before.
5680 * Used by MaskSystem, when its time to use stencil mask for Graphics element.
5681 *
5682 * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind.
5683 *
5684 * @private
5685 */
5686 FramebufferSystem.prototype.forceStencil = function () {
5687 var framebuffer = this.current;
5688 if (!framebuffer) {
5689 return;
5690 }
5691 var fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];
5692 if (!fbo || fbo.stencil) {
5693 return;
5694 }
5695 framebuffer.enableStencil();
5696 var w = framebuffer.width;
5697 var h = framebuffer.height;
5698 var gl = this.gl;
5699 var stencil = gl.createRenderbuffer();
5700 gl.bindRenderbuffer(gl.RENDERBUFFER, stencil);
5701 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, w, h);
5702 fbo.stencil = stencil;
5703 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil);
5704 };
5705 /**
5706 * resets framebuffer stored state, binds screen framebuffer
5707 *
5708 * should be called before renderTexture reset()
5709 */
5710 FramebufferSystem.prototype.reset = function () {
5711 this.current = this.unknownFramebuffer;
5712 this.viewport = new Rectangle();
5713 };
5714 return FramebufferSystem;
5715}(System));
5716
5717var GLBuffer = /** @class */ (function () {
5718 function GLBuffer(buffer) {
5719 this.buffer = buffer || null;
5720 this.updateID = -1;
5721 this.byteLength = -1;
5722 this.refCount = 0;
5723 }
5724 return GLBuffer;
5725}());
5726
5727var byteSizeMap$1 = { 5126: 4, 5123: 2, 5121: 1 };
5728/**
5729 * System plugin to the renderer to manage geometry.
5730 *
5731 * @class
5732 * @extends PIXI.System
5733 * @memberof PIXI
5734 */
5735var GeometrySystem = /** @class */ (function (_super) {
5736 __extends(GeometrySystem, _super);
5737 /**
5738 * @param {PIXI.Renderer} renderer - The renderer this System works for.
5739 */
5740 function GeometrySystem(renderer) {
5741 var _this = _super.call(this, renderer) || this;
5742 _this._activeGeometry = null;
5743 _this._activeVao = null;
5744 /**
5745 * `true` if we has `*_vertex_array_object` extension
5746 * @member {boolean}
5747 * @readonly
5748 */
5749 _this.hasVao = true;
5750 /**
5751 * `true` if has `ANGLE_instanced_arrays` extension
5752 * @member {boolean}
5753 * @readonly
5754 */
5755 _this.hasInstance = true;
5756 /**
5757 * `true` if support `gl.UNSIGNED_INT` in `gl.drawElements` or `gl.drawElementsInstanced`
5758 * @member {boolean}
5759 * @readonly
5760 */
5761 _this.canUseUInt32ElementIndex = false;
5762 /**
5763 * Cache for all geometries by id, used in case renderer gets destroyed or for profiling
5764 * @member {object}
5765 * @readonly
5766 */
5767 _this.managedGeometries = {};
5768 /**
5769 * Cache for all buffers by id, used in case renderer gets destroyed or for profiling
5770 * @member {object}
5771 * @readonly
5772 */
5773 _this.managedBuffers = {};
5774 return _this;
5775 }
5776 /**
5777 * Sets up the renderer context and necessary buffers.
5778 */
5779 GeometrySystem.prototype.contextChange = function () {
5780 this.disposeAll(true);
5781 var gl = this.gl = this.renderer.gl;
5782 var context = this.renderer.context;
5783 this.CONTEXT_UID = this.renderer.CONTEXT_UID;
5784 // webgl2
5785 if (context.webGLVersion !== 2) {
5786 // webgl 1!
5787 var nativeVaoExtension_1 = this.renderer.context.extensions.vertexArrayObject;
5788 if (settings.PREFER_ENV === ENV.WEBGL_LEGACY) {
5789 nativeVaoExtension_1 = null;
5790 }
5791 if (nativeVaoExtension_1) {
5792 gl.createVertexArray = function () {
5793 return nativeVaoExtension_1.createVertexArrayOES();
5794 };
5795 gl.bindVertexArray = function (vao) {
5796 return nativeVaoExtension_1.bindVertexArrayOES(vao);
5797 };
5798 gl.deleteVertexArray = function (vao) {
5799 return nativeVaoExtension_1.deleteVertexArrayOES(vao);
5800 };
5801 }
5802 else {
5803 this.hasVao = false;
5804 gl.createVertexArray = function () {
5805 return null;
5806 };
5807 gl.bindVertexArray = function () {
5808 return null;
5809 };
5810 gl.deleteVertexArray = function () {
5811 return null;
5812 };
5813 }
5814 }
5815 if (context.webGLVersion !== 2) {
5816 var instanceExt_1 = gl.getExtension('ANGLE_instanced_arrays');
5817 if (instanceExt_1) {
5818 gl.vertexAttribDivisor = function (a, b) {
5819 return instanceExt_1.vertexAttribDivisorANGLE(a, b);
5820 };
5821 gl.drawElementsInstanced = function (a, b, c, d, e) {
5822 return instanceExt_1.drawElementsInstancedANGLE(a, b, c, d, e);
5823 };
5824 gl.drawArraysInstanced = function (a, b, c, d) {
5825 return instanceExt_1.drawArraysInstancedANGLE(a, b, c, d);
5826 };
5827 }
5828 else {
5829 this.hasInstance = false;
5830 }
5831 }
5832 this.canUseUInt32ElementIndex = context.webGLVersion === 2 || !!context.extensions.uint32ElementIndex;
5833 };
5834 /**
5835 * Binds geometry so that is can be drawn. Creating a Vao if required
5836 *
5837 * @param {PIXI.Geometry} geometry - instance of geometry to bind
5838 * @param {PIXI.Shader} [shader] - instance of shader to use vao for
5839 */
5840 GeometrySystem.prototype.bind = function (geometry, shader) {
5841 shader = shader || this.renderer.shader.shader;
5842 var gl = this.gl;
5843 // not sure the best way to address this..
5844 // currently different shaders require different VAOs for the same geometry
5845 // Still mulling over the best way to solve this one..
5846 // will likely need to modify the shader attribute locations at run time!
5847 var vaos = geometry.glVertexArrayObjects[this.CONTEXT_UID];
5848 var incRefCount = false;
5849 if (!vaos) {
5850 this.managedGeometries[geometry.id] = geometry;
5851 geometry.disposeRunner.add(this);
5852 geometry.glVertexArrayObjects[this.CONTEXT_UID] = vaos = {};
5853 incRefCount = true;
5854 }
5855 var vao = vaos[shader.program.id] || this.initGeometryVao(geometry, shader.program, incRefCount);
5856 this._activeGeometry = geometry;
5857 if (this._activeVao !== vao) {
5858 this._activeVao = vao;
5859 if (this.hasVao) {
5860 gl.bindVertexArray(vao);
5861 }
5862 else {
5863 this.activateVao(geometry, shader.program);
5864 }
5865 }
5866 // TODO - optimise later!
5867 // don't need to loop through if nothing changed!
5868 // maybe look to add an 'autoupdate' to geometry?
5869 this.updateBuffers();
5870 };
5871 /**
5872 * Reset and unbind any active VAO and geometry
5873 */
5874 GeometrySystem.prototype.reset = function () {
5875 this.unbind();
5876 };
5877 /**
5878 * Update buffers
5879 * @protected
5880 */
5881 GeometrySystem.prototype.updateBuffers = function () {
5882 var geometry = this._activeGeometry;
5883 var gl = this.gl;
5884 for (var i = 0; i < geometry.buffers.length; i++) {
5885 var buffer = geometry.buffers[i];
5886 var glBuffer = buffer._glBuffers[this.CONTEXT_UID];
5887 if (buffer._updateID !== glBuffer.updateID) {
5888 glBuffer.updateID = buffer._updateID;
5889 // TODO can cache this on buffer! maybe added a getter / setter?
5890 var type = buffer.index ? gl.ELEMENT_ARRAY_BUFFER : gl.ARRAY_BUFFER;
5891 // TODO this could change if the VAO changes...
5892 // need to come up with a better way to cache..
5893 // if (this.boundBuffers[type] !== glBuffer)
5894 // {
5895 // this.boundBuffers[type] = glBuffer;
5896 gl.bindBuffer(type, glBuffer.buffer);
5897 // }
5898 this._boundBuffer = glBuffer;
5899 if (glBuffer.byteLength >= buffer.data.byteLength) {
5900 // offset is always zero for now!
5901 gl.bufferSubData(type, 0, buffer.data);
5902 }
5903 else {
5904 var drawType = buffer.static ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
5905 glBuffer.byteLength = buffer.data.byteLength;
5906 gl.bufferData(type, buffer.data, drawType);
5907 }
5908 }
5909 }
5910 };
5911 /**
5912 * Check compatibility between a geometry and a program
5913 * @protected
5914 * @param {PIXI.Geometry} geometry - Geometry instance
5915 * @param {PIXI.Program} program - Program instance
5916 */
5917 GeometrySystem.prototype.checkCompatibility = function (geometry, program) {
5918 // geometry must have at least all the attributes that the shader requires.
5919 var geometryAttributes = geometry.attributes;
5920 var shaderAttributes = program.attributeData;
5921 for (var j in shaderAttributes) {
5922 if (!geometryAttributes[j]) {
5923 throw new Error("shader and geometry incompatible, geometry missing the \"" + j + "\" attribute");
5924 }
5925 }
5926 };
5927 /**
5928 * Takes a geometry and program and generates a unique signature for them.
5929 *
5930 * @param {PIXI.Geometry} geometry - to get signature from
5931 * @param {PIXI.Program} program - to test geometry against
5932 * @returns {String} Unique signature of the geometry and program
5933 * @protected
5934 */
5935 GeometrySystem.prototype.getSignature = function (geometry, program) {
5936 var attribs = geometry.attributes;
5937 var shaderAttributes = program.attributeData;
5938 var strings = ['g', geometry.id];
5939 for (var i in attribs) {
5940 if (shaderAttributes[i]) {
5941 strings.push(i);
5942 }
5943 }
5944 return strings.join('-');
5945 };
5946 /**
5947 * Creates or gets Vao with the same structure as the geometry and stores it on the geometry.
5948 * If vao is created, it is bound automatically.
5949 *
5950 * @protected
5951 * @param {PIXI.Geometry} geometry - Instance of geometry to to generate Vao for
5952 * @param {PIXI.Program} program - Instance of program
5953 * @param {boolean} [incRefCount=false] - Increment refCount of all geometry buffers
5954 */
5955 GeometrySystem.prototype.initGeometryVao = function (geometry, program, incRefCount) {
5956 if (incRefCount === void 0) { incRefCount = true; }
5957 this.checkCompatibility(geometry, program);
5958 var gl = this.gl;
5959 var CONTEXT_UID = this.CONTEXT_UID;
5960 var signature = this.getSignature(geometry, program);
5961 var vaoObjectHash = geometry.glVertexArrayObjects[this.CONTEXT_UID];
5962 var vao = vaoObjectHash[signature];
5963 if (vao) {
5964 // this will give us easy access to the vao
5965 vaoObjectHash[program.id] = vao;
5966 return vao;
5967 }
5968 var buffers = geometry.buffers;
5969 var attributes = geometry.attributes;
5970 var tempStride = {};
5971 var tempStart = {};
5972 for (var j in buffers) {
5973 tempStride[j] = 0;
5974 tempStart[j] = 0;
5975 }
5976 for (var j in attributes) {
5977 if (!attributes[j].size && program.attributeData[j]) {
5978 attributes[j].size = program.attributeData[j].size;
5979 }
5980 else if (!attributes[j].size) {
5981 console.warn("PIXI Geometry attribute '" + j + "' size cannot be determined (likely the bound shader does not have the attribute)"); // eslint-disable-line
5982 }
5983 tempStride[attributes[j].buffer] += attributes[j].size * byteSizeMap$1[attributes[j].type];
5984 }
5985 for (var j in attributes) {
5986 var attribute = attributes[j];
5987 var attribSize = attribute.size;
5988 if (attribute.stride === undefined) {
5989 if (tempStride[attribute.buffer] === attribSize * byteSizeMap$1[attribute.type]) {
5990 attribute.stride = 0;
5991 }
5992 else {
5993 attribute.stride = tempStride[attribute.buffer];
5994 }
5995 }
5996 if (attribute.start === undefined) {
5997 attribute.start = tempStart[attribute.buffer];
5998 tempStart[attribute.buffer] += attribSize * byteSizeMap$1[attribute.type];
5999 }
6000 }
6001 vao = gl.createVertexArray();
6002 gl.bindVertexArray(vao);
6003 // first update - and create the buffers!
6004 // only create a gl buffer if it actually gets
6005 for (var i = 0; i < buffers.length; i++) {
6006 var buffer = buffers[i];
6007 if (!buffer._glBuffers[CONTEXT_UID]) {
6008 buffer._glBuffers[CONTEXT_UID] = new GLBuffer(gl.createBuffer());
6009 this.managedBuffers[buffer.id] = buffer;
6010 buffer.disposeRunner.add(this);
6011 }
6012 if (incRefCount) {
6013 buffer._glBuffers[CONTEXT_UID].refCount++;
6014 }
6015 }
6016 // TODO - maybe make this a data object?
6017 // lets wait to see if we need to first!
6018 this.activateVao(geometry, program);
6019 this._activeVao = vao;
6020 // add it to the cache!
6021 vaoObjectHash[program.id] = vao;
6022 vaoObjectHash[signature] = vao;
6023 return vao;
6024 };
6025 /**
6026 * Disposes buffer
6027 * @param {PIXI.Buffer} buffer - buffer with data
6028 * @param {boolean} [contextLost=false] - If context was lost, we suppress deleteVertexArray
6029 */
6030 GeometrySystem.prototype.disposeBuffer = function (buffer, contextLost) {
6031 if (!this.managedBuffers[buffer.id]) {
6032 return;
6033 }
6034 delete this.managedBuffers[buffer.id];
6035 var glBuffer = buffer._glBuffers[this.CONTEXT_UID];
6036 var gl = this.gl;
6037 buffer.disposeRunner.remove(this);
6038 if (!glBuffer) {
6039 return;
6040 }
6041 if (!contextLost) {
6042 gl.deleteBuffer(glBuffer.buffer);
6043 }
6044 delete buffer._glBuffers[this.CONTEXT_UID];
6045 };
6046 /**
6047 * Disposes geometry
6048 * @param {PIXI.Geometry} geometry - Geometry with buffers. Only VAO will be disposed
6049 * @param {boolean} [contextLost=false] - If context was lost, we suppress deleteVertexArray
6050 */
6051 GeometrySystem.prototype.disposeGeometry = function (geometry, contextLost) {
6052 if (!this.managedGeometries[geometry.id]) {
6053 return;
6054 }
6055 delete this.managedGeometries[geometry.id];
6056 var vaos = geometry.glVertexArrayObjects[this.CONTEXT_UID];
6057 var gl = this.gl;
6058 var buffers = geometry.buffers;
6059 geometry.disposeRunner.remove(this);
6060 if (!vaos) {
6061 return;
6062 }
6063 for (var i = 0; i < buffers.length; i++) {
6064 var buf = buffers[i]._glBuffers[this.CONTEXT_UID];
6065 buf.refCount--;
6066 if (buf.refCount === 0 && !contextLost) {
6067 this.disposeBuffer(buffers[i], contextLost);
6068 }
6069 }
6070 if (!contextLost) {
6071 for (var vaoId in vaos) {
6072 // delete only signatures, everything else are copies
6073 if (vaoId[0] === 'g') {
6074 var vao = vaos[vaoId];
6075 if (this._activeVao === vao) {
6076 this.unbind();
6077 }
6078 gl.deleteVertexArray(vao);
6079 }
6080 }
6081 }
6082 delete geometry.glVertexArrayObjects[this.CONTEXT_UID];
6083 };
6084 /**
6085 * dispose all WebGL resources of all managed geometries and buffers
6086 * @param {boolean} [contextLost=false] - If context was lost, we suppress `gl.delete` calls
6087 */
6088 GeometrySystem.prototype.disposeAll = function (contextLost) {
6089 var all = Object.keys(this.managedGeometries);
6090 for (var i = 0; i < all.length; i++) {
6091 this.disposeGeometry(this.managedGeometries[all[i]], contextLost);
6092 }
6093 all = Object.keys(this.managedBuffers);
6094 for (var i = 0; i < all.length; i++) {
6095 this.disposeBuffer(this.managedBuffers[all[i]], contextLost);
6096 }
6097 };
6098 /**
6099 * Activate vertex array object
6100 *
6101 * @protected
6102 * @param {PIXI.Geometry} geometry - Geometry instance
6103 * @param {PIXI.Program} program - Shader program instance
6104 */
6105 GeometrySystem.prototype.activateVao = function (geometry, program) {
6106 var gl = this.gl;
6107 var CONTEXT_UID = this.CONTEXT_UID;
6108 var buffers = geometry.buffers;
6109 var attributes = geometry.attributes;
6110 if (geometry.indexBuffer) {
6111 // first update the index buffer if we have one..
6112 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geometry.indexBuffer._glBuffers[CONTEXT_UID].buffer);
6113 }
6114 var lastBuffer = null;
6115 // add a new one!
6116 for (var j in attributes) {
6117 var attribute = attributes[j];
6118 var buffer = buffers[attribute.buffer];
6119 var glBuffer = buffer._glBuffers[CONTEXT_UID];
6120 if (program.attributeData[j]) {
6121 if (lastBuffer !== glBuffer) {
6122 gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer.buffer);
6123 lastBuffer = glBuffer;
6124 }
6125 var location = program.attributeData[j].location;
6126 // TODO introduce state again
6127 // we can optimise this for older devices that have no VAOs
6128 gl.enableVertexAttribArray(location);
6129 gl.vertexAttribPointer(location, attribute.size, attribute.type || gl.FLOAT, attribute.normalized, attribute.stride, attribute.start);
6130 if (attribute.instance) {
6131 // TODO calculate instance count based of this...
6132 if (this.hasInstance) {
6133 gl.vertexAttribDivisor(location, 1);
6134 }
6135 else {
6136 throw new Error('geometry error, GPU Instancing is not supported on this device');
6137 }
6138 }
6139 }
6140 }
6141 };
6142 /**
6143 * Draw the geometry
6144 *
6145 * @param {Number} type - the type primitive to render
6146 * @param {Number} [size] - the number of elements to be rendered
6147 * @param {Number} [start] - Starting index
6148 * @param {Number} [instanceCount] - the number of instances of the set of elements to execute
6149 */
6150 GeometrySystem.prototype.draw = function (type, size, start, instanceCount) {
6151 var gl = this.gl;
6152 var geometry = this._activeGeometry;
6153 // TODO.. this should not change so maybe cache the function?
6154 if (geometry.indexBuffer) {
6155 var byteSize = geometry.indexBuffer.data.BYTES_PER_ELEMENT;
6156 var glType = byteSize === 2 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
6157 if (byteSize === 2 || (byteSize === 4 && this.canUseUInt32ElementIndex)) {
6158 if (geometry.instanced) {
6159 /* eslint-disable max-len */
6160 gl.drawElementsInstanced(type, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize, instanceCount || 1);
6161 /* eslint-enable max-len */
6162 }
6163 else {
6164 /* eslint-disable max-len */
6165 gl.drawElements(type, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize);
6166 /* eslint-enable max-len */
6167 }
6168 }
6169 else {
6170 console.warn('unsupported index buffer type: uint32');
6171 }
6172 }
6173 else if (geometry.instanced) {
6174 // TODO need a better way to calculate size..
6175 gl.drawArraysInstanced(type, start, size || geometry.getSize(), instanceCount || 1);
6176 }
6177 else {
6178 gl.drawArrays(type, start, size || geometry.getSize());
6179 }
6180 return this;
6181 };
6182 /**
6183 * Unbind/reset everything
6184 * @protected
6185 */
6186 GeometrySystem.prototype.unbind = function () {
6187 this.gl.bindVertexArray(null);
6188 this._activeVao = null;
6189 this._activeGeometry = null;
6190 };
6191 return GeometrySystem;
6192}(System));
6193
6194/**
6195 * Component for masked elements
6196 *
6197 * Holds mask mode and temporary data about current mask
6198 *
6199 * @class
6200 * @memberof PIXI
6201 */
6202var MaskData = /** @class */ (function () {
6203 /**
6204 * Create MaskData
6205 *
6206 * @param {PIXI.DisplayObject} [maskObject=null] - object that describes the mask
6207 */
6208 function MaskData(maskObject) {
6209 if (maskObject === void 0) { maskObject = null; }
6210 /**
6211 * Mask type
6212 * @member {PIXI.MASK_TYPES}
6213 */
6214 this.type = MASK_TYPES.NONE;
6215 /**
6216 * Whether we know the mask type beforehand
6217 * @member {boolean}
6218 * @default true
6219 */
6220 this.autoDetect = true;
6221 /**
6222 * Which element we use to mask
6223 * @member {PIXI.DisplayObject}
6224 */
6225 this.maskObject = maskObject || null;
6226 /**
6227 * Whether it belongs to MaskSystem pool
6228 * @member {boolean}
6229 */
6230 this.pooled = false;
6231 /**
6232 * Indicator of the type
6233 * @member {boolean}
6234 */
6235 this.isMaskData = true;
6236 /**
6237 * Stencil counter above the mask in stack
6238 * @member {number}
6239 * @private
6240 */
6241 this._stencilCounter = 0;
6242 /**
6243 * Scissor counter above the mask in stack
6244 * @member {number}
6245 * @private
6246 */
6247 this._scissorCounter = 0;
6248 /**
6249 * Scissor operation above the mask in stack.
6250 * Null if _scissorCounter is zero, rectangle instance if positive.
6251 * @member {PIXI.Rectangle}
6252 */
6253 this._scissorRect = null;
6254 /**
6255 * Targeted element. Temporary variable set by MaskSystem
6256 * @member {PIXI.DisplayObject}
6257 * @private
6258 */
6259 this._target = null;
6260 }
6261 /**
6262 * resets the mask data after popMask()
6263 */
6264 MaskData.prototype.reset = function () {
6265 if (this.pooled) {
6266 this.maskObject = null;
6267 this.type = MASK_TYPES.NONE;
6268 this.autoDetect = true;
6269 }
6270 this._target = null;
6271 };
6272 /**
6273 * copies counters from maskData above, called from pushMask()
6274 * @param {PIXI.MaskData|null} maskAbove
6275 */
6276 MaskData.prototype.copyCountersOrReset = function (maskAbove) {
6277 if (maskAbove) {
6278 this._stencilCounter = maskAbove._stencilCounter;
6279 this._scissorCounter = maskAbove._scissorCounter;
6280 this._scissorRect = maskAbove._scissorRect;
6281 }
6282 else {
6283 this._stencilCounter = 0;
6284 this._scissorCounter = 0;
6285 this._scissorRect = null;
6286 }
6287 };
6288 return MaskData;
6289}());
6290
6291/**
6292 * @private
6293 * @param {WebGLRenderingContext} gl - The current WebGL context {WebGLProgram}
6294 * @param {Number} type - the type, can be either VERTEX_SHADER or FRAGMENT_SHADER
6295 * @param {string} src - The vertex shader source as an array of strings.
6296 * @return {WebGLShader} the shader
6297 */
6298function compileShader(gl, type, src) {
6299 var shader = gl.createShader(type);
6300 gl.shaderSource(shader, src);
6301 gl.compileShader(shader);
6302 return shader;
6303}
6304/**
6305 * @function compileProgram
6306 * @private
6307 * @memberof PIXI.glCore.shader
6308 * @param {WebGLRenderingContext} gl - The current WebGL context {WebGLProgram}
6309 * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings.
6310 * @param {string|string[]} fragmentSrc - fragment shader source as an array of strings.
6311 * @param {Object} attributeLocations - An attribute location map that lets you manually set the attribute locations
6312 * @return {WebGLProgram} the shader program
6313 */
6314function compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations) {
6315 var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc);
6316 var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
6317 var program = gl.createProgram();
6318 gl.attachShader(program, glVertShader);
6319 gl.attachShader(program, glFragShader);
6320 // optionally, set the attributes manually for the program rather than letting WebGL decide..
6321 if (attributeLocations) {
6322 for (var i in attributeLocations) {
6323 gl.bindAttribLocation(program, attributeLocations[i], i);
6324 }
6325 }
6326 gl.linkProgram(program);
6327 // if linking fails, then log and cleanup
6328 if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
6329 if (!gl.getShaderParameter(glVertShader, gl.COMPILE_STATUS)) {
6330 console.warn(vertexSrc);
6331 console.error(gl.getShaderInfoLog(glVertShader));
6332 }
6333 if (!gl.getShaderParameter(glFragShader, gl.COMPILE_STATUS)) {
6334 console.warn(fragmentSrc);
6335 console.error(gl.getShaderInfoLog(glFragShader));
6336 }
6337 console.error('Pixi.js Error: Could not initialize shader.');
6338 console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));
6339 console.error('gl.getError()', gl.getError());
6340 // if there is a program info log, log it
6341 if (gl.getProgramInfoLog(program) !== '') {
6342 console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));
6343 }
6344 gl.deleteProgram(program);
6345 program = null;
6346 }
6347 // clean up some shaders
6348 gl.deleteShader(glVertShader);
6349 gl.deleteShader(glFragShader);
6350 return program;
6351}
6352
6353function booleanArray(size) {
6354 var array = new Array(size);
6355 for (var i = 0; i < array.length; i++) {
6356 array[i] = false;
6357 }
6358 return array;
6359}
6360/**
6361 * @method defaultValue
6362 * @memberof PIXI.glCore.shader
6363 * @param {string} type - Type of value
6364 * @param {number} size
6365 * @private
6366 */
6367function defaultValue(type, size) {
6368 switch (type) {
6369 case 'float':
6370 return 0;
6371 case 'vec2':
6372 return new Float32Array(2 * size);
6373 case 'vec3':
6374 return new Float32Array(3 * size);
6375 case 'vec4':
6376 return new Float32Array(4 * size);
6377 case 'int':
6378 case 'uint':
6379 case 'sampler2D':
6380 case 'sampler2DArray':
6381 return 0;
6382 case 'ivec2':
6383 return new Int32Array(2 * size);
6384 case 'ivec3':
6385 return new Int32Array(3 * size);
6386 case 'ivec4':
6387 return new Int32Array(4 * size);
6388 case 'uvec2':
6389 return new Uint32Array(2 * size);
6390 case 'uvec3':
6391 return new Uint32Array(3 * size);
6392 case 'uvec4':
6393 return new Uint32Array(4 * size);
6394 case 'bool':
6395 return false;
6396 case 'bvec2':
6397 return booleanArray(2 * size);
6398 case 'bvec3':
6399 return booleanArray(3 * size);
6400 case 'bvec4':
6401 return booleanArray(4 * size);
6402 case 'mat2':
6403 return new Float32Array([1, 0,
6404 0, 1]);
6405 case 'mat3':
6406 return new Float32Array([1, 0, 0,
6407 0, 1, 0,
6408 0, 0, 1]);
6409 case 'mat4':
6410 return new Float32Array([1, 0, 0, 0,
6411 0, 1, 0, 0,
6412 0, 0, 1, 0,
6413 0, 0, 0, 1]);
6414 }
6415 return null;
6416}
6417
6418var unknownContext = {};
6419var context = unknownContext;
6420/**
6421 * returns a little WebGL context to use for program inspection.
6422 *
6423 * @static
6424 * @private
6425 * @returns {WebGLRenderingContext} a gl context to test with
6426 */
6427function getTestContext() {
6428 if (context === unknownContext || (context && context.isContextLost())) {
6429 var canvas = document.createElement('canvas');
6430 var gl = void 0;
6431 if (settings.PREFER_ENV >= ENV.WEBGL2) {
6432 gl = canvas.getContext('webgl2', {});
6433 }
6434 if (!gl) {
6435 gl = canvas.getContext('webgl', {})
6436 || canvas.getContext('experimental-webgl', {});
6437 if (!gl) {
6438 // fail, not able to get a context
6439 gl = null;
6440 }
6441 else {
6442 // for shader testing..
6443 gl.getExtension('WEBGL_draw_buffers');
6444 }
6445 }
6446 context = gl;
6447 }
6448 return context;
6449}
6450
6451var maxFragmentPrecision;
6452function getMaxFragmentPrecision() {
6453 if (!maxFragmentPrecision) {
6454 maxFragmentPrecision = PRECISION.MEDIUM;
6455 var gl = getTestContext();
6456 if (gl) {
6457 if (gl.getShaderPrecisionFormat) {
6458 var shaderFragment = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
6459 maxFragmentPrecision = shaderFragment.precision ? PRECISION.HIGH : PRECISION.MEDIUM;
6460 }
6461 }
6462 }
6463 return maxFragmentPrecision;
6464}
6465
6466/**
6467 * Sets the float precision on the shader, ensuring the device supports the request precision.
6468 * If the precision is already present, it just ensures that the device is able to handle it.
6469 *
6470 * @private
6471 * @param {string} src - The shader source
6472 * @param {string} requestedPrecision - The request float precision of the shader. Options are 'lowp', 'mediump' or 'highp'.
6473 * @param {string} maxSupportedPrecision - The maximum precision the shader supports.
6474 *
6475 * @return {string} modified shader source
6476 */
6477function setPrecision(src, requestedPrecision, maxSupportedPrecision) {
6478 if (src.substring(0, 9) !== 'precision') {
6479 // no precision supplied, so PixiJS will add the requested level.
6480 var precision = requestedPrecision;
6481 // If highp is requested but not supported, downgrade precision to a level all devices support.
6482 if (requestedPrecision === PRECISION.HIGH && maxSupportedPrecision !== PRECISION.HIGH) {
6483 precision = PRECISION.MEDIUM;
6484 }
6485 return "precision " + precision + " float;\n" + src;
6486 }
6487 else if (maxSupportedPrecision !== PRECISION.HIGH && src.substring(0, 15) === 'precision highp') {
6488 // precision was supplied, but at a level this device does not support, so downgrading to mediump.
6489 return src.replace('precision highp', 'precision mediump');
6490 }
6491 return src;
6492}
6493
6494var GLSL_TO_SIZE = {
6495 float: 1,
6496 vec2: 2,
6497 vec3: 3,
6498 vec4: 4,
6499 int: 1,
6500 ivec2: 2,
6501 ivec3: 3,
6502 ivec4: 4,
6503 uint: 1,
6504 uvec2: 2,
6505 uvec3: 3,
6506 uvec4: 4,
6507 bool: 1,
6508 bvec2: 2,
6509 bvec3: 3,
6510 bvec4: 4,
6511 mat2: 4,
6512 mat3: 9,
6513 mat4: 16,
6514 sampler2D: 1,
6515};
6516/**
6517 * @private
6518 * @method mapSize
6519 * @memberof PIXI.glCore.shader
6520 * @param {String} type
6521 * @return {Number}
6522 */
6523function mapSize(type) {
6524 return GLSL_TO_SIZE[type];
6525}
6526
6527var GL_TABLE = null;
6528var GL_TO_GLSL_TYPES = {
6529 FLOAT: 'float',
6530 FLOAT_VEC2: 'vec2',
6531 FLOAT_VEC3: 'vec3',
6532 FLOAT_VEC4: 'vec4',
6533 INT: 'int',
6534 INT_VEC2: 'ivec2',
6535 INT_VEC3: 'ivec3',
6536 INT_VEC4: 'ivec4',
6537 UNSIGNED_INT: 'uint',
6538 UNSIGNED_INT_VEC2: 'uvec2',
6539 UNSIGNED_INT_VEC3: 'uvec3',
6540 UNSIGNED_INT_VEC4: 'uvec4',
6541 BOOL: 'bool',
6542 BOOL_VEC2: 'bvec2',
6543 BOOL_VEC3: 'bvec3',
6544 BOOL_VEC4: 'bvec4',
6545 FLOAT_MAT2: 'mat2',
6546 FLOAT_MAT3: 'mat3',
6547 FLOAT_MAT4: 'mat4',
6548 SAMPLER_2D: 'sampler2D',
6549 INT_SAMPLER_2D: 'sampler2D',
6550 UNSIGNED_INT_SAMPLER_2D: 'sampler2D',
6551 SAMPLER_CUBE: 'samplerCube',
6552 INT_SAMPLER_CUBE: 'samplerCube',
6553 UNSIGNED_INT_SAMPLER_CUBE: 'samplerCube',
6554 SAMPLER_2D_ARRAY: 'sampler2DArray',
6555 INT_SAMPLER_2D_ARRAY: 'sampler2DArray',
6556 UNSIGNED_INT_SAMPLER_2D_ARRAY: 'sampler2DArray',
6557};
6558// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
6559function mapType(gl, type) {
6560 if (!GL_TABLE) {
6561 var typeNames = Object.keys(GL_TO_GLSL_TYPES);
6562 GL_TABLE = {};
6563 for (var i = 0; i < typeNames.length; ++i) {
6564 var tn = typeNames[i];
6565 GL_TABLE[gl[tn]] = GL_TO_GLSL_TYPES[tn];
6566 }
6567 }
6568 return GL_TABLE[type];
6569}
6570
6571/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
6572// Parsers, each one of these will take a look at the type of shader property and uniform.
6573// if they pass the test function then the code function is called that returns a the shader upload code for that uniform.
6574// Shader upload code is automagically generated with these parsers.
6575// If no parser is valid then the default upload functions are used.
6576// exposing Parsers means that custom upload logic can be added to pixi's shaders.
6577// A good example would be a pixi rectangle can be directly set on a uniform.
6578// If the shader sees it it knows how to upload the rectangle structure as a vec4
6579// format is as follows:
6580//
6581// {
6582// test: (data, uniform) => {} <--- test is this code should be used for this uniform
6583// code: (name, uniform) => {} <--- returns the string of the piece of code that uploads the uniform
6584// }
6585var uniformParsers = [
6586 // a float cache layer
6587 {
6588 test: function (data) {
6589 return data.type === 'float' && data.size === 1;
6590 },
6591 code: function (name) {
6592 return "\n if(uv[\"" + name + "\"] !== ud[\"" + name + "\"].value)\n {\n ud[\"" + name + "\"].value = uv[\"" + name + "\"]\n gl.uniform1f(ud[\"" + name + "\"].location, uv[\"" + name + "\"])\n }\n ";
6593 },
6594 },
6595 // handling samplers
6596 {
6597 test: function (data) {
6598 // eslint-disable-next-line max-len
6599 return (data.type === 'sampler2D' || data.type === 'samplerCube' || data.type === 'sampler2DArray') && data.size === 1 && !data.isArray;
6600 },
6601 code: function (name) { return "t = syncData.textureCount++;\n\n renderer.texture.bind(uv[\"" + name + "\"], t);\n\n if(ud[\"" + name + "\"].value !== t)\n {\n ud[\"" + name + "\"].value = t;\n gl.uniform1i(ud[\"" + name + "\"].location, t);\n; // eslint-disable-line max-len\n }"; },
6602 },
6603 // uploading pixi matrix object to mat3
6604 {
6605 test: function (data, uniform) {
6606 return data.type === 'mat3' && data.size === 1 && uniform.a !== undefined;
6607 },
6608 code: function (name) {
6609 // TODO and some smart caching dirty ids here!
6610 return "\n gl.uniformMatrix3fv(ud[\"" + name + "\"].location, false, uv[\"" + name + "\"].toArray(true));\n ";
6611 },
6612 },
6613 // uploading a pixi point as a vec2 with caching layer
6614 {
6615 test: function (data, uniform) {
6616 return data.type === 'vec2' && data.size === 1 && uniform.x !== undefined;
6617 },
6618 code: function (name) {
6619 return "\n cv = ud[\"" + name + "\"].value;\n v = uv[\"" + name + "\"];\n\n if(cv[0] !== v.x || cv[1] !== v.y)\n {\n cv[0] = v.x;\n cv[1] = v.y;\n gl.uniform2f(ud[\"" + name + "\"].location, v.x, v.y);\n }";
6620 },
6621 },
6622 // caching layer for a vec2
6623 {
6624 test: function (data) {
6625 return data.type === 'vec2' && data.size === 1;
6626 },
6627 code: function (name) {
6628 return "\n cv = ud[\"" + name + "\"].value;\n v = uv[\"" + name + "\"];\n\n if(cv[0] !== v[0] || cv[1] !== v[1])\n {\n cv[0] = v[0];\n cv[1] = v[1];\n gl.uniform2f(ud[\"" + name + "\"].location, v[0], v[1]);\n }\n ";
6629 },
6630 },
6631 // upload a pixi rectangle as a vec4 with caching layer
6632 {
6633 test: function (data, uniform) {
6634 return data.type === 'vec4' && data.size === 1 && uniform.width !== undefined;
6635 },
6636 code: function (name) {
6637 return "\n cv = ud[\"" + name + "\"].value;\n v = uv[\"" + name + "\"];\n\n if(cv[0] !== v.x || cv[1] !== v.y || cv[2] !== v.width || cv[3] !== v.height)\n {\n cv[0] = v.x;\n cv[1] = v.y;\n cv[2] = v.width;\n cv[3] = v.height;\n gl.uniform4f(ud[\"" + name + "\"].location, v.x, v.y, v.width, v.height)\n }";
6638 },
6639 },
6640 // a caching layer for vec4 uploading
6641 {
6642 test: function (data) {
6643 return data.type === 'vec4' && data.size === 1;
6644 },
6645 code: function (name) {
6646 return "\n cv = ud[\"" + name + "\"].value;\n v = uv[\"" + name + "\"];\n\n if(cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3])\n {\n cv[0] = v[0];\n cv[1] = v[1];\n cv[2] = v[2];\n cv[3] = v[3];\n\n gl.uniform4f(ud[\"" + name + "\"].location, v[0], v[1], v[2], v[3])\n }";
6647 },
6648 } ];
6649
6650// cv = CachedValue
6651// v = value
6652// ud = uniformData
6653// uv = uniformValue
6654// l = location
6655var GLSL_TO_SINGLE_SETTERS_CACHED = {
6656 float: "\n if(cv !== v)\n {\n cv.v = v;\n gl.uniform1f(location, v)\n }",
6657 vec2: "\n if(cv[0] !== v[0] || cv[1] !== v[1])\n {\n cv[0] = v[0];\n cv[1] = v[1];\n gl.uniform2f(location, v[0], v[1])\n }",
6658 vec3: "\n if(cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2])\n {\n cv[0] = v[0];\n cv[1] = v[1];\n cv[2] = v[2];\n\n gl.uniform3f(location, v[0], v[1], v[2])\n }",
6659 vec4: 'gl.uniform4f(location, v[0], v[1], v[2], v[3])',
6660 int: 'gl.uniform1i(location, v)',
6661 ivec2: 'gl.uniform2i(location, v[0], v[1])',
6662 ivec3: 'gl.uniform3i(location, v[0], v[1], v[2])',
6663 ivec4: 'gl.uniform4i(location, v[0], v[1], v[2], v[3])',
6664 uint: 'gl.uniform1ui(location, v)',
6665 uvec2: 'gl.uniform2ui(location, v[0], v[1])',
6666 uvec3: 'gl.uniform3ui(location, v[0], v[1], v[2])',
6667 uvec4: 'gl.uniform4ui(location, v[0], v[1], v[2], v[3])',
6668 bool: 'gl.uniform1i(location, v)',
6669 bvec2: 'gl.uniform2i(location, v[0], v[1])',
6670 bvec3: 'gl.uniform3i(location, v[0], v[1], v[2])',
6671 bvec4: 'gl.uniform4i(location, v[0], v[1], v[2], v[3])',
6672 mat2: 'gl.uniformMatrix2fv(location, false, v)',
6673 mat3: 'gl.uniformMatrix3fv(location, false, v)',
6674 mat4: 'gl.uniformMatrix4fv(location, false, v)',
6675 sampler2D: 'gl.uniform1i(location, v)',
6676 samplerCube: 'gl.uniform1i(location, v)',
6677 sampler2DArray: 'gl.uniform1i(location, v)',
6678};
6679var GLSL_TO_ARRAY_SETTERS = {
6680 float: "gl.uniform1fv(location, v)",
6681 vec2: "gl.uniform2fv(location, v)",
6682 vec3: "gl.uniform3fv(location, v)",
6683 vec4: 'gl.uniform4fv(location, v)',
6684 mat4: 'gl.uniformMatrix4fv(location, false, v)',
6685 mat3: 'gl.uniformMatrix3fv(location, false, v)',
6686 mat2: 'gl.uniformMatrix2fv(location, false, v)',
6687 int: 'gl.uniform1iv(location, v)',
6688 ivec2: 'gl.uniform2iv(location, v)',
6689 ivec3: 'gl.uniform3iv(location, v)',
6690 ivec4: 'gl.uniform4iv(location, v)',
6691 uint: 'gl.uniform1uiv(location, v)',
6692 uvec2: 'gl.uniform2uiv(location, v)',
6693 uvec3: 'gl.uniform3uiv(location, v)',
6694 uvec4: 'gl.uniform4uiv(location, v)',
6695 bool: 'gl.uniform1iv(location, v)',
6696 bvec2: 'gl.uniform2iv(location, v)',
6697 bvec3: 'gl.uniform3iv(location, v)',
6698 bvec4: 'gl.uniform4iv(location, v)',
6699 sampler2D: 'gl.uniform1iv(location, v)',
6700 samplerCube: 'gl.uniform1iv(location, v)',
6701 sampler2DArray: 'gl.uniform1iv(location, v)',
6702};
6703function generateUniformsSync(group, uniformData) {
6704 var funcFragments = ["\n var v = null;\n var cv = null\n var t = 0;\n var gl = renderer.gl\n "];
6705 for (var i in group.uniforms) {
6706 var data = uniformData[i];
6707 if (!data) {
6708 if (group.uniforms[i].group) {
6709 funcFragments.push("\n renderer.shader.syncUniformGroup(uv[\"" + i + "\"], syncData);\n ");
6710 }
6711 continue;
6712 }
6713 var uniform = group.uniforms[i];
6714 var parsed = false;
6715 for (var j = 0; j < uniformParsers.length; j++) {
6716 if (uniformParsers[j].test(data, uniform)) {
6717 funcFragments.push(uniformParsers[j].code(i, uniform));
6718 parsed = true;
6719 break;
6720 }
6721 }
6722 if (!parsed) {
6723 var templateType = (data.size === 1) ? GLSL_TO_SINGLE_SETTERS_CACHED : GLSL_TO_ARRAY_SETTERS;
6724 var template = templateType[data.type].replace('location', "ud[\"" + i + "\"].location");
6725 funcFragments.push("\n cv = ud[\"" + i + "\"].value;\n v = uv[\"" + i + "\"];\n " + template + ";");
6726 }
6727 }
6728 /*
6729 * the introduction of syncData is to solve an issue where textures in uniform groups are not set correctly
6730 * the texture count was always starting from 0 in each group. This needs to increment each time a texture is used
6731 * no matter which group is being used
6732 *
6733 */
6734 // eslint-disable-next-line no-new-func
6735 return new Function('ud', 'uv', 'renderer', 'syncData', funcFragments.join('\n'));
6736}
6737
6738var fragTemplate = [
6739 'precision mediump float;',
6740 'void main(void){',
6741 'float test = 0.1;',
6742 '%forloop%',
6743 'gl_FragColor = vec4(0.0);',
6744 '}' ].join('\n');
6745function generateIfTestSrc(maxIfs) {
6746 var src = '';
6747 for (var i = 0; i < maxIfs; ++i) {
6748 if (i > 0) {
6749 src += '\nelse ';
6750 }
6751 if (i < maxIfs - 1) {
6752 src += "if(test == " + i + ".0){}";
6753 }
6754 }
6755 return src;
6756}
6757function checkMaxIfStatementsInShader(maxIfs, gl) {
6758 if (maxIfs === 0) {
6759 throw new Error('Invalid value of `0` passed to `checkMaxIfStatementsInShader`');
6760 }
6761 var shader = gl.createShader(gl.FRAGMENT_SHADER);
6762 while (true) // eslint-disable-line no-constant-condition
6763 {
6764 var fragmentSrc = fragTemplate.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));
6765 gl.shaderSource(shader, fragmentSrc);
6766 gl.compileShader(shader);
6767 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
6768 maxIfs = (maxIfs / 2) | 0;
6769 }
6770 else {
6771 // valid!
6772 break;
6773 }
6774 }
6775 return maxIfs;
6776}
6777
6778// Cache the result to prevent running this over and over
6779var unsafeEval;
6780/**
6781 * Not all platforms allow to generate function code (e.g., `new Function`).
6782 * this provides the platform-level detection.
6783 *
6784 * @private
6785 * @returns {boolean}
6786 */
6787function unsafeEvalSupported() {
6788 if (typeof unsafeEval === 'boolean') {
6789 return unsafeEval;
6790 }
6791 try {
6792 /* eslint-disable no-new-func */
6793 var func = new Function('param1', 'param2', 'param3', 'return param1[param2] === param3;');
6794 /* eslint-enable no-new-func */
6795 unsafeEval = func({ a: 'b' }, 'a', 'b') === true;
6796 }
6797 catch (e) {
6798 unsafeEval = false;
6799 }
6800 return unsafeEval;
6801}
6802
6803var defaultFragment = "varying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nvoid main(void){\n gl_FragColor *= texture2D(uSampler, vTextureCoord);\n}";
6804
6805var defaultVertex = "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n";
6806
6807var UID$3 = 0;
6808var nameCache = {};
6809/**
6810 * Helper class to create a shader program.
6811 *
6812 * @class
6813 * @memberof PIXI
6814 */
6815var Program = /** @class */ (function () {
6816 /**
6817 * @param {string} [vertexSrc] - The source of the vertex shader.
6818 * @param {string} [fragmentSrc] - The source of the fragment shader.
6819 * @param {string} [name] - Name for shader
6820 */
6821 function Program(vertexSrc, fragmentSrc, name) {
6822 if (name === void 0) { name = 'pixi-shader'; }
6823 this.id = UID$3++;
6824 /**
6825 * The vertex shader.
6826 *
6827 * @member {string}
6828 */
6829 this.vertexSrc = vertexSrc || Program.defaultVertexSrc;
6830 /**
6831 * The fragment shader.
6832 *
6833 * @member {string}
6834 */
6835 this.fragmentSrc = fragmentSrc || Program.defaultFragmentSrc;
6836 this.vertexSrc = this.vertexSrc.trim();
6837 this.fragmentSrc = this.fragmentSrc.trim();
6838 if (this.vertexSrc.substring(0, 8) !== '#version') {
6839 name = name.replace(/\s+/g, '-');
6840 if (nameCache[name]) {
6841 nameCache[name]++;
6842 name += "-" + nameCache[name];
6843 }
6844 else {
6845 nameCache[name] = 1;
6846 }
6847 this.vertexSrc = "#define SHADER_NAME " + name + "\n" + this.vertexSrc;
6848 this.fragmentSrc = "#define SHADER_NAME " + name + "\n" + this.fragmentSrc;
6849 this.vertexSrc = setPrecision(this.vertexSrc, settings.PRECISION_VERTEX, PRECISION.HIGH);
6850 this.fragmentSrc = setPrecision(this.fragmentSrc, settings.PRECISION_FRAGMENT, getMaxFragmentPrecision());
6851 }
6852 // currently this does not extract structs only default types
6853 this.extractData(this.vertexSrc, this.fragmentSrc);
6854 // this is where we store shader references..
6855 this.glPrograms = {};
6856 this.syncUniforms = null;
6857 }
6858 /**
6859 * Extracts the data for a buy creating a small test program
6860 * or reading the src directly.
6861 * @protected
6862 *
6863 * @param {string} [vertexSrc] - The source of the vertex shader.
6864 * @param {string} [fragmentSrc] - The source of the fragment shader.
6865 */
6866 Program.prototype.extractData = function (vertexSrc, fragmentSrc) {
6867 var gl = getTestContext();
6868 if (gl) {
6869 var program = compileProgram(gl, vertexSrc, fragmentSrc);
6870 this.attributeData = this.getAttributeData(program, gl);
6871 this.uniformData = this.getUniformData(program, gl);
6872 gl.deleteProgram(program);
6873 }
6874 else {
6875 this.uniformData = {};
6876 this.attributeData = {};
6877 }
6878 };
6879 /**
6880 * returns the attribute data from the program
6881 * @private
6882 *
6883 * @param {WebGLProgram} [program] - the WebGL program
6884 * @param {WebGLRenderingContext} [gl] - the WebGL context
6885 *
6886 * @returns {object} the attribute data for this program
6887 */
6888 Program.prototype.getAttributeData = function (program, gl) {
6889 var attributes = {};
6890 var attributesArray = [];
6891 var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
6892 for (var i = 0; i < totalAttributes; i++) {
6893 var attribData = gl.getActiveAttrib(program, i);
6894 var type = mapType(gl, attribData.type);
6895 /*eslint-disable */
6896 var data = {
6897 type: type,
6898 name: attribData.name,
6899 size: mapSize(type),
6900 location: 0,
6901 };
6902 /* eslint-enable */
6903 attributes[attribData.name] = data;
6904 attributesArray.push(data);
6905 }
6906 attributesArray.sort(function (a, b) { return (a.name > b.name) ? 1 : -1; }); // eslint-disable-line no-confusing-arrow
6907 for (var i = 0; i < attributesArray.length; i++) {
6908 attributesArray[i].location = i;
6909 }
6910 return attributes;
6911 };
6912 /**
6913 * returns the uniform data from the program
6914 * @private
6915 *
6916 * @param {webGL-program} [program] - the webgl program
6917 * @param {context} [gl] - the WebGL context
6918 *
6919 * @returns {object} the uniform data for this program
6920 */
6921 Program.prototype.getUniformData = function (program, gl) {
6922 var uniforms = {};
6923 var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
6924 // TODO expose this as a prop?
6925 // const maskRegex = new RegExp('^(projectionMatrix|uSampler|translationMatrix)$');
6926 // const maskRegex = new RegExp('^(projectionMatrix|uSampler|translationMatrix)$');
6927 for (var i = 0; i < totalUniforms; i++) {
6928 var uniformData = gl.getActiveUniform(program, i);
6929 var name = uniformData.name.replace(/\[.*?\]$/, '');
6930 var isArray = uniformData.name.match(/\[.*?\]$/);
6931 var type = mapType(gl, uniformData.type);
6932 /*eslint-disable */
6933 uniforms[name] = {
6934 type: type,
6935 size: uniformData.size,
6936 isArray: isArray,
6937 value: defaultValue(type, uniformData.size),
6938 };
6939 /* eslint-enable */
6940 }
6941 return uniforms;
6942 };
6943 Object.defineProperty(Program, "defaultVertexSrc", {
6944 /**
6945 * The default vertex shader source
6946 *
6947 * @static
6948 * @constant
6949 * @member {string}
6950 */
6951 get: function () {
6952 return defaultVertex;
6953 },
6954 enumerable: false,
6955 configurable: true
6956 });
6957 Object.defineProperty(Program, "defaultFragmentSrc", {
6958 /**
6959 * The default fragment shader source
6960 *
6961 * @static
6962 * @constant
6963 * @member {string}
6964 */
6965 get: function () {
6966 return defaultFragment;
6967 },
6968 enumerable: false,
6969 configurable: true
6970 });
6971 /**
6972 * A short hand function to create a program based of a vertex and fragment shader
6973 * this method will also check to see if there is a cached program.
6974 *
6975 * @param {string} [vertexSrc] - The source of the vertex shader.
6976 * @param {string} [fragmentSrc] - The source of the fragment shader.
6977 * @param {string} [name=pixi-shader] - Name for shader
6978 *
6979 * @returns {PIXI.Program} an shiny new Pixi shader!
6980 */
6981 Program.from = function (vertexSrc, fragmentSrc, name) {
6982 var key = vertexSrc + fragmentSrc;
6983 var program = ProgramCache[key];
6984 if (!program) {
6985 ProgramCache[key] = program = new Program(vertexSrc, fragmentSrc, name);
6986 }
6987 return program;
6988 };
6989 return Program;
6990}());
6991
6992/**
6993 * A helper class for shaders
6994 *
6995 * @class
6996 * @memberof PIXI
6997 */
6998var Shader = /** @class */ (function () {
6999 /**
7000 * @param {PIXI.Program} [program] - The program the shader will use.
7001 * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones.
7002 */
7003 function Shader(program, uniforms) {
7004 /**
7005 * Program that the shader uses
7006 *
7007 * @member {PIXI.Program}
7008 */
7009 this.program = program;
7010 // lets see whats been passed in
7011 // uniforms should be converted to a uniform group
7012 if (uniforms) {
7013 if (uniforms instanceof UniformGroup) {
7014 this.uniformGroup = uniforms;
7015 }
7016 else {
7017 this.uniformGroup = new UniformGroup(uniforms);
7018 }
7019 }
7020 else {
7021 this.uniformGroup = new UniformGroup({});
7022 }
7023 // time to build some getters and setters!
7024 // I guess down the line this could sort of generate an instruction list rather than use dirty ids?
7025 // does the trick for now though!
7026 for (var i in program.uniformData) {
7027 if (this.uniformGroup.uniforms[i] instanceof Array) {
7028 this.uniformGroup.uniforms[i] = new Float32Array(this.uniformGroup.uniforms[i]);
7029 }
7030 }
7031 }
7032 // TODO move to shader system..
7033 Shader.prototype.checkUniformExists = function (name, group) {
7034 if (group.uniforms[name]) {
7035 return true;
7036 }
7037 for (var i in group.uniforms) {
7038 var uniform = group.uniforms[i];
7039 if (uniform.group) {
7040 if (this.checkUniformExists(name, uniform)) {
7041 return true;
7042 }
7043 }
7044 }
7045 return false;
7046 };
7047 Shader.prototype.destroy = function () {
7048 // usage count on programs?
7049 // remove if not used!
7050 this.uniformGroup = null;
7051 };
7052 Object.defineProperty(Shader.prototype, "uniforms", {
7053 /**
7054 * Shader uniform values, shortcut for `uniformGroup.uniforms`
7055 * @readonly
7056 * @member {object}
7057 */
7058 get: function () {
7059 return this.uniformGroup.uniforms;
7060 },
7061 enumerable: false,
7062 configurable: true
7063 });
7064 /**
7065 * A short hand function to create a shader based of a vertex and fragment shader
7066 *
7067 * @param {string} [vertexSrc] - The source of the vertex shader.
7068 * @param {string} [fragmentSrc] - The source of the fragment shader.
7069 * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones.
7070 *
7071 * @returns {PIXI.Shader} an shiny new Pixi shader!
7072 */
7073 Shader.from = function (vertexSrc, fragmentSrc, uniforms) {
7074 var program = Program.from(vertexSrc, fragmentSrc);
7075 return new Shader(program, uniforms);
7076 };
7077 return Shader;
7078}());
7079
7080/* eslint-disable max-len */
7081var BLEND = 0;
7082var OFFSET = 1;
7083var CULLING = 2;
7084var DEPTH_TEST = 3;
7085var WINDING = 4;
7086var DEPTH_MASK = 5;
7087/**
7088 * This is a WebGL state, and is is passed The WebGL StateManager.
7089 *
7090 * Each mesh rendered may require WebGL to be in a different state.
7091 * For example you may want different blend mode or to enable polygon offsets
7092 *
7093 * @class
7094 * @memberof PIXI
7095 */
7096var State = /** @class */ (function () {
7097 function State() {
7098 this.data = 0;
7099 this.blendMode = BLEND_MODES.NORMAL;
7100 this.polygonOffset = 0;
7101 this.blend = true;
7102 this.depthMask = true;
7103 // this.depthTest = true;
7104 }
7105 Object.defineProperty(State.prototype, "blend", {
7106 /**
7107 * Activates blending of the computed fragment color values
7108 *
7109 * @member {boolean}
7110 */
7111 get: function () {
7112 return !!(this.data & (1 << BLEND));
7113 },
7114 set: function (value) {
7115 if (!!(this.data & (1 << BLEND)) !== value) {
7116 this.data ^= (1 << BLEND);
7117 }
7118 },
7119 enumerable: false,
7120 configurable: true
7121 });
7122 Object.defineProperty(State.prototype, "offsets", {
7123 /**
7124 * Activates adding an offset to depth values of polygon's fragments
7125 *
7126 * @member {boolean}
7127 * @default false
7128 */
7129 get: function () {
7130 return !!(this.data & (1 << OFFSET));
7131 },
7132 set: function (value) {
7133 if (!!(this.data & (1 << OFFSET)) !== value) {
7134 this.data ^= (1 << OFFSET);
7135 }
7136 },
7137 enumerable: false,
7138 configurable: true
7139 });
7140 Object.defineProperty(State.prototype, "culling", {
7141 /**
7142 * Activates culling of polygons.
7143 *
7144 * @member {boolean}
7145 * @default false
7146 */
7147 get: function () {
7148 return !!(this.data & (1 << CULLING));
7149 },
7150 set: function (value) {
7151 if (!!(this.data & (1 << CULLING)) !== value) {
7152 this.data ^= (1 << CULLING);
7153 }
7154 },
7155 enumerable: false,
7156 configurable: true
7157 });
7158 Object.defineProperty(State.prototype, "depthTest", {
7159 /**
7160 * Activates depth comparisons and updates to the depth buffer.
7161 *
7162 * @member {boolean}
7163 * @default false
7164 */
7165 get: function () {
7166 return !!(this.data & (1 << DEPTH_TEST));
7167 },
7168 set: function (value) {
7169 if (!!(this.data & (1 << DEPTH_TEST)) !== value) {
7170 this.data ^= (1 << DEPTH_TEST);
7171 }
7172 },
7173 enumerable: false,
7174 configurable: true
7175 });
7176 Object.defineProperty(State.prototype, "depthMask", {
7177 /**
7178 * Enables or disables writing to the depth buffer.
7179 *
7180 * @member {boolean}
7181 * @default true
7182 */
7183 get: function () {
7184 return !!(this.data & (1 << DEPTH_MASK));
7185 },
7186 set: function (value) {
7187 if (!!(this.data & (1 << DEPTH_MASK)) !== value) {
7188 this.data ^= (1 << DEPTH_MASK);
7189 }
7190 },
7191 enumerable: false,
7192 configurable: true
7193 });
7194 Object.defineProperty(State.prototype, "clockwiseFrontFace", {
7195 /**
7196 * Specifies whether or not front or back-facing polygons can be culled.
7197 * @member {boolean}
7198 * @default false
7199 */
7200 get: function () {
7201 return !!(this.data & (1 << WINDING));
7202 },
7203 set: function (value) {
7204 if (!!(this.data & (1 << WINDING)) !== value) {
7205 this.data ^= (1 << WINDING);
7206 }
7207 },
7208 enumerable: false,
7209 configurable: true
7210 });
7211 Object.defineProperty(State.prototype, "blendMode", {
7212 /**
7213 * The blend mode to be applied when this state is set. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode.
7214 * Setting this mode to anything other than NO_BLEND will automatically switch blending on.
7215 *
7216 * @member {number}
7217 * @default PIXI.BLEND_MODES.NORMAL
7218 * @see PIXI.BLEND_MODES
7219 */
7220 get: function () {
7221 return this._blendMode;
7222 },
7223 set: function (value) {
7224 this.blend = (value !== BLEND_MODES.NONE);
7225 this._blendMode = value;
7226 },
7227 enumerable: false,
7228 configurable: true
7229 });
7230 Object.defineProperty(State.prototype, "polygonOffset", {
7231 /**
7232 * The polygon offset. Setting this property to anything other than 0 will automatically enable polygon offset fill.
7233 *
7234 * @member {number}
7235 * @default 0
7236 */
7237 get: function () {
7238 return this._polygonOffset;
7239 },
7240 set: function (value) {
7241 this.offsets = !!value;
7242 this._polygonOffset = value;
7243 },
7244 enumerable: false,
7245 configurable: true
7246 });
7247 State.prototype.toString = function () {
7248 return "[@pixi/core:State "
7249 + ("blendMode=" + this.blendMode + " ")
7250 + ("clockwiseFrontFace=" + this.clockwiseFrontFace + " ")
7251 + ("culling=" + this.culling + " ")
7252 + ("depthMask=" + this.depthMask + " ")
7253 + ("polygonOffset=" + this.polygonOffset)
7254 + "]";
7255 };
7256 State.for2d = function () {
7257 var state = new State();
7258 state.depthTest = false;
7259 state.blend = true;
7260 return state;
7261 };
7262 return State;
7263}());
7264
7265var defaultVertex$1 = "attribute vec2 aVertexPosition;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nuniform vec4 inputSize;\nuniform vec4 outputFrame;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;\n\n return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aVertexPosition * (outputFrame.zw * inputSize.zw);\n}\n\nvoid main(void)\n{\n gl_Position = filterVertexPosition();\n vTextureCoord = filterTextureCoord();\n}\n";
7266
7267var defaultFragment$1 = "varying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nvoid main(void){\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n}\n";
7268
7269/**
7270 * A filter is a special shader that applies post-processing effects to an input texture and writes into an output
7271 * render-target.
7272 *
7273 * {@link http://pixijs.io/examples/#/filters/blur-filter.js Example} of the
7274 * {@link PIXI.filters.BlurFilter BlurFilter}.
7275 *
7276 * ### Usage
7277 * Filters can be applied to any DisplayObject or Container.
7278 * PixiJS' `FilterSystem` renders the container into temporary Framebuffer,
7279 * then filter renders it to the screen.
7280 * Multiple filters can be added to the `filters` array property and stacked on each other.
7281 *
7282 * ```
7283 * const filter = new PIXI.Filter(myShaderVert, myShaderFrag, { myUniform: 0.5 });
7284 * const container = new PIXI.Container();
7285 * container.filters = [filter];
7286 * ```
7287 *
7288 * ### Previous Version Differences
7289 *
7290 * In PixiJS **v3**, a filter was always applied to _whole screen_.
7291 *
7292 * In PixiJS **v4**, a filter can be applied _only part of the screen_.
7293 * Developers had to create a set of uniforms to deal with coordinates.
7294 *
7295 * In PixiJS **v5** combines _both approaches_.
7296 * Developers can use normal coordinates of v3 and then allow filter to use partial Framebuffers,
7297 * bringing those extra uniforms into account.
7298 *
7299 * Also be aware that we have changed default vertex shader, please consult
7300 * {@link https://github.com/pixijs/pixi.js/wiki/v5-Creating-filters Wiki}.
7301 *
7302 * ### Frames
7303 *
7304 * The following table summarizes the coordinate spaces used in the filtering pipeline:
7305 *
7306 * <table>
7307 * <thead>
7308 * <tr>
7309 * <th>Coordinate Space</th>
7310 * <th>Description</th>
7311 * </tr>
7312 * </thead>
7313 * <tbody>
7314 * <tr>
7315 * <td>Texture Coordinates</td>
7316 * <td>
7317 * The texture (or UV) coordinates in the input base-texture's space. These are normalized into the (0,1) range along
7318 * both axes.
7319 * </td>
7320 * </tr>
7321 * <tr>
7322 * <td>World Space</td>
7323 * <td>
7324 * A point in the same space as the world bounds of any display-object (i.e. in the scene graph's space).
7325 * </td>
7326 * </tr>
7327 * <tr>
7328 * <td>Physical Pixels</td>
7329 * <td>
7330 * This is base-texture's space with the origin on the top-left. You can calculate these by multiplying the texture
7331 * coordinates by the dimensions of the texture.
7332 * </td>
7333 * </tr>
7334 * </tbody>
7335 * </table>
7336 *
7337 * ### Built-in Uniforms
7338 *
7339 * PixiJS viewport uses screen (CSS) coordinates, `(0, 0, renderer.screen.width, renderer.screen.height)`,
7340 * and `projectionMatrix` uniform maps it to the gl viewport.
7341 *
7342 * **uSampler**
7343 *
7344 * The most important uniform is the input texture that container was rendered into.
7345 * _Important note: as with all Framebuffers in PixiJS, both input and output are
7346 * premultiplied by alpha._
7347 *
7348 * By default, input normalized coordinates are passed to fragment shader with `vTextureCoord`.
7349 * Use it to sample the input.
7350 *
7351 * ```
7352 * const fragment = `
7353 * varying vec2 vTextureCoord;
7354 * uniform sampler2D uSampler;
7355 * void main(void)
7356 * {
7357 * gl_FragColor = texture2D(uSampler, vTextureCoord);
7358 * }
7359 * `;
7360 *
7361 * const myFilter = new PIXI.Filter(null, fragment);
7362 * ```
7363 *
7364 * This filter is just one uniform less than {@link PIXI.filters.AlphaFilter AlphaFilter}.
7365 *
7366 * **outputFrame**
7367 *
7368 * The `outputFrame` holds the rectangle where filter is applied in screen (CSS) coordinates.
7369 * It's the same as `renderer.screen` for a fullscreen filter.
7370 * Only a part of `outputFrame.zw` size of temporary Framebuffer is used,
7371 * `(0, 0, outputFrame.width, outputFrame.height)`,
7372 *
7373 * Filters uses this quad to normalized (0-1) space, its passed into `aVertexPosition` attribute.
7374 * To calculate vertex position in screen space using normalized (0-1) space:
7375 *
7376 * ```
7377 * vec4 filterVertexPosition( void )
7378 * {
7379 * vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;
7380 * return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
7381 * }
7382 * ```
7383 *
7384 * **inputSize**
7385 *
7386 * Temporary framebuffer is different, it can be either the size of screen, either power-of-two.
7387 * The `inputSize.xy` are size of temporary framebuffer that holds input.
7388 * The `inputSize.zw` is inverted, it's a shortcut to evade division inside the shader.
7389 *
7390 * Set `inputSize.xy = outputFrame.zw` for a fullscreen filter.
7391 *
7392 * To calculate input normalized coordinate, you have to map it to filter normalized space.
7393 * Multiply by `outputFrame.zw` to get input coordinate.
7394 * Divide by `inputSize.xy` to get input normalized coordinate.
7395 *
7396 * ```
7397 * vec2 filterTextureCoord( void )
7398 * {
7399 * return aVertexPosition * (outputFrame.zw * inputSize.zw); // same as /inputSize.xy
7400 * }
7401 * ```
7402 * **resolution**
7403 *
7404 * The `resolution` is the ratio of screen (CSS) pixels to real pixels.
7405 *
7406 * **inputPixel**
7407 *
7408 * `inputPixel.xy` is the size of framebuffer in real pixels, same as `inputSize.xy * resolution`
7409 * `inputPixel.zw` is inverted `inputPixel.xy`.
7410 *
7411 * It's handy for filters that use neighbour pixels, like {@link PIXI.filters.FXAAFilter FXAAFilter}.
7412 *
7413 * **inputClamp**
7414 *
7415 * If you try to get info from outside of used part of Framebuffer - you'll get undefined behaviour.
7416 * For displacements, coordinates has to be clamped.
7417 *
7418 * The `inputClamp.xy` is left-top pixel center, you may ignore it, because we use left-top part of Framebuffer
7419 * `inputClamp.zw` is bottom-right pixel center.
7420 *
7421 * ```
7422 * vec4 color = texture2D(uSampler, clamp(modifiedTextureCoord, inputClamp.xy, inputClamp.zw))
7423 * ```
7424 * OR
7425 * ```
7426 * vec4 color = texture2D(uSampler, min(modifigedTextureCoord, inputClamp.zw))
7427 * ```
7428 *
7429 * ### Additional Information
7430 *
7431 * Complete documentation on Filter usage is located in the
7432 * {@link https://github.com/pixijs/pixi.js/wiki/v5-Creating-filters Wiki}.
7433 *
7434 * Since PixiJS only had a handful of built-in filters, additional filters can be downloaded
7435 * {@link https://github.com/pixijs/pixi-filters here} from the PixiJS Filters repository.
7436 *
7437 * @class
7438 * @memberof PIXI
7439 * @extends PIXI.Shader
7440 */
7441var Filter = /** @class */ (function (_super) {
7442 __extends(Filter, _super);
7443 /**
7444 * @param {string} [vertexSrc] - The source of the vertex shader.
7445 * @param {string} [fragmentSrc] - The source of the fragment shader.
7446 * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones.
7447 */
7448 function Filter(vertexSrc, fragmentSrc, uniforms) {
7449 var _this = this;
7450 var program = Program.from(vertexSrc || Filter.defaultVertexSrc, fragmentSrc || Filter.defaultFragmentSrc);
7451 _this = _super.call(this, program, uniforms) || this;
7452 /**
7453 * The padding of the filter. Some filters require extra space to breath such as a blur.
7454 * Increasing this will add extra width and height to the bounds of the object that the
7455 * filter is applied to.
7456 *
7457 * @member {number}
7458 */
7459 _this.padding = 0;
7460 /**
7461 * The resolution of the filter. Setting this to be lower will lower the quality but
7462 * increase the performance of the filter.
7463 *
7464 * @member {number}
7465 */
7466 _this.resolution = settings.FILTER_RESOLUTION;
7467 /**
7468 * If enabled is true the filter is applied, if false it will not.
7469 *
7470 * @member {boolean}
7471 */
7472 _this.enabled = true;
7473 /**
7474 * If enabled, PixiJS will fit the filter area into boundaries for better performance.
7475 * Switch it off if it does not work for specific shader.
7476 *
7477 * @member {boolean}
7478 */
7479 _this.autoFit = true;
7480 /**
7481 * Legacy filters use position and uvs from attributes
7482 * @member {boolean}
7483 * @readonly
7484 */
7485 _this.legacy = !!_this.program.attributeData.aTextureCoord;
7486 /**
7487 * The WebGL state the filter requires to render
7488 * @member {PIXI.State}
7489 */
7490 _this.state = new State();
7491 return _this;
7492 }
7493 /**
7494 * Applies the filter
7495 *
7496 * @param {PIXI.FilterSystem} filterManager - The renderer to retrieve the filter from
7497 * @param {PIXI.RenderTexture} input - The input render target.
7498 * @param {PIXI.RenderTexture} output - The target to output to.
7499 * @param {PIXI.CLEAR_MODES} [clearMode] - Should the output be cleared before rendering to it.
7500 * @param {object} [currentState] - It's current state of filter.
7501 * There are some useful properties in the currentState :
7502 * target, filters, sourceFrame, destinationFrame, renderTarget, resolution
7503 */
7504 Filter.prototype.apply = function (filterManager, input, output, clearMode, _currentState) {
7505 // do as you please!
7506 filterManager.applyFilter(this, input, output, clearMode);
7507 // or just do a regular render..
7508 };
7509 Object.defineProperty(Filter.prototype, "blendMode", {
7510 /**
7511 * Sets the blendmode of the filter
7512 *
7513 * @member {number}
7514 * @default PIXI.BLEND_MODES.NORMAL
7515 */
7516 get: function () {
7517 return this.state.blendMode;
7518 },
7519 set: function (value) {
7520 this.state.blendMode = value;
7521 },
7522 enumerable: false,
7523 configurable: true
7524 });
7525 Object.defineProperty(Filter, "defaultVertexSrc", {
7526 /**
7527 * The default vertex shader source
7528 *
7529 * @static
7530 * @type {string}
7531 * @constant
7532 */
7533 get: function () {
7534 return defaultVertex$1;
7535 },
7536 enumerable: false,
7537 configurable: true
7538 });
7539 Object.defineProperty(Filter, "defaultFragmentSrc", {
7540 /**
7541 * The default fragment shader source
7542 *
7543 * @static
7544 * @type {string}
7545 * @constant
7546 */
7547 get: function () {
7548 return defaultFragment$1;
7549 },
7550 enumerable: false,
7551 configurable: true
7552 });
7553 return Filter;
7554}(Shader));
7555
7556var vertex = "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n}\n";
7557
7558var fragment = "varying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform sampler2D mask;\nuniform float alpha;\nuniform float npmAlpha;\nuniform vec4 maskClamp;\n\nvoid main(void)\n{\n float clip = step(3.5,\n step(maskClamp.x, vMaskCoord.x) +\n step(maskClamp.y, vMaskCoord.y) +\n step(vMaskCoord.x, maskClamp.z) +\n step(vMaskCoord.y, maskClamp.w));\n\n vec4 original = texture2D(uSampler, vTextureCoord);\n vec4 masky = texture2D(mask, vMaskCoord);\n float alphaMul = 1.0 - npmAlpha * (1.0 - masky.a);\n\n original *= (alphaMul * masky.r * alpha * clip);\n\n gl_FragColor = original;\n}\n";
7559
7560var tempMat = new Matrix();
7561/**
7562 * Class controls uv mapping from Texture normal space to BaseTexture normal space.
7563 *
7564 * Takes `trim` and `rotate` into account. May contain clamp settings for Meshes and TilingSprite.
7565 *
7566 * Can be used in Texture `uvMatrix` field, or separately, you can use different clamp settings on the same texture.
7567 * If you want to add support for texture region of certain feature or filter, that's what you're looking for.
7568 *
7569 * Takes track of Texture changes through `_lastTextureID` private field.
7570 * Use `update()` method call to track it from outside.
7571 *
7572 * @see PIXI.Texture
7573 * @see PIXI.Mesh
7574 * @see PIXI.TilingSprite
7575 * @class
7576 * @memberof PIXI
7577 */
7578var TextureMatrix = /** @class */ (function () {
7579 /**
7580 *
7581 * @param {PIXI.Texture} texture - observed texture
7582 * @param {number} [clampMargin] - Changes frame clamping, 0.5 by default. Use -0.5 for extra border.
7583 * @constructor
7584 */
7585 function TextureMatrix(texture, clampMargin) {
7586 this._texture = texture;
7587 /**
7588 * Matrix operation that converts texture region coords to texture coords
7589 * @member {PIXI.Matrix}
7590 * @readonly
7591 */
7592 this.mapCoord = new Matrix();
7593 /**
7594 * Clamp region for normalized coords, left-top pixel center in xy , bottom-right in zw.
7595 * Calculated based on clampOffset.
7596 * @member {Float32Array}
7597 * @readonly
7598 */
7599 this.uClampFrame = new Float32Array(4);
7600 /**
7601 * Normalized clamp offset.
7602 * Calculated based on clampOffset.
7603 * @member {Float32Array}
7604 * @readonly
7605 */
7606 this.uClampOffset = new Float32Array(2);
7607 /**
7608 * Tracks Texture frame changes
7609 * @member {number}
7610 * @protected
7611 */
7612 this._textureID = -1;
7613 /**
7614 * Tracks Texture frame changes
7615 * @member {number}
7616 * @protected
7617 */
7618 this._updateID = 0;
7619 /**
7620 * Changes frame clamping
7621 * Works with TilingSprite and Mesh
7622 * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders
7623 *
7624 * @default 0
7625 * @member {number}
7626 */
7627 this.clampOffset = 0;
7628 /**
7629 * Changes frame clamping
7630 * Works with TilingSprite and Mesh
7631 * Change to -0.5 to add a pixel to the edge, recommended for transparent trimmed textures in atlas
7632 *
7633 * @default 0.5
7634 * @member {number}
7635 */
7636 this.clampMargin = (typeof clampMargin === 'undefined') ? 0.5 : clampMargin;
7637 /**
7638 * If texture size is the same as baseTexture
7639 * @member {boolean}
7640 * @default false
7641 * @readonly
7642 */
7643 this.isSimple = false;
7644 }
7645 Object.defineProperty(TextureMatrix.prototype, "texture", {
7646 /**
7647 * texture property
7648 * @member {PIXI.Texture}
7649 */
7650 get: function () {
7651 return this._texture;
7652 },
7653 set: function (value) {
7654 this._texture = value;
7655 this._textureID = -1;
7656 },
7657 enumerable: false,
7658 configurable: true
7659 });
7660 /**
7661 * Multiplies uvs array to transform
7662 * @param {Float32Array} uvs - mesh uvs
7663 * @param {Float32Array} [out=uvs] - output
7664 * @returns {Float32Array} output
7665 */
7666 TextureMatrix.prototype.multiplyUvs = function (uvs, out) {
7667 if (out === undefined) {
7668 out = uvs;
7669 }
7670 var mat = this.mapCoord;
7671 for (var i = 0; i < uvs.length; i += 2) {
7672 var x = uvs[i];
7673 var y = uvs[i + 1];
7674 out[i] = (x * mat.a) + (y * mat.c) + mat.tx;
7675 out[i + 1] = (x * mat.b) + (y * mat.d) + mat.ty;
7676 }
7677 return out;
7678 };
7679 /**
7680 * updates matrices if texture was changed
7681 * @param {boolean} [forceUpdate=false] - if true, matrices will be updated any case
7682 * @returns {boolean} whether or not it was updated
7683 */
7684 TextureMatrix.prototype.update = function (forceUpdate) {
7685 var tex = this._texture;
7686 if (!tex || !tex.valid) {
7687 return false;
7688 }
7689 if (!forceUpdate
7690 && this._textureID === tex._updateID) {
7691 return false;
7692 }
7693 this._textureID = tex._updateID;
7694 this._updateID++;
7695 var uvs = tex._uvs;
7696 this.mapCoord.set(uvs.x1 - uvs.x0, uvs.y1 - uvs.y0, uvs.x3 - uvs.x0, uvs.y3 - uvs.y0, uvs.x0, uvs.y0);
7697 var orig = tex.orig;
7698 var trim = tex.trim;
7699 if (trim) {
7700 tempMat.set(orig.width / trim.width, 0, 0, orig.height / trim.height, -trim.x / trim.width, -trim.y / trim.height);
7701 this.mapCoord.append(tempMat);
7702 }
7703 var texBase = tex.baseTexture;
7704 var frame = this.uClampFrame;
7705 var margin = this.clampMargin / texBase.resolution;
7706 var offset = this.clampOffset;
7707 frame[0] = (tex._frame.x + margin + offset) / texBase.width;
7708 frame[1] = (tex._frame.y + margin + offset) / texBase.height;
7709 frame[2] = (tex._frame.x + tex._frame.width - margin + offset) / texBase.width;
7710 frame[3] = (tex._frame.y + tex._frame.height - margin + offset) / texBase.height;
7711 this.uClampOffset[0] = offset / texBase.realWidth;
7712 this.uClampOffset[1] = offset / texBase.realHeight;
7713 this.isSimple = tex._frame.width === texBase.width
7714 && tex._frame.height === texBase.height
7715 && tex.rotate === 0;
7716 return true;
7717 };
7718 return TextureMatrix;
7719}());
7720
7721/**
7722 * This handles a Sprite acting as a mask, as opposed to a Graphic.
7723 *
7724 * WebGL only.
7725 *
7726 * @class
7727 * @extends PIXI.Filter
7728 * @memberof PIXI
7729 */
7730var SpriteMaskFilter = /** @class */ (function (_super) {
7731 __extends(SpriteMaskFilter, _super);
7732 /**
7733 * @param {PIXI.Sprite} sprite - the target sprite
7734 */
7735 function SpriteMaskFilter(sprite) {
7736 var _this = this;
7737 var maskMatrix = new Matrix();
7738 _this = _super.call(this, vertex, fragment) || this;
7739 sprite.renderable = false;
7740 /**
7741 * Sprite mask
7742 * @member {PIXI.Sprite}
7743 */
7744 _this.maskSprite = sprite;
7745 /**
7746 * Mask matrix
7747 * @member {PIXI.Matrix}
7748 */
7749 _this.maskMatrix = maskMatrix;
7750 return _this;
7751 }
7752 /**
7753 * Applies the filter
7754 *
7755 * @param {PIXI.FilterSystem} filterManager - The renderer to retrieve the filter from
7756 * @param {PIXI.RenderTexture} input - The input render target.
7757 * @param {PIXI.RenderTexture} output - The target to output to.
7758 * @param {PIXI.CLEAR_MODES} clearMode - Should the output be cleared before rendering to it.
7759 */
7760 SpriteMaskFilter.prototype.apply = function (filterManager, input, output, clearMode) {
7761 var maskSprite = this.maskSprite;
7762 var tex = maskSprite._texture;
7763 if (!tex.valid) {
7764 return;
7765 }
7766 if (!tex.uvMatrix) {
7767 // margin = 0.0, let it bleed a bit, shader code becomes easier
7768 // assuming that atlas textures were made with 1-pixel padding
7769 tex.uvMatrix = new TextureMatrix(tex, 0.0);
7770 }
7771 tex.uvMatrix.update();
7772 this.uniforms.npmAlpha = tex.baseTexture.alphaMode ? 0.0 : 1.0;
7773 this.uniforms.mask = tex;
7774 // get _normalized sprite texture coords_ and convert them to _normalized atlas texture coords_ with `prepend`
7775 this.uniforms.otherMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, maskSprite)
7776 .prepend(tex.uvMatrix.mapCoord);
7777 this.uniforms.alpha = maskSprite.worldAlpha;
7778 this.uniforms.maskClamp = tex.uvMatrix.uClampFrame;
7779 filterManager.applyFilter(this, input, output, clearMode);
7780 };
7781 return SpriteMaskFilter;
7782}(Filter));
7783
7784/**
7785 * System plugin to the renderer to manage masks.
7786 *
7787 * There are three built-in types of masking:
7788 * * **Scissor Masking**: Scissor masking discards pixels that are outside of a rectangle called the scissor box. It is
7789 * the most performant as the scissor test is inexpensive. However, it can only be used when the mask is rectangular.
7790 * * **Stencil Masking**: Stencil masking discards pixels that don't overlap with the pixels rendered into the stencil
7791 * buffer. It is the next fastest option as it does not require rendering into a separate framebuffer. However, it does
7792 * cause the mask to be rendered **twice** for each masking operation; hence, minimize the rendering cost of your masks.
7793 * * **Sprite Mask Filtering**: Sprite mask filtering discards pixels based on the red channel of the sprite-mask's
7794 * texture. (Generally, the masking texture is grayscale). Using advanced techniques, you might be able to embed this
7795 * type of masking in a custom shader - and hence, bypassing the masking system fully for performance wins.
7796 *
7797 * The best type of masking is auto-detected when you `push` one. To use scissor masking, you must pass in a `Graphics`
7798 * object with just a rectangle drawn.
7799 *
7800 * ## Mask Stacks
7801 *
7802 * In the scene graph, masks can be applied recursively, i.e. a mask can be applied during a masking operation. The mask
7803 * stack stores the currently applied masks in order. Each {@link PIXI.BaseRenderTexture} holds its own mask stack, i.e.
7804 * when you switch render-textures, the old masks only applied when you switch back to rendering to the old render-target.
7805 *
7806 * @class
7807 * @extends PIXI.System
7808 * @memberof PIXI
7809 */
7810var MaskSystem = /** @class */ (function (_super) {
7811 __extends(MaskSystem, _super);
7812 /**
7813 * @param {PIXI.Renderer} renderer - The renderer this System works for.
7814 */
7815 function MaskSystem(renderer) {
7816 var _this = _super.call(this, renderer) || this;
7817 /**
7818 * Enable scissor masking.
7819 *
7820 * @member {boolean}
7821 * @readonly
7822 */
7823 _this.enableScissor = true;
7824 /**
7825 * Pool of used sprite mask filters
7826 * @member {PIXI.SpriteMaskFilter[]}
7827 * @readonly
7828 */
7829 _this.alphaMaskPool = [];
7830 /**
7831 * Pool of mask data
7832 * @member {PIXI.MaskData[]}
7833 * @readonly
7834 */
7835 _this.maskDataPool = [];
7836 _this.maskStack = [];
7837 /**
7838 * Current index of alpha mask pool
7839 * @member {number}
7840 * @default 0
7841 * @readonly
7842 */
7843 _this.alphaMaskIndex = 0;
7844 return _this;
7845 }
7846 /**
7847 * Changes the mask stack that is used by this System.
7848 *
7849 * @param {PIXI.MaskData[]} maskStack - The mask stack
7850 */
7851 MaskSystem.prototype.setMaskStack = function (maskStack) {
7852 this.maskStack = maskStack;
7853 this.renderer.scissor.setMaskStack(maskStack);
7854 this.renderer.stencil.setMaskStack(maskStack);
7855 };
7856 /**
7857 * Enables the mask and appends it to the current mask stack.
7858 *
7859 * NOTE: The batch renderer should be flushed beforehand to prevent pending renders from being masked.
7860 *
7861 * @param {PIXI.DisplayObject} target - Display Object to push the mask to
7862 * @param {PIXI.MaskData|PIXI.Sprite|PIXI.Graphics|PIXI.DisplayObject} maskData - The masking data.
7863 */
7864 MaskSystem.prototype.push = function (target, maskDataOrTarget) {
7865 var maskData = maskDataOrTarget;
7866 if (!maskData.isMaskData) {
7867 var d = this.maskDataPool.pop() || new MaskData();
7868 d.pooled = true;
7869 d.maskObject = maskDataOrTarget;
7870 maskData = d;
7871 }
7872 if (maskData.autoDetect) {
7873 this.detect(maskData);
7874 }
7875 maskData.copyCountersOrReset(this.maskStack[this.maskStack.length - 1]);
7876 maskData._target = target;
7877 switch (maskData.type) {
7878 case MASK_TYPES.SCISSOR:
7879 this.maskStack.push(maskData);
7880 this.renderer.scissor.push(maskData);
7881 break;
7882 case MASK_TYPES.STENCIL:
7883 this.maskStack.push(maskData);
7884 this.renderer.stencil.push(maskData);
7885 break;
7886 case MASK_TYPES.SPRITE:
7887 maskData.copyCountersOrReset(null);
7888 this.pushSpriteMask(maskData);
7889 this.maskStack.push(maskData);
7890 break;
7891 }
7892 };
7893 /**
7894 * Removes the last mask from the mask stack and doesn't return it.
7895 *
7896 * NOTE: The batch renderer should be flushed beforehand to render the masked contents before the mask is removed.
7897 *
7898 * @param {PIXI.DisplayObject} target - Display Object to pop the mask from
7899 */
7900 MaskSystem.prototype.pop = function (target) {
7901 var maskData = this.maskStack.pop();
7902 if (!maskData || maskData._target !== target) {
7903 // TODO: add an assert when we have it
7904 return;
7905 }
7906 switch (maskData.type) {
7907 case MASK_TYPES.SCISSOR:
7908 this.renderer.scissor.pop();
7909 break;
7910 case MASK_TYPES.STENCIL:
7911 this.renderer.stencil.pop(maskData.maskObject);
7912 break;
7913 case MASK_TYPES.SPRITE:
7914 this.popSpriteMask();
7915 break;
7916 }
7917 maskData.reset();
7918 if (maskData.pooled) {
7919 this.maskDataPool.push(maskData);
7920 }
7921 };
7922 /**
7923 * Sets type of MaskData based on its maskObject
7924 * @param {PIXI.MaskData} maskData
7925 */
7926 MaskSystem.prototype.detect = function (maskData) {
7927 var maskObject = maskData.maskObject;
7928 if (maskObject.isSprite) {
7929 maskData.type = MASK_TYPES.SPRITE;
7930 return;
7931 }
7932 maskData.type = MASK_TYPES.STENCIL;
7933 // detect scissor in graphics
7934 if (this.enableScissor
7935 && maskObject.isFastRect
7936 && maskObject.isFastRect()) {
7937 var matrix = maskObject.worldTransform;
7938 // TODO: move the check to the matrix itself
7939 // we are checking that its orthogonal and x rotation is 0 90 180 or 270
7940 var rotX = Math.atan2(matrix.b, matrix.a);
7941 var rotXY = Math.atan2(matrix.d, matrix.c);
7942 // use the nearest degree to 0.01
7943 rotX = Math.round(rotX * (180 / Math.PI) * 100);
7944 rotXY = Math.round(rotXY * (180 / Math.PI) * 100) - rotX;
7945 rotX = ((rotX % 9000) + 9000) % 9000;
7946 rotXY = ((rotXY % 18000) + 18000) % 18000;
7947 if (rotX === 0 && rotXY === 9000) {
7948 maskData.type = MASK_TYPES.SCISSOR;
7949 }
7950 }
7951 };
7952 /**
7953 * Applies the Mask and adds it to the current filter stack.
7954 *
7955 * @param {PIXI.MaskData} maskData - Sprite to be used as the mask
7956 */
7957 MaskSystem.prototype.pushSpriteMask = function (maskData) {
7958 var maskObject = maskData.maskObject;
7959 var target = maskData._target;
7960 var alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex];
7961 if (!alphaMaskFilter) {
7962 alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new SpriteMaskFilter(maskObject)];
7963 }
7964 alphaMaskFilter[0].resolution = this.renderer.resolution;
7965 alphaMaskFilter[0].maskSprite = maskObject;
7966 var stashFilterArea = target.filterArea;
7967 target.filterArea = maskObject.getBounds(true);
7968 this.renderer.filter.push(target, alphaMaskFilter);
7969 target.filterArea = stashFilterArea;
7970 this.alphaMaskIndex++;
7971 };
7972 /**
7973 * Removes the last filter from the filter stack and doesn't return it.
7974 */
7975 MaskSystem.prototype.popSpriteMask = function () {
7976 this.renderer.filter.pop();
7977 this.alphaMaskIndex--;
7978 };
7979 return MaskSystem;
7980}(System));
7981
7982/**
7983 * System plugin to the renderer to manage specific types of masking operations.
7984 *
7985 * @class
7986 * @extends PIXI.System
7987 * @memberof PIXI
7988 */
7989var AbstractMaskSystem = /** @class */ (function (_super) {
7990 __extends(AbstractMaskSystem, _super);
7991 /**
7992 * @param {PIXI.Renderer} renderer - The renderer this System works for.
7993 */
7994 function AbstractMaskSystem(renderer) {
7995 var _this = _super.call(this, renderer) || this;
7996 /**
7997 * The mask stack
7998 * @member {PIXI.MaskData[]}
7999 */
8000 _this.maskStack = [];
8001 /**
8002 * Constant for gl.enable
8003 * @member {number}
8004 * @private
8005 */
8006 _this.glConst = 0;
8007 return _this;
8008 }
8009 /**
8010 * gets count of masks of certain type
8011 * @returns {number}
8012 */
8013 AbstractMaskSystem.prototype.getStackLength = function () {
8014 return this.maskStack.length;
8015 };
8016 /**
8017 * Changes the mask stack that is used by this System.
8018 *
8019 * @param {PIXI.MaskData[]} maskStack - The mask stack
8020 */
8021 AbstractMaskSystem.prototype.setMaskStack = function (maskStack) {
8022 var gl = this.renderer.gl;
8023 var curStackLen = this.getStackLength();
8024 this.maskStack = maskStack;
8025 var newStackLen = this.getStackLength();
8026 if (newStackLen !== curStackLen) {
8027 if (newStackLen === 0) {
8028 gl.disable(this.glConst);
8029 }
8030 else {
8031 gl.enable(this.glConst);
8032 this._useCurrent();
8033 }
8034 }
8035 };
8036 /**
8037 * Setup renderer to use the current mask data.
8038 * @private
8039 */
8040 AbstractMaskSystem.prototype._useCurrent = function () {
8041 // OVERWRITE;
8042 };
8043 /**
8044 * Destroys the mask stack.
8045 *
8046 */
8047 AbstractMaskSystem.prototype.destroy = function () {
8048 _super.prototype.destroy.call(this);
8049 this.maskStack = null;
8050 };
8051 return AbstractMaskSystem;
8052}(System));
8053
8054/**
8055 * System plugin to the renderer to manage scissor masking.
8056 *
8057 * Scissor masking discards pixels outside of a rectangle called the scissor box. The scissor box is in the framebuffer
8058 * viewport's space; however, the mask's rectangle is projected from world-space to viewport space automatically
8059 * by this system.
8060 *
8061 * @class
8062 * @extends PIXI.System
8063 * @memberof PIXI
8064 */
8065var ScissorSystem = /** @class */ (function (_super) {
8066 __extends(ScissorSystem, _super);
8067 /**
8068 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8069 */
8070 function ScissorSystem(renderer) {
8071 var _this = _super.call(this, renderer) || this;
8072 _this.glConst = WebGLRenderingContext.SCISSOR_TEST;
8073 return _this;
8074 }
8075 ScissorSystem.prototype.getStackLength = function () {
8076 var maskData = this.maskStack[this.maskStack.length - 1];
8077 if (maskData) {
8078 return maskData._scissorCounter;
8079 }
8080 return 0;
8081 };
8082 /**
8083 * Applies the Mask and adds it to the current stencil stack.
8084 *
8085 * @author alvin
8086 * @param {PIXI.MaskData} maskData - The mask data
8087 */
8088 ScissorSystem.prototype.push = function (maskData) {
8089 var maskObject = maskData.maskObject;
8090 maskObject.renderable = true;
8091 var prevData = maskData._scissorRect;
8092 var bounds = maskObject.getBounds(true);
8093 var gl = this.renderer.gl;
8094 maskObject.renderable = false;
8095 if (prevData) {
8096 bounds.fit(prevData);
8097 }
8098 else {
8099 gl.enable(gl.SCISSOR_TEST);
8100 }
8101 maskData._scissorCounter++;
8102 maskData._scissorRect = bounds;
8103 this._useCurrent();
8104 };
8105 /**
8106 * This should be called after a mask is popped off the mask stack. It will rebind the scissor box to be latest with the
8107 * last mask in the stack.
8108 *
8109 * This can also be called when you directly modify the scissor box and want to restore PixiJS state.
8110 */
8111 ScissorSystem.prototype.pop = function () {
8112 var gl = this.renderer.gl;
8113 if (this.getStackLength() > 0) {
8114 this._useCurrent();
8115 }
8116 else {
8117 gl.disable(gl.SCISSOR_TEST);
8118 }
8119 };
8120 /**
8121 * Setup renderer to use the current scissor data.
8122 * @private
8123 */
8124 ScissorSystem.prototype._useCurrent = function () {
8125 var rect = this.maskStack[this.maskStack.length - 1]._scissorRect;
8126 var rt = this.renderer.renderTexture.current;
8127 var _a = this.renderer.projection, transform = _a.transform, sourceFrame = _a.sourceFrame, destinationFrame = _a.destinationFrame;
8128 var resolution = rt ? rt.resolution : this.renderer.resolution;
8129 var sx = destinationFrame.width / sourceFrame.width;
8130 var sy = destinationFrame.height / sourceFrame.height;
8131 var x = (((rect.x - sourceFrame.x) * sx) + destinationFrame.x) * resolution;
8132 var y = (((rect.y - sourceFrame.y) * sy) + destinationFrame.y) * resolution;
8133 var width = rect.width * sx * resolution;
8134 var height = rect.height * sy * resolution;
8135 if (transform) {
8136 x += transform.tx * resolution;
8137 y += transform.ty * resolution;
8138 }
8139 if (!rt) {
8140 // flipY. In future we'll have it over renderTextures as an option
8141 y = this.renderer.height - height - y;
8142 }
8143 this.renderer.gl.scissor(x, y, width, height);
8144 };
8145 return ScissorSystem;
8146}(AbstractMaskSystem));
8147
8148/**
8149 * System plugin to the renderer to manage stencils (used for masks).
8150 *
8151 * @class
8152 * @extends PIXI.System
8153 * @memberof PIXI
8154 */
8155var StencilSystem = /** @class */ (function (_super) {
8156 __extends(StencilSystem, _super);
8157 /**
8158 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8159 */
8160 function StencilSystem(renderer) {
8161 var _this = _super.call(this, renderer) || this;
8162 _this.glConst = WebGLRenderingContext.STENCIL_TEST;
8163 return _this;
8164 }
8165 StencilSystem.prototype.getStackLength = function () {
8166 var maskData = this.maskStack[this.maskStack.length - 1];
8167 if (maskData) {
8168 return maskData._stencilCounter;
8169 }
8170 return 0;
8171 };
8172 /**
8173 * Applies the Mask and adds it to the current stencil stack.
8174 *
8175 * @param {PIXI.MaskData} maskData - The mask data
8176 */
8177 StencilSystem.prototype.push = function (maskData) {
8178 var maskObject = maskData.maskObject;
8179 var gl = this.renderer.gl;
8180 var prevMaskCount = maskData._stencilCounter;
8181 if (prevMaskCount === 0) {
8182 // force use stencil texture in current framebuffer
8183 this.renderer.framebuffer.forceStencil();
8184 gl.enable(gl.STENCIL_TEST);
8185 }
8186 maskData._stencilCounter++;
8187 // Increment the reference stencil value where the new mask overlaps with the old ones.
8188 gl.colorMask(false, false, false, false);
8189 gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask());
8190 gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
8191 maskObject.renderable = true;
8192 maskObject.render(this.renderer);
8193 this.renderer.batch.flush();
8194 this.renderer.framebuffer.blit();
8195 maskObject.renderable = false;
8196 this._useCurrent();
8197 };
8198 /**
8199 * Pops stencil mask. MaskData is already removed from stack
8200 *
8201 * @param {PIXI.DisplayObject} maskObject - object of popped mask data
8202 */
8203 StencilSystem.prototype.pop = function (maskObject) {
8204 var gl = this.renderer.gl;
8205 if (this.getStackLength() === 0) {
8206 // the stack is empty!
8207 gl.disable(gl.STENCIL_TEST);
8208 gl.clear(gl.STENCIL_BUFFER_BIT);
8209 gl.clearStencil(0);
8210 }
8211 else {
8212 // Decrement the reference stencil value where the popped mask overlaps with the other ones
8213 gl.colorMask(false, false, false, false);
8214 gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
8215 maskObject.renderable = true;
8216 maskObject.render(this.renderer);
8217 this.renderer.batch.flush();
8218 maskObject.renderable = false;
8219 this._useCurrent();
8220 }
8221 };
8222 /**
8223 * Setup renderer to use the current stencil data.
8224 * @private
8225 */
8226 StencilSystem.prototype._useCurrent = function () {
8227 var gl = this.renderer.gl;
8228 gl.colorMask(true, true, true, true);
8229 gl.stencilFunc(gl.EQUAL, this.getStackLength(), this._getBitwiseMask());
8230 gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
8231 };
8232 /**
8233 * Fill 1s equal to the number of acitve stencil masks.
8234 * @private
8235 * @return {number} The bitwise mask.
8236 */
8237 StencilSystem.prototype._getBitwiseMask = function () {
8238 return (1 << this.getStackLength()) - 1;
8239 };
8240 return StencilSystem;
8241}(AbstractMaskSystem));
8242
8243/**
8244 * System plugin to the renderer to manage the projection matrix.
8245 *
8246 * The `projectionMatrix` is a global uniform provided to all shaders. It is used to transform points in world space to
8247 * normalized device coordinates.
8248 *
8249 * @class
8250 * @extends PIXI.System
8251 * @memberof PIXI
8252 */
8253var ProjectionSystem = /** @class */ (function (_super) {
8254 __extends(ProjectionSystem, _super);
8255 /**
8256 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8257 */
8258 function ProjectionSystem(renderer) {
8259 var _this = _super.call(this, renderer) || this;
8260 /**
8261 * The destination frame used to calculate the current projection matrix.
8262 *
8263 * The destination frame is the rectangle in the render-target into which contents are rendered. If rendering
8264 * to the screen, the origin is on the top-left. If rendering to a framebuffer, the origin is on the
8265 * bottom-left. This "flipping" phenomenon is because of WebGL convention for (shader) texture coordinates, where
8266 * the bottom-left corner is (0,0). It allows display-objects to map their (0,0) position in local-space (top-left)
8267 * to (0,0) in texture space (bottom-left). In other words, a sprite's top-left corner actually renders the
8268 * texture's bottom-left corner. You will also notice this when using a tool like SpectorJS to view your textures
8269 * at runtime.
8270 *
8271 * The destination frame's dimensions (width,height) should be equal to the source frame. This is because,
8272 * otherwise, the contents will be scaled to fill the destination frame. Similarly, the destination frame's (x,y)
8273 * coordinates are (0,0) unless you know what you're doing.
8274 *
8275 *
8276 * @member {PIXI.Rectangle}
8277 * @readonly
8278 */
8279 _this.destinationFrame = null;
8280 /**
8281 * The source frame used to calculate the current projection matrix.
8282 *
8283 * The source frame is the rectangle in world space containing the contents to be rendered.
8284 *
8285 * @member {PIXI.Rectangle}
8286 * @readonly
8287 */
8288 _this.sourceFrame = null;
8289 /**
8290 * Default destination frame
8291 *
8292 * This is not used internally. It is not advised to use this feature specifically unless you know what
8293 * you're doing. The `update` method will default to this frame if you do not pass the destination frame.
8294 *
8295 * @member {PIXI.Rectangle}
8296 * @readonly
8297 */
8298 _this.defaultFrame = null;
8299 /**
8300 * Projection matrix
8301 *
8302 * This matrix can be used to transform points from world space to normalized device coordinates, and is calculated
8303 * from the sourceFrame → destinationFrame mapping provided.
8304 *
8305 * The renderer's `globalUniforms` keeps a reference to this, and so it is available for all shaders to use as a
8306 * uniform.
8307 *
8308 * @member {PIXI.Matrix}
8309 * @readonly
8310 */
8311 _this.projectionMatrix = new Matrix();
8312 /**
8313 * A transform to be appended to the projection matrix.
8314 *
8315 * This can be used to transform points in world-space one last time before they are outputted by the shader. You can
8316 * use to rotate the whole scene, for example. Remember to clear it once you've rendered everything.
8317 *
8318 * @member {PIXI.Matrix}
8319 */
8320 _this.transform = null;
8321 return _this;
8322 }
8323 /**
8324 * Updates the projection-matrix based on the sourceFrame → destinationFrame mapping provided.
8325 *
8326 * NOTE: It is expected you call `renderer.framebuffer.setViewport(destinationFrame)` after this. This is because
8327 * the framebuffer viewport converts shader vertex output in normalized device coordinates to window coordinates.
8328 *
8329 * NOTE-2: {@link RenderTextureSystem#bind} updates the projection-matrix when you bind a render-texture. It is expected
8330 * that you dirty the current bindings when calling this manually.
8331 *
8332 * @param {PIXI.Rectangle} destinationFrame - The rectangle in the render-target to render the contents
8333 * into. If rendering to the canvas, the origin is on the top-left; if rendering to a render-texture, the origin
8334 * is on the bottom-left.
8335 * @param {PIXI.Rectangle} sourceFrame - The rectangle in world space that contains the contents being rendered.
8336 * @param {Number} resolution - The resolution of the render-target, which is the ratio of world-space (or CSS) pixels
8337 * to physical pixels.
8338 * @param {boolean} root - Whether the render-target is the screen. This is required because rendering to textures
8339 * is y-flipped (i.e. upside down relative to the screen).
8340 */
8341 ProjectionSystem.prototype.update = function (destinationFrame, sourceFrame, resolution, root) {
8342 this.destinationFrame = destinationFrame || this.destinationFrame || this.defaultFrame;
8343 this.sourceFrame = sourceFrame || this.sourceFrame || destinationFrame;
8344 // Calculate object-space to clip-space projection
8345 this.calculateProjection(this.destinationFrame, this.sourceFrame, resolution, root);
8346 if (this.transform) {
8347 this.projectionMatrix.append(this.transform);
8348 }
8349 var renderer = this.renderer;
8350 renderer.globalUniforms.uniforms.projectionMatrix = this.projectionMatrix;
8351 renderer.globalUniforms.update();
8352 // this will work for now
8353 // but would be sweet to stick and even on the global uniforms..
8354 if (renderer.shader.shader) {
8355 renderer.shader.syncUniformGroup(renderer.shader.shader.uniforms.globals);
8356 }
8357 };
8358 /**
8359 * Calculates the `projectionMatrix` to map points inside `sourceFrame` to inside `destinationFrame`.
8360 *
8361 * @param {PIXI.Rectangle} destinationFrame - The destination frame in the render-target.
8362 * @param {PIXI.Rectangle} sourceFrame - The source frame in world space.
8363 * @param {Number} resolution - The render-target's resolution, i.e. ratio of CSS to physical pixels.
8364 * @param {boolean} root - Whether rendering into the screen. Otherwise, if rendering to a framebuffer, the projection
8365 * is y-flipped.
8366 */
8367 ProjectionSystem.prototype.calculateProjection = function (_destinationFrame, sourceFrame, _resolution, root) {
8368 var pm = this.projectionMatrix;
8369 var sign = !root ? 1 : -1;
8370 pm.identity();
8371 pm.a = (1 / sourceFrame.width * 2);
8372 pm.d = sign * (1 / sourceFrame.height * 2);
8373 pm.tx = -1 - (sourceFrame.x * pm.a);
8374 pm.ty = -sign - (sourceFrame.y * pm.d);
8375 };
8376 /**
8377 * Sets the transform of the active render target to the given matrix
8378 *
8379 * @param {PIXI.Matrix} matrix - The transformation matrix
8380 */
8381 ProjectionSystem.prototype.setTransform = function (_matrix) {
8382 // this._activeRenderTarget.transform = matrix;
8383 };
8384 return ProjectionSystem;
8385}(System));
8386
8387// Temporary rectangle for assigned sourceFrame or destinationFrame
8388var tempRect = new Rectangle();
8389// Temporary rectangle for renderTexture destinationFrame
8390var tempRect2 = new Rectangle();
8391/* eslint-disable max-len */
8392/**
8393 * System plugin to the renderer to manage render textures.
8394 *
8395 * Should be added after FramebufferSystem
8396 *
8397 * ### Frames
8398 *
8399 * The `RenderTextureSystem` holds a sourceFrame → destinationFrame projection. The following table explains the different
8400 * coordinate spaces used:
8401 *
8402 * | Frame | Description | Coordinate System |
8403 * | ---------------------- | ---------------------------------------------------------------- | ------------------------------------------------------- |
8404 * | sourceFrame | The rectangle inside of which display-objects are being rendered | **World Space**: The origin on the top-left |
8405 * | destinationFrame | The rectangle in the render-target (canvas or texture) into which contents should be rendered | If rendering to the canvas, this is in screen space and the origin is on the top-left. If rendering to a render-texture, this is in its base-texture's space with the origin on the bottom-left. |
8406 * | viewportFrame | The framebuffer viewport corresponding to the destination-frame | **Window Coordinates**: The origin is always on the bottom-left. |
8407 *
8408 * @class
8409 * @extends PIXI.System
8410 * @memberof PIXI
8411 */
8412var RenderTextureSystem = /** @class */ (function (_super) {
8413 __extends(RenderTextureSystem, _super);
8414 /**
8415 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8416 */
8417 function RenderTextureSystem(renderer) {
8418 var _this = _super.call(this, renderer) || this;
8419 /**
8420 * The clear background color as rgba
8421 * @member {number[]}
8422 */
8423 _this.clearColor = renderer._backgroundColorRgba;
8424 // TODO move this property somewhere else!
8425 /**
8426 * List of masks for the StencilSystem
8427 * @member {PIXI.Graphics[]}
8428 * @readonly
8429 */
8430 _this.defaultMaskStack = [];
8431 // empty render texture?
8432 /**
8433 * Render texture
8434 * @member {PIXI.RenderTexture}
8435 * @readonly
8436 */
8437 _this.current = null;
8438 /**
8439 * The source frame for the render-target's projection mapping.
8440 *
8441 * See {@link PIXI.ProjectionSystem#sourceFrame} for more details.
8442 *
8443 * @member {PIXI.Rectangle}
8444 * @readonly
8445 */
8446 _this.sourceFrame = new Rectangle();
8447 /**
8448 * The destination frame for the render-target's projection mapping.
8449 *
8450 * See {@link PIXI.Projection#destinationFrame} for more details.
8451 *
8452 * @member {PIXI.Rectangle}
8453 * @readonly
8454 */
8455 _this.destinationFrame = new Rectangle();
8456 /**
8457 * The viewport frame for the render-target's viewport binding. This is equal to the destination-frame
8458 * for render-textures, while it is y-flipped when rendering to the screen (i.e. its origin is always on
8459 * the bottom-left).
8460 *
8461 * @member {PIXI.Rectangle}
8462 * @readonly
8463 */
8464 _this.viewportFrame = new Rectangle();
8465 return _this;
8466 }
8467 /**
8468 * Bind the current render texture
8469 *
8470 * @param {PIXI.RenderTexture} [renderTexture] - RenderTexture to bind, by default its `null`, the screen
8471 * @param {PIXI.Rectangle} [sourceFrame] - part of screen that is mapped to the renderTexture
8472 * @param {PIXI.Rectangle} [destinationFrame] - part of renderTexture, by default it has the same size as sourceFrame
8473 */
8474 RenderTextureSystem.prototype.bind = function (renderTexture, sourceFrame, destinationFrame) {
8475 if (renderTexture === void 0) { renderTexture = null; }
8476 var renderer = this.renderer;
8477 this.current = renderTexture;
8478 var baseTexture;
8479 var framebuffer;
8480 var resolution;
8481 if (renderTexture) {
8482 baseTexture = renderTexture.baseTexture;
8483 resolution = baseTexture.resolution;
8484 if (!sourceFrame) {
8485 tempRect.width = renderTexture.frame.width;
8486 tempRect.height = renderTexture.frame.height;
8487 sourceFrame = tempRect;
8488 }
8489 if (!destinationFrame) {
8490 tempRect2.x = renderTexture.frame.x;
8491 tempRect2.y = renderTexture.frame.y;
8492 tempRect2.width = sourceFrame.width;
8493 tempRect2.height = sourceFrame.height;
8494 destinationFrame = tempRect2;
8495 }
8496 framebuffer = baseTexture.framebuffer;
8497 }
8498 else {
8499 resolution = renderer.resolution;
8500 if (!sourceFrame) {
8501 tempRect.width = renderer.screen.width;
8502 tempRect.height = renderer.screen.height;
8503 sourceFrame = tempRect;
8504 }
8505 if (!destinationFrame) {
8506 destinationFrame = tempRect;
8507 destinationFrame.width = sourceFrame.width;
8508 destinationFrame.height = sourceFrame.height;
8509 }
8510 }
8511 var viewportFrame = this.viewportFrame;
8512 viewportFrame.x = destinationFrame.x * resolution;
8513 viewportFrame.y = destinationFrame.y * resolution;
8514 viewportFrame.width = destinationFrame.width * resolution;
8515 viewportFrame.height = destinationFrame.height * resolution;
8516 if (!renderTexture) {
8517 viewportFrame.y = renderer.view.height - (viewportFrame.y + viewportFrame.height);
8518 }
8519 this.renderer.framebuffer.bind(framebuffer, viewportFrame);
8520 this.renderer.projection.update(destinationFrame, sourceFrame, resolution, !framebuffer);
8521 if (renderTexture) {
8522 this.renderer.mask.setMaskStack(baseTexture.maskStack);
8523 }
8524 else {
8525 this.renderer.mask.setMaskStack(this.defaultMaskStack);
8526 }
8527 this.sourceFrame.copyFrom(sourceFrame);
8528 this.destinationFrame.copyFrom(destinationFrame);
8529 };
8530 /**
8531 * Erases the render texture and fills the drawing area with a colour
8532 *
8533 * @param {number[]} [clearColor] - The color as rgba, default to use the renderer backgroundColor
8534 * @param {PIXI.BUFFER_BITS} [mask=BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH] - Bitwise OR of masks
8535 * that indicate the buffers to be cleared, by default COLOR and DEPTH buffers.
8536 * @return {PIXI.Renderer} Returns itself.
8537 */
8538 RenderTextureSystem.prototype.clear = function (clearColor, mask) {
8539 if (this.current) {
8540 clearColor = clearColor || this.current.baseTexture.clearColor;
8541 }
8542 else {
8543 clearColor = clearColor || this.clearColor;
8544 }
8545 var destinationFrame = this.destinationFrame;
8546 var baseFrame = this.current ? this.current.baseTexture : this.renderer.screen;
8547 var clearMask = destinationFrame.width !== baseFrame.width || destinationFrame.height !== baseFrame.height;
8548 if (clearMask) {
8549 var _a = this.viewportFrame, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
8550 // TODO: ScissorSystem should cache whether the scissor test is enabled or not.
8551 this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST);
8552 this.renderer.gl.scissor(x, y, width, height);
8553 }
8554 this.renderer.framebuffer.clear(clearColor[0], clearColor[1], clearColor[2], clearColor[3], mask);
8555 if (clearMask) {
8556 // Restore the scissor box
8557 this.renderer.scissor.pop();
8558 }
8559 };
8560 RenderTextureSystem.prototype.resize = function () {
8561 // resize the root only!
8562 this.bind(null);
8563 };
8564 /**
8565 * Resets renderTexture state
8566 */
8567 RenderTextureSystem.prototype.reset = function () {
8568 this.bind(null);
8569 };
8570 return RenderTextureSystem;
8571}(System));
8572
8573var IGLUniformData = /** @class */ (function () {
8574 function IGLUniformData() {
8575 }
8576 return IGLUniformData;
8577}());
8578/**
8579 * Helper class to create a WebGL Program
8580 *
8581 * @class
8582 * @memberof PIXI
8583 */
8584var GLProgram = /** @class */ (function () {
8585 /**
8586 * Makes a new Pixi program
8587 *
8588 * @param {WebGLProgram} program - webgl program
8589 * @param {Object} uniformData - uniforms
8590 */
8591 function GLProgram(program, uniformData) {
8592 /**
8593 * The shader program
8594 *
8595 * @member {WebGLProgram}
8596 */
8597 this.program = program;
8598 /**
8599 * holds the uniform data which contains uniform locations
8600 * and current uniform values used for caching and preventing unneeded GPU commands
8601 * @member {Object}
8602 */
8603 this.uniformData = uniformData;
8604 /**
8605 * uniformGroups holds the various upload functions for the shader. Each uniform group
8606 * and program have a unique upload function generated.
8607 * @member {Object}
8608 */
8609 this.uniformGroups = {};
8610 }
8611 /**
8612 * Destroys this program
8613 */
8614 GLProgram.prototype.destroy = function () {
8615 this.uniformData = null;
8616 this.uniformGroups = null;
8617 this.program = null;
8618 };
8619 return GLProgram;
8620}());
8621
8622var UID$4 = 0;
8623// default sync data so we don't create a new one each time!
8624var defaultSyncData = { textureCount: 0 };
8625/**
8626 * System plugin to the renderer to manage shaders.
8627 *
8628 * @class
8629 * @memberof PIXI
8630 * @extends PIXI.System
8631 */
8632var ShaderSystem = /** @class */ (function (_super) {
8633 __extends(ShaderSystem, _super);
8634 /**
8635 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8636 */
8637 function ShaderSystem(renderer) {
8638 var _this = _super.call(this, renderer) || this;
8639 _this.destroyed = false;
8640 // Validation check that this environment support `new Function`
8641 _this.systemCheck();
8642 /**
8643 * The current WebGL rendering context
8644 *
8645 * @member {WebGLRenderingContext}
8646 */
8647 _this.gl = null;
8648 _this.shader = null;
8649 _this.program = null;
8650 /**
8651 * Cache to holds the generated functions. Stored against UniformObjects unique signature
8652 * @type {Object}
8653 * @private
8654 */
8655 _this.cache = {};
8656 _this.id = UID$4++;
8657 return _this;
8658 }
8659 /**
8660 * Overrideable function by `@pixi/unsafe-eval` to silence
8661 * throwing an error if platform doesn't support unsafe-evals.
8662 *
8663 * @private
8664 */
8665 ShaderSystem.prototype.systemCheck = function () {
8666 if (!unsafeEvalSupported()) {
8667 throw new Error('Current environment does not allow unsafe-eval, '
8668 + 'please use @pixi/unsafe-eval module to enable support.');
8669 }
8670 };
8671 ShaderSystem.prototype.contextChange = function (gl) {
8672 this.gl = gl;
8673 this.reset();
8674 };
8675 /**
8676 * Changes the current shader to the one given in parameter
8677 *
8678 * @param {PIXI.Shader} shader - the new shader
8679 * @param {boolean} [dontSync] - false if the shader should automatically sync its uniforms.
8680 * @returns {PIXI.GLProgram} the glProgram that belongs to the shader.
8681 */
8682 ShaderSystem.prototype.bind = function (shader, dontSync) {
8683 shader.uniforms.globals = this.renderer.globalUniforms;
8684 var program = shader.program;
8685 var glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader);
8686 this.shader = shader;
8687 // TODO - some current Pixi plugins bypass this.. so it not safe to use yet..
8688 if (this.program !== program) {
8689 this.program = program;
8690 this.gl.useProgram(glProgram.program);
8691 }
8692 if (!dontSync) {
8693 defaultSyncData.textureCount = 0;
8694 this.syncUniformGroup(shader.uniformGroup, defaultSyncData);
8695 }
8696 return glProgram;
8697 };
8698 /**
8699 * Uploads the uniforms values to the currently bound shader.
8700 *
8701 * @param {object} uniforms - the uniforms values that be applied to the current shader
8702 */
8703 ShaderSystem.prototype.setUniforms = function (uniforms) {
8704 var shader = this.shader.program;
8705 var glProgram = shader.glPrograms[this.renderer.CONTEXT_UID];
8706 shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer);
8707 };
8708 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
8709 /**
8710 *
8711 * syncs uniforms on the group
8712 * @param {*} group - the uniform group to sync
8713 * @param {*} [syncData] - this is data that is passed to the sync function and any nested sync functions
8714 */
8715 ShaderSystem.prototype.syncUniformGroup = function (group, syncData) {
8716 var glProgram = this.getglProgram();
8717 if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) {
8718 glProgram.uniformGroups[group.id] = group.dirtyId;
8719 this.syncUniforms(group, glProgram, syncData);
8720 }
8721 };
8722 /**
8723 * Overrideable by the @pixi/unsafe-eval package to use static
8724 * syncUnforms instead.
8725 *
8726 * @private
8727 */
8728 ShaderSystem.prototype.syncUniforms = function (group, glProgram, syncData) {
8729 var syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group);
8730 syncFunc(glProgram.uniformData, group.uniforms, this.renderer, syncData);
8731 };
8732 /* eslint-enable @typescript-eslint/explicit-module-boundary-types */
8733 ShaderSystem.prototype.createSyncGroups = function (group) {
8734 var id = this.getSignature(group, this.shader.program.uniformData);
8735 if (!this.cache[id]) {
8736 this.cache[id] = generateUniformsSync(group, this.shader.program.uniformData);
8737 }
8738 group.syncUniforms[this.shader.program.id] = this.cache[id];
8739 return group.syncUniforms[this.shader.program.id];
8740 };
8741 /**
8742 * Takes a uniform group and data and generates a unique signature for them.
8743 *
8744 * @param {PIXI.UniformGroup} group - the uniform group to get signature of
8745 * @param {Object} uniformData - uniform information generated by the shader
8746 * @returns {String} Unique signature of the uniform group
8747 * @private
8748 */
8749 ShaderSystem.prototype.getSignature = function (group, uniformData) {
8750 var uniforms = group.uniforms;
8751 var strings = [];
8752 for (var i in uniforms) {
8753 strings.push(i);
8754 if (uniformData[i]) {
8755 strings.push(uniformData[i].type);
8756 }
8757 }
8758 return strings.join('-');
8759 };
8760 /**
8761 * Returns the underlying GLShade rof the currently bound shader.
8762 * This can be handy for when you to have a little more control over the setting of your uniforms.
8763 *
8764 * @return {PIXI.GLProgram} the glProgram for the currently bound Shader for this context
8765 */
8766 ShaderSystem.prototype.getglProgram = function () {
8767 if (this.shader) {
8768 return this.shader.program.glPrograms[this.renderer.CONTEXT_UID];
8769 }
8770 return null;
8771 };
8772 /**
8773 * Generates a glProgram version of the Shader provided.
8774 *
8775 * @private
8776 * @param {PIXI.Shader} shader - the shader that the glProgram will be based on.
8777 * @return {PIXI.GLProgram} A shiny new glProgram!
8778 */
8779 ShaderSystem.prototype.generateShader = function (shader) {
8780 var gl = this.gl;
8781 var program = shader.program;
8782 var attribMap = {};
8783 for (var i in program.attributeData) {
8784 attribMap[i] = program.attributeData[i].location;
8785 }
8786 var shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap);
8787 var uniformData = {};
8788 for (var i in program.uniformData) {
8789 var data = program.uniformData[i];
8790 uniformData[i] = {
8791 location: gl.getUniformLocation(shaderProgram, i),
8792 value: defaultValue(data.type, data.size),
8793 };
8794 }
8795 var glProgram = new GLProgram(shaderProgram, uniformData);
8796 program.glPrograms[this.renderer.CONTEXT_UID] = glProgram;
8797 return glProgram;
8798 };
8799 /**
8800 * Resets ShaderSystem state, does not affect WebGL state
8801 */
8802 ShaderSystem.prototype.reset = function () {
8803 this.program = null;
8804 this.shader = null;
8805 };
8806 /**
8807 * Destroys this System and removes all its textures
8808 */
8809 ShaderSystem.prototype.destroy = function () {
8810 // TODO implement destroy method for ShaderSystem
8811 this.destroyed = true;
8812 };
8813 return ShaderSystem;
8814}(System));
8815
8816/**
8817 * Maps gl blend combinations to WebGL.
8818 *
8819 * @memberof PIXI
8820 * @function mapWebGLBlendModesToPixi
8821 * @private
8822 * @param {WebGLRenderingContext} gl - The rendering context.
8823 * @param {number[][]} [array=[]] - The array to output into.
8824 * @return {number[][]} Mapped modes.
8825 */
8826function mapWebGLBlendModesToPixi(gl, array) {
8827 if (array === void 0) { array = []; }
8828 // TODO - premultiply alpha would be different.
8829 // add a boolean for that!
8830 array[BLEND_MODES.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8831 array[BLEND_MODES.ADD] = [gl.ONE, gl.ONE];
8832 array[BLEND_MODES.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8833 array[BLEND_MODES.SCREEN] = [gl.ONE, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8834 array[BLEND_MODES.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8835 array[BLEND_MODES.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8836 array[BLEND_MODES.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8837 array[BLEND_MODES.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8838 array[BLEND_MODES.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8839 array[BLEND_MODES.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8840 array[BLEND_MODES.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8841 array[BLEND_MODES.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8842 array[BLEND_MODES.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8843 array[BLEND_MODES.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8844 array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8845 array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8846 array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8847 array[BLEND_MODES.NONE] = [0, 0];
8848 // not-premultiplied blend modes
8849 array[BLEND_MODES.NORMAL_NPM] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8850 array[BLEND_MODES.ADD_NPM] = [gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE];
8851 array[BLEND_MODES.SCREEN_NPM] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
8852 // composite operations
8853 array[BLEND_MODES.SRC_IN] = [gl.DST_ALPHA, gl.ZERO];
8854 array[BLEND_MODES.SRC_OUT] = [gl.ONE_MINUS_DST_ALPHA, gl.ZERO];
8855 array[BLEND_MODES.SRC_ATOP] = [gl.DST_ALPHA, gl.ONE_MINUS_SRC_ALPHA];
8856 array[BLEND_MODES.DST_OVER] = [gl.ONE_MINUS_DST_ALPHA, gl.ONE];
8857 array[BLEND_MODES.DST_IN] = [gl.ZERO, gl.SRC_ALPHA];
8858 array[BLEND_MODES.DST_OUT] = [gl.ZERO, gl.ONE_MINUS_SRC_ALPHA];
8859 array[BLEND_MODES.DST_ATOP] = [gl.ONE_MINUS_DST_ALPHA, gl.SRC_ALPHA];
8860 array[BLEND_MODES.XOR] = [gl.ONE_MINUS_DST_ALPHA, gl.ONE_MINUS_SRC_ALPHA];
8861 // SUBTRACT from flash
8862 array[BLEND_MODES.SUBTRACT] = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, gl.FUNC_REVERSE_SUBTRACT, gl.FUNC_ADD];
8863 return array;
8864}
8865
8866var BLEND$1 = 0;
8867var OFFSET$1 = 1;
8868var CULLING$1 = 2;
8869var DEPTH_TEST$1 = 3;
8870var WINDING$1 = 4;
8871var DEPTH_MASK$1 = 5;
8872/**
8873 * System plugin to the renderer to manage WebGL state machines.
8874 *
8875 * @class
8876 * @extends PIXI.System
8877 * @memberof PIXI
8878 */
8879var StateSystem = /** @class */ (function (_super) {
8880 __extends(StateSystem, _super);
8881 /**
8882 * @param {PIXI.Renderer} renderer - The renderer this System works for.
8883 */
8884 function StateSystem(renderer) {
8885 var _this = _super.call(this, renderer) || this;
8886 /**
8887 * GL context
8888 * @member {WebGLRenderingContext}
8889 * @readonly
8890 */
8891 _this.gl = null;
8892 /**
8893 * State ID
8894 * @member {number}
8895 * @readonly
8896 */
8897 _this.stateId = 0;
8898 /**
8899 * Polygon offset
8900 * @member {number}
8901 * @readonly
8902 */
8903 _this.polygonOffset = 0;
8904 /**
8905 * Blend mode
8906 * @member {number}
8907 * @default PIXI.BLEND_MODES.NONE
8908 * @readonly
8909 */
8910 _this.blendMode = BLEND_MODES.NONE;
8911 /**
8912 * Whether current blend equation is different
8913 * @member {boolean}
8914 * @protected
8915 */
8916 _this._blendEq = false;
8917 /**
8918 * Collection of calls
8919 * @member {function[]}
8920 * @readonly
8921 */
8922 _this.map = [];
8923 // map functions for when we set state..
8924 _this.map[BLEND$1] = _this.setBlend;
8925 _this.map[OFFSET$1] = _this.setOffset;
8926 _this.map[CULLING$1] = _this.setCullFace;
8927 _this.map[DEPTH_TEST$1] = _this.setDepthTest;
8928 _this.map[WINDING$1] = _this.setFrontFace;
8929 _this.map[DEPTH_MASK$1] = _this.setDepthMask;
8930 /**
8931 * Collection of check calls
8932 * @member {function[]}
8933 * @readonly
8934 */
8935 _this.checks = [];
8936 /**
8937 * Default WebGL State
8938 * @member {PIXI.State}
8939 * @readonly
8940 */
8941 _this.defaultState = new State();
8942 _this.defaultState.blend = true;
8943 return _this;
8944 }
8945 StateSystem.prototype.contextChange = function (gl) {
8946 this.gl = gl;
8947 this.blendModes = mapWebGLBlendModesToPixi(gl);
8948 this.set(this.defaultState);
8949 this.reset();
8950 };
8951 /**
8952 * Sets the current state
8953 *
8954 * @param {*} state - The state to set.
8955 */
8956 StateSystem.prototype.set = function (state) {
8957 state = state || this.defaultState;
8958 // TODO maybe to an object check? ( this.state === state )?
8959 if (this.stateId !== state.data) {
8960 var diff = this.stateId ^ state.data;
8961 var i = 0;
8962 // order from least to most common
8963 while (diff) {
8964 if (diff & 1) {
8965 // state change!
8966 this.map[i].call(this, !!(state.data & (1 << i)));
8967 }
8968 diff = diff >> 1;
8969 i++;
8970 }
8971 this.stateId = state.data;
8972 }
8973 // based on the above settings we check for specific modes..
8974 // for example if blend is active we check and set the blend modes
8975 // or of polygon offset is active we check the poly depth.
8976 for (var i = 0; i < this.checks.length; i++) {
8977 this.checks[i](this, state);
8978 }
8979 };
8980 /**
8981 * Sets the state, when previous state is unknown
8982 *
8983 * @param {*} state - The state to set
8984 */
8985 StateSystem.prototype.forceState = function (state) {
8986 state = state || this.defaultState;
8987 for (var i = 0; i < this.map.length; i++) {
8988 this.map[i].call(this, !!(state.data & (1 << i)));
8989 }
8990 for (var i = 0; i < this.checks.length; i++) {
8991 this.checks[i](this, state);
8992 }
8993 this.stateId = state.data;
8994 };
8995 /**
8996 * Enables or disabled blending.
8997 *
8998 * @param {boolean} value - Turn on or off webgl blending.
8999 */
9000 StateSystem.prototype.setBlend = function (value) {
9001 this.updateCheck(StateSystem.checkBlendMode, value);
9002 this.gl[value ? 'enable' : 'disable'](this.gl.BLEND);
9003 };
9004 /**
9005 * Enables or disable polygon offset fill
9006 *
9007 * @param {boolean} value - Turn on or off webgl polygon offset testing.
9008 */
9009 StateSystem.prototype.setOffset = function (value) {
9010 this.updateCheck(StateSystem.checkPolygonOffset, value);
9011 this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL);
9012 };
9013 /**
9014 * Sets whether to enable or disable depth test.
9015 *
9016 * @param {boolean} value - Turn on or off webgl depth testing.
9017 */
9018 StateSystem.prototype.setDepthTest = function (value) {
9019 this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST);
9020 };
9021 /**
9022 * Sets whether to enable or disable depth mask.
9023 *
9024 * @param {boolean} value - Turn on or off webgl depth mask.
9025 */
9026 StateSystem.prototype.setDepthMask = function (value) {
9027 this.gl.depthMask(value);
9028 };
9029 /**
9030 * Sets whether to enable or disable cull face.
9031 *
9032 * @param {boolean} value - Turn on or off webgl cull face.
9033 */
9034 StateSystem.prototype.setCullFace = function (value) {
9035 this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE);
9036 };
9037 /**
9038 * Sets the gl front face.
9039 *
9040 * @param {boolean} value - true is clockwise and false is counter-clockwise
9041 */
9042 StateSystem.prototype.setFrontFace = function (value) {
9043 this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']);
9044 };
9045 /**
9046 * Sets the blend mode.
9047 *
9048 * @param {number} value - The blend mode to set to.
9049 */
9050 StateSystem.prototype.setBlendMode = function (value) {
9051 if (value === this.blendMode) {
9052 return;
9053 }
9054 this.blendMode = value;
9055 var mode = this.blendModes[value];
9056 var gl = this.gl;
9057 if (mode.length === 2) {
9058 gl.blendFunc(mode[0], mode[1]);
9059 }
9060 else {
9061 gl.blendFuncSeparate(mode[0], mode[1], mode[2], mode[3]);
9062 }
9063 if (mode.length === 6) {
9064 this._blendEq = true;
9065 gl.blendEquationSeparate(mode[4], mode[5]);
9066 }
9067 else if (this._blendEq) {
9068 this._blendEq = false;
9069 gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
9070 }
9071 };
9072 /**
9073 * Sets the polygon offset.
9074 *
9075 * @param {number} value - the polygon offset
9076 * @param {number} scale - the polygon offset scale
9077 */
9078 StateSystem.prototype.setPolygonOffset = function (value, scale) {
9079 this.gl.polygonOffset(value, scale);
9080 };
9081 // used
9082 /**
9083 * Resets all the logic and disables the vaos
9084 */
9085 StateSystem.prototype.reset = function () {
9086 this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
9087 this.forceState(this.defaultState);
9088 this._blendEq = true;
9089 this.blendMode = -1;
9090 this.setBlendMode(0);
9091 };
9092 /**
9093 * checks to see which updates should be checked based on which settings have been activated.
9094 * For example, if blend is enabled then we should check the blend modes each time the state is changed
9095 * or if polygon fill is activated then we need to check if the polygon offset changes.
9096 * The idea is that we only check what we have too.
9097 *
9098 * @param {Function} func - the checking function to add or remove
9099 * @param {boolean} value - should the check function be added or removed.
9100 */
9101 StateSystem.prototype.updateCheck = function (func, value) {
9102 var index = this.checks.indexOf(func);
9103 if (value && index === -1) {
9104 this.checks.push(func);
9105 }
9106 else if (!value && index !== -1) {
9107 this.checks.splice(index, 1);
9108 }
9109 };
9110 /**
9111 * A private little wrapper function that we call to check the blend mode.
9112 *
9113 * @static
9114 * @private
9115 * @param {PIXI.StateSystem} System - the System to perform the state check on
9116 * @param {PIXI.State} state - the state that the blendMode will pulled from
9117 */
9118 StateSystem.checkBlendMode = function (system, state) {
9119 system.setBlendMode(state.blendMode);
9120 };
9121 /**
9122 * A private little wrapper function that we call to check the polygon offset.
9123 *
9124 * @static
9125 * @private
9126 * @param {PIXI.StateSystem} System - the System to perform the state check on
9127 * @param {PIXI.State} state - the state that the blendMode will pulled from
9128 */
9129 StateSystem.checkPolygonOffset = function (system, state) {
9130 system.setPolygonOffset(1, state.polygonOffset);
9131 };
9132 return StateSystem;
9133}(System));
9134
9135/**
9136 * System plugin to the renderer to manage texture garbage collection on the GPU,
9137 * ensuring that it does not get clogged up with textures that are no longer being used.
9138 *
9139 * @class
9140 * @memberof PIXI
9141 * @extends PIXI.System
9142 */
9143var TextureGCSystem = /** @class */ (function (_super) {
9144 __extends(TextureGCSystem, _super);
9145 /**
9146 * @param {PIXI.Renderer} renderer - The renderer this System works for.
9147 */
9148 function TextureGCSystem(renderer) {
9149 var _this = _super.call(this, renderer) || this;
9150 /**
9151 * Count
9152 * @member {number}
9153 * @readonly
9154 */
9155 _this.count = 0;
9156 /**
9157 * Check count
9158 * @member {number}
9159 * @readonly
9160 */
9161 _this.checkCount = 0;
9162 /**
9163 * Maximum idle time, in seconds
9164 * @member {number}
9165 * @see PIXI.settings.GC_MAX_IDLE
9166 */
9167 _this.maxIdle = settings.GC_MAX_IDLE;
9168 /**
9169 * Maximum number of item to check
9170 * @member {number}
9171 * @see PIXI.settings.GC_MAX_CHECK_COUNT
9172 */
9173 _this.checkCountMax = settings.GC_MAX_CHECK_COUNT;
9174 /**
9175 * Current garbage collection mode
9176 * @member {PIXI.GC_MODES}
9177 * @see PIXI.settings.GC_MODE
9178 */
9179 _this.mode = settings.GC_MODE;
9180 return _this;
9181 }
9182 /**
9183 * Checks to see when the last time a texture was used
9184 * if the texture has not been used for a specified amount of time it will be removed from the GPU
9185 */
9186 TextureGCSystem.prototype.postrender = function () {
9187 if (!this.renderer.renderingToScreen) {
9188 return;
9189 }
9190 this.count++;
9191 if (this.mode === GC_MODES.MANUAL) {
9192 return;
9193 }
9194 this.checkCount++;
9195 if (this.checkCount > this.checkCountMax) {
9196 this.checkCount = 0;
9197 this.run();
9198 }
9199 };
9200 /**
9201 * Checks to see when the last time a texture was used
9202 * if the texture has not been used for a specified amount of time it will be removed from the GPU
9203 */
9204 TextureGCSystem.prototype.run = function () {
9205 var tm = this.renderer.texture;
9206 var managedTextures = tm.managedTextures;
9207 var wasRemoved = false;
9208 for (var i = 0; i < managedTextures.length; i++) {
9209 var texture = managedTextures[i];
9210 // only supports non generated textures at the moment!
9211 if (!texture.framebuffer && this.count - texture.touched > this.maxIdle) {
9212 tm.destroyTexture(texture, true);
9213 managedTextures[i] = null;
9214 wasRemoved = true;
9215 }
9216 }
9217 if (wasRemoved) {
9218 var j = 0;
9219 for (var i = 0; i < managedTextures.length; i++) {
9220 if (managedTextures[i] !== null) {
9221 managedTextures[j++] = managedTextures[i];
9222 }
9223 }
9224 managedTextures.length = j;
9225 }
9226 };
9227 /**
9228 * Removes all the textures within the specified displayObject and its children from the GPU
9229 *
9230 * @param {PIXI.DisplayObject} displayObject - the displayObject to remove the textures from.
9231 */
9232 TextureGCSystem.prototype.unload = function (displayObject) {
9233 var tm = this.renderer.texture;
9234 var texture = displayObject._texture;
9235 // only destroy non generated textures
9236 if (texture && !texture.framebuffer) {
9237 tm.destroyTexture(texture);
9238 }
9239 for (var i = displayObject.children.length - 1; i >= 0; i--) {
9240 this.unload(displayObject.children[i]);
9241 }
9242 };
9243 return TextureGCSystem;
9244}(System));
9245
9246/**
9247 * Internal texture for WebGL context
9248 * @class
9249 * @memberof PIXI
9250 */
9251var GLTexture = /** @class */ (function () {
9252 function GLTexture(texture) {
9253 /**
9254 * The WebGL texture
9255 * @member {WebGLTexture}
9256 */
9257 this.texture = texture;
9258 /**
9259 * Width of texture that was used in texImage2D
9260 * @member {number}
9261 */
9262 this.width = -1;
9263 /**
9264 * Height of texture that was used in texImage2D
9265 * @member {number}
9266 */
9267 this.height = -1;
9268 /**
9269 * Texture contents dirty flag
9270 * @member {number}
9271 */
9272 this.dirtyId = -1;
9273 /**
9274 * Texture style dirty flag
9275 * @member {number}
9276 */
9277 this.dirtyStyleId = -1;
9278 /**
9279 * Whether mip levels has to be generated
9280 * @member {boolean}
9281 */
9282 this.mipmap = false;
9283 /**
9284 * WrapMode copied from baseTexture
9285 * @member {number}
9286 */
9287 this.wrapMode = 33071;
9288 /**
9289 * Type copied from baseTexture
9290 * @member {number}
9291 */
9292 this.type = 6408;
9293 /**
9294 * Type copied from baseTexture
9295 * @member {number}
9296 */
9297 this.internalFormat = 5121;
9298 }
9299 return GLTexture;
9300}());
9301
9302/**
9303 * System plugin to the renderer to manage textures.
9304 *
9305 * @class
9306 * @extends PIXI.System
9307 * @memberof PIXI
9308 */
9309var TextureSystem = /** @class */ (function (_super) {
9310 __extends(TextureSystem, _super);
9311 /**
9312 * @param {PIXI.Renderer} renderer - The renderer this System works for.
9313 */
9314 function TextureSystem(renderer) {
9315 var _this = _super.call(this, renderer) || this;
9316 // TODO set to max textures...
9317 /**
9318 * Bound textures
9319 * @member {PIXI.BaseTexture[]}
9320 * @readonly
9321 */
9322 _this.boundTextures = [];
9323 /**
9324 * Current location
9325 * @member {number}
9326 * @readonly
9327 */
9328 _this.currentLocation = -1;
9329 /**
9330 * List of managed textures
9331 * @member {PIXI.BaseTexture[]}
9332 * @readonly
9333 */
9334 _this.managedTextures = [];
9335 /**
9336 * Did someone temper with textures state? We'll overwrite them when we need to unbind something.
9337 * @member {boolean}
9338 * @private
9339 */
9340 _this._unknownBoundTextures = false;
9341 /**
9342 * BaseTexture value that shows that we don't know what is bound
9343 * @member {PIXI.BaseTexture}
9344 * @readonly
9345 */
9346 _this.unknownTexture = new BaseTexture();
9347 return _this;
9348 }
9349 /**
9350 * Sets up the renderer context and necessary buffers.
9351 */
9352 TextureSystem.prototype.contextChange = function () {
9353 var gl = this.gl = this.renderer.gl;
9354 this.CONTEXT_UID = this.renderer.CONTEXT_UID;
9355 this.webGLVersion = this.renderer.context.webGLVersion;
9356 var maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
9357 this.boundTextures.length = maxTextures;
9358 for (var i = 0; i < maxTextures; i++) {
9359 this.boundTextures[i] = null;
9360 }
9361 // TODO move this.. to a nice make empty textures class..
9362 this.emptyTextures = {};
9363 var emptyTexture2D = new GLTexture(gl.createTexture());
9364 gl.bindTexture(gl.TEXTURE_2D, emptyTexture2D.texture);
9365 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
9366 this.emptyTextures[gl.TEXTURE_2D] = emptyTexture2D;
9367 this.emptyTextures[gl.TEXTURE_CUBE_MAP] = new GLTexture(gl.createTexture());
9368 gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.emptyTextures[gl.TEXTURE_CUBE_MAP].texture);
9369 for (var i = 0; i < 6; i++) {
9370 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
9371 }
9372 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
9373 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
9374 for (var i = 0; i < this.boundTextures.length; i++) {
9375 this.bind(null, i);
9376 }
9377 };
9378 /**
9379 * Bind a texture to a specific location
9380 *
9381 * If you want to unbind something, please use `unbind(texture)` instead of `bind(null, textureLocation)`
9382 *
9383 * @param {PIXI.Texture|PIXI.BaseTexture} texture_ - Texture to bind
9384 * @param {number} [location=0] - Location to bind at
9385 */
9386 TextureSystem.prototype.bind = function (texture, location) {
9387 if (location === void 0) { location = 0; }
9388 var gl = this.gl;
9389 if (texture) {
9390 texture = texture.castToBaseTexture();
9391 if (texture.parentTextureArray) {
9392 // cannot bind partial texture
9393 // TODO: report a warning
9394 return;
9395 }
9396 if (texture.valid) {
9397 texture.touched = this.renderer.textureGC.count;
9398 var glTexture = texture._glTextures[this.CONTEXT_UID] || this.initTexture(texture);
9399 if (this.boundTextures[location] !== texture) {
9400 if (this.currentLocation !== location) {
9401 this.currentLocation = location;
9402 gl.activeTexture(gl.TEXTURE0 + location);
9403 }
9404 gl.bindTexture(texture.target, glTexture.texture);
9405 }
9406 if (glTexture.dirtyId !== texture.dirtyId) {
9407 if (this.currentLocation !== location) {
9408 this.currentLocation = location;
9409 gl.activeTexture(gl.TEXTURE0 + location);
9410 }
9411 this.updateTexture(texture);
9412 }
9413 this.boundTextures[location] = texture;
9414 }
9415 }
9416 else {
9417 if (this.currentLocation !== location) {
9418 this.currentLocation = location;
9419 gl.activeTexture(gl.TEXTURE0 + location);
9420 }
9421 gl.bindTexture(gl.TEXTURE_2D, this.emptyTextures[gl.TEXTURE_2D].texture);
9422 this.boundTextures[location] = null;
9423 }
9424 };
9425 /**
9426 * Resets texture location and bound textures
9427 *
9428 * Actual `bind(null, i)` calls will be performed at next `unbind()` call
9429 */
9430 TextureSystem.prototype.reset = function () {
9431 this._unknownBoundTextures = true;
9432 this.currentLocation = -1;
9433 for (var i = 0; i < this.boundTextures.length; i++) {
9434 this.boundTextures[i] = this.unknownTexture;
9435 }
9436 };
9437 /**
9438 * Unbind a texture
9439 * @param {PIXI.BaseTexture} texture - Texture to bind
9440 */
9441 TextureSystem.prototype.unbind = function (texture) {
9442 var _a = this, gl = _a.gl, boundTextures = _a.boundTextures;
9443 if (this._unknownBoundTextures) {
9444 this._unknownBoundTextures = false;
9445 // someone changed webGL state,
9446 // we have to be sure that our texture does not appear in multi-texture renderer samplers
9447 for (var i = 0; i < boundTextures.length; i++) {
9448 if (boundTextures[i] === this.unknownTexture) {
9449 this.bind(null, i);
9450 }
9451 }
9452 }
9453 for (var i = 0; i < boundTextures.length; i++) {
9454 if (boundTextures[i] === texture) {
9455 if (this.currentLocation !== i) {
9456 gl.activeTexture(gl.TEXTURE0 + i);
9457 this.currentLocation = i;
9458 }
9459 gl.bindTexture(texture.target, this.emptyTextures[texture.target].texture);
9460 boundTextures[i] = null;
9461 }
9462 }
9463 };
9464 /**
9465 * Initialize a texture
9466 *
9467 * @private
9468 * @param {PIXI.BaseTexture} texture - Texture to initialize
9469 */
9470 TextureSystem.prototype.initTexture = function (texture) {
9471 var glTexture = new GLTexture(this.gl.createTexture());
9472 // guarantee an update..
9473 glTexture.dirtyId = -1;
9474 texture._glTextures[this.CONTEXT_UID] = glTexture;
9475 this.managedTextures.push(texture);
9476 texture.on('dispose', this.destroyTexture, this);
9477 return glTexture;
9478 };
9479 TextureSystem.prototype.initTextureType = function (texture, glTexture) {
9480 glTexture.internalFormat = texture.format;
9481 glTexture.type = texture.type;
9482 if (this.webGLVersion !== 2) {
9483 return;
9484 }
9485 var gl = this.renderer.gl;
9486 if (texture.type === gl.FLOAT
9487 && texture.format === gl.RGBA) {
9488 glTexture.internalFormat = gl.RGBA32F;
9489 }
9490 // that's WebGL1 HALF_FLOAT_OES
9491 // we have to convert it to WebGL HALF_FLOAT
9492 if (texture.type === TYPES.HALF_FLOAT) {
9493 glTexture.type = gl.HALF_FLOAT;
9494 }
9495 if (glTexture.type === gl.HALF_FLOAT
9496 && texture.format === gl.RGBA) {
9497 glTexture.internalFormat = gl.RGBA16F;
9498 }
9499 };
9500 /**
9501 * Update a texture
9502 *
9503 * @private
9504 * @param {PIXI.BaseTexture} texture - Texture to initialize
9505 */
9506 TextureSystem.prototype.updateTexture = function (texture) {
9507 var glTexture = texture._glTextures[this.CONTEXT_UID];
9508 if (!glTexture) {
9509 return;
9510 }
9511 var renderer = this.renderer;
9512 this.initTextureType(texture, glTexture);
9513 if (texture.resource && texture.resource.upload(renderer, texture, glTexture)) ;
9514 else {
9515 // default, renderTexture-like logic
9516 var width = texture.realWidth;
9517 var height = texture.realHeight;
9518 var gl = renderer.gl;
9519 if (glTexture.width !== width
9520 || glTexture.height !== height
9521 || glTexture.dirtyId < 0) {
9522 glTexture.width = width;
9523 glTexture.height = height;
9524 gl.texImage2D(texture.target, 0, glTexture.internalFormat, width, height, 0, texture.format, glTexture.type, null);
9525 }
9526 }
9527 // lets only update what changes..
9528 if (texture.dirtyStyleId !== glTexture.dirtyStyleId) {
9529 this.updateTextureStyle(texture);
9530 }
9531 glTexture.dirtyId = texture.dirtyId;
9532 };
9533 /**
9534 * Deletes the texture from WebGL
9535 *
9536 * @private
9537 * @param {PIXI.BaseTexture|PIXI.Texture} texture_ - the texture to destroy
9538 * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager.
9539 */
9540 TextureSystem.prototype.destroyTexture = function (texture, skipRemove) {
9541 var gl = this.gl;
9542 texture = texture.castToBaseTexture();
9543 if (texture._glTextures[this.CONTEXT_UID]) {
9544 this.unbind(texture);
9545 gl.deleteTexture(texture._glTextures[this.CONTEXT_UID].texture);
9546 texture.off('dispose', this.destroyTexture, this);
9547 delete texture._glTextures[this.CONTEXT_UID];
9548 if (!skipRemove) {
9549 var i = this.managedTextures.indexOf(texture);
9550 if (i !== -1) {
9551 removeItems(this.managedTextures, i, 1);
9552 }
9553 }
9554 }
9555 };
9556 /**
9557 * Update texture style such as mipmap flag
9558 *
9559 * @private
9560 * @param {PIXI.BaseTexture} texture - Texture to update
9561 */
9562 TextureSystem.prototype.updateTextureStyle = function (texture) {
9563 var glTexture = texture._glTextures[this.CONTEXT_UID];
9564 if (!glTexture) {
9565 return;
9566 }
9567 if ((texture.mipmap === MIPMAP_MODES.POW2 || this.webGLVersion !== 2) && !texture.isPowerOfTwo) {
9568 glTexture.mipmap = false;
9569 }
9570 else {
9571 glTexture.mipmap = texture.mipmap >= 1;
9572 }
9573 if (this.webGLVersion !== 2 && !texture.isPowerOfTwo) {
9574 glTexture.wrapMode = WRAP_MODES.CLAMP;
9575 }
9576 else {
9577 glTexture.wrapMode = texture.wrapMode;
9578 }
9579 if (texture.resource && texture.resource.style(this.renderer, texture, glTexture)) ;
9580 else {
9581 this.setStyle(texture, glTexture);
9582 }
9583 glTexture.dirtyStyleId = texture.dirtyStyleId;
9584 };
9585 /**
9586 * Set style for texture
9587 *
9588 * @private
9589 * @param {PIXI.BaseTexture} texture - Texture to update
9590 * @param {PIXI.GLTexture} glTexture
9591 */
9592 TextureSystem.prototype.setStyle = function (texture, glTexture) {
9593 var gl = this.gl;
9594 if (glTexture.mipmap && texture.mipmap !== MIPMAP_MODES.ON_MANUAL) {
9595 gl.generateMipmap(texture.target);
9596 }
9597 gl.texParameteri(texture.target, gl.TEXTURE_WRAP_S, glTexture.wrapMode);
9598 gl.texParameteri(texture.target, gl.TEXTURE_WRAP_T, glTexture.wrapMode);
9599 if (glTexture.mipmap) {
9600 /* eslint-disable max-len */
9601 gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);
9602 /* eslint-disable max-len */
9603 var anisotropicExt = this.renderer.context.extensions.anisotropicFiltering;
9604 if (anisotropicExt && texture.anisotropicLevel > 0 && texture.scaleMode === SCALE_MODES.LINEAR) {
9605 var level = Math.min(texture.anisotropicLevel, gl.getParameter(anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT));
9606 gl.texParameterf(texture.target, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, level);
9607 }
9608 }
9609 else {
9610 gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
9611 }
9612 gl.texParameteri(texture.target, gl.TEXTURE_MAG_FILTER, texture.scaleMode === SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
9613 };
9614 return TextureSystem;
9615}(System));
9616
9617
9618
9619var _systems = {
9620 __proto__: null,
9621 FilterSystem: FilterSystem,
9622 BatchSystem: BatchSystem,
9623 ContextSystem: ContextSystem,
9624 FramebufferSystem: FramebufferSystem,
9625 GeometrySystem: GeometrySystem,
9626 MaskSystem: MaskSystem,
9627 ScissorSystem: ScissorSystem,
9628 StencilSystem: StencilSystem,
9629 ProjectionSystem: ProjectionSystem,
9630 RenderTextureSystem: RenderTextureSystem,
9631 ShaderSystem: ShaderSystem,
9632 StateSystem: StateSystem,
9633 TextureGCSystem: TextureGCSystem,
9634 TextureSystem: TextureSystem
9635};
9636
9637var tempMatrix$1 = new Matrix();
9638/**
9639 * The AbstractRenderer is the base for a PixiJS Renderer. It is extended by the {@link PIXI.CanvasRenderer}
9640 * and {@link PIXI.Renderer} which can be used for rendering a PixiJS scene.
9641 *
9642 * @abstract
9643 * @class
9644 * @extends PIXI.utils.EventEmitter
9645 * @memberof PIXI
9646 */
9647var AbstractRenderer = /** @class */ (function (_super) {
9648 __extends(AbstractRenderer, _super);
9649 /**
9650 * @param system - The name of the system this renderer is for.
9651 * @param [options] - The optional renderer parameters.
9652 * @param {number} [options.width=800] - The width of the screen.
9653 * @param {number} [options.height=600] - The height of the screen.
9654 * @param {HTMLCanvasElement} [options.view] - The canvas to use as a view, optional.
9655 * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property.
9656 * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the
9657 * canvas needs to be opaque, possibly for performance reasons on some older devices.
9658 * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for
9659 * resolutions other than 1.
9660 * @param {boolean} [options.antialias=false] - Sets antialias
9661 * @param {number} [options.resolution=1] - The resolution / device pixel ratio of the renderer. The
9662 * resolution of the renderer retina would be 2.
9663 * @param {boolean} [options.preserveDrawingBuffer=false] - Enables drawing buffer preservation,
9664 * enable this if you need to call toDataUrl on the WebGL context.
9665 * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or
9666 * not before the new render pass.
9667 * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area
9668 * (shown if not transparent).
9669 * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque).
9670 */
9671 function AbstractRenderer(type, options) {
9672 if (type === void 0) { type = RENDERER_TYPE.UNKNOWN; }
9673 var _this = _super.call(this) || this;
9674 // Add the default render options
9675 options = Object.assign({}, settings.RENDER_OPTIONS, options);
9676 /**
9677 * The supplied constructor options.
9678 *
9679 * @member {Object}
9680 * @readOnly
9681 */
9682 _this.options = options;
9683 /**
9684 * The type of the renderer.
9685 *
9686 * @member {number}
9687 * @default PIXI.RENDERER_TYPE.UNKNOWN
9688 * @see PIXI.RENDERER_TYPE
9689 */
9690 _this.type = type;
9691 /**
9692 * Measurements of the screen. (0, 0, screenWidth, screenHeight).
9693 *
9694 * Its safe to use as filterArea or hitArea for the whole stage.
9695 *
9696 * @member {PIXI.Rectangle}
9697 */
9698 _this.screen = new Rectangle(0, 0, options.width, options.height);
9699 /**
9700 * The canvas element that everything is drawn to.
9701 *
9702 * @member {HTMLCanvasElement}
9703 */
9704 _this.view = options.view || document.createElement('canvas');
9705 /**
9706 * The resolution / device pixel ratio of the renderer.
9707 *
9708 * @member {number}
9709 * @default 1
9710 */
9711 _this.resolution = options.resolution || settings.RESOLUTION;
9712 /**
9713 * Pass-thru setting for the the canvas' context `alpha` property. This is typically
9714 * not something you need to fiddle with. If you want transparency, use `backgroundAlpha`.
9715 *
9716 * @member {boolean}
9717 */
9718 _this.useContextAlpha = options.useContextAlpha;
9719 /**
9720 * Whether CSS dimensions of canvas view should be resized to screen dimensions automatically.
9721 *
9722 * @member {boolean}
9723 */
9724 _this.autoDensity = !!options.autoDensity;
9725 /**
9726 * The value of the preserveDrawingBuffer flag affects whether or not the contents of
9727 * the stencil buffer is retained after rendering.
9728 *
9729 * @member {boolean}
9730 */
9731 _this.preserveDrawingBuffer = options.preserveDrawingBuffer;
9732 /**
9733 * This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
9734 * If the scene is NOT transparent PixiJS will use a canvas sized fillRect operation every
9735 * frame to set the canvas background color. If the scene is transparent PixiJS will use clearRect
9736 * to clear the canvas every frame. Disable this by setting this to false. For example, if
9737 * your game has a canvas filling background image you often don't need this set.
9738 *
9739 * @member {boolean}
9740 * @default
9741 */
9742 _this.clearBeforeRender = options.clearBeforeRender;
9743 /**
9744 * The background color as a number.
9745 *
9746 * @member {number}
9747 * @protected
9748 */
9749 _this._backgroundColor = 0x000000;
9750 /**
9751 * The background color as an [R, G, B, A] array.
9752 *
9753 * @member {number[]}
9754 * @protected
9755 */
9756 _this._backgroundColorRgba = [0, 0, 0, 1];
9757 /**
9758 * The background color as a string.
9759 *
9760 * @member {string}
9761 * @protected
9762 */
9763 _this._backgroundColorString = '#000000';
9764 _this.backgroundColor = options.backgroundColor || _this._backgroundColor; // run bg color setter
9765 _this.backgroundAlpha = options.backgroundAlpha;
9766 // @deprecated
9767 if (options.transparent !== undefined) {
9768 deprecation('6.0.0', 'Option transparent is deprecated, please use backgroundAlpha instead.');
9769 _this.useContextAlpha = options.transparent;
9770 _this.backgroundAlpha = options.transparent ? 0 : 1;
9771 }
9772 /**
9773 * The last root object that the renderer tried to render.
9774 *
9775 * @member {PIXI.DisplayObject}
9776 * @protected
9777 */
9778 _this._lastObjectRendered = null;
9779 /**
9780 * Collection of plugins.
9781 * @readonly
9782 * @member {object}
9783 */
9784 _this.plugins = {};
9785 return _this;
9786 }
9787 /**
9788 * Initialize the plugins.
9789 *
9790 * @protected
9791 * @param {object} staticMap - The dictionary of statically saved plugins.
9792 */
9793 AbstractRenderer.prototype.initPlugins = function (staticMap) {
9794 for (var o in staticMap) {
9795 this.plugins[o] = new (staticMap[o])(this);
9796 }
9797 };
9798 Object.defineProperty(AbstractRenderer.prototype, "width", {
9799 /**
9800 * Same as view.width, actual number of pixels in the canvas by horizontal.
9801 *
9802 * @member {number}
9803 * @readonly
9804 * @default 800
9805 */
9806 get: function () {
9807 return this.view.width;
9808 },
9809 enumerable: false,
9810 configurable: true
9811 });
9812 Object.defineProperty(AbstractRenderer.prototype, "height", {
9813 /**
9814 * Same as view.height, actual number of pixels in the canvas by vertical.
9815 *
9816 * @member {number}
9817 * @readonly
9818 * @default 600
9819 */
9820 get: function () {
9821 return this.view.height;
9822 },
9823 enumerable: false,
9824 configurable: true
9825 });
9826 /**
9827 * Resizes the screen and canvas to the specified width and height.
9828 * Canvas dimensions are multiplied by resolution.
9829 *
9830 * @param screenWidth - The new width of the screen.
9831 * @param screenHeight - The new height of the screen.
9832 */
9833 AbstractRenderer.prototype.resize = function (screenWidth, screenHeight) {
9834 this.screen.width = screenWidth;
9835 this.screen.height = screenHeight;
9836 this.view.width = screenWidth * this.resolution;
9837 this.view.height = screenHeight * this.resolution;
9838 if (this.autoDensity) {
9839 this.view.style.width = screenWidth + "px";
9840 this.view.style.height = screenHeight + "px";
9841 }
9842 /**
9843 * Fired after view has been resized.
9844 *
9845 * @event PIXI.Renderer#resize
9846 * @param {number} screenWidth - The new width of the screen.
9847 * @param {number} screenHeight - The new height of the screen.
9848 */
9849 this.emit('resize', screenWidth, screenHeight);
9850 };
9851 /**
9852 * Useful function that returns a texture of the display object that can then be used to create sprites
9853 * This can be quite useful if your displayObject is complicated and needs to be reused multiple times.
9854 *
9855 * @param displayObject - The displayObject the object will be generated from.
9856 * @param scaleMode - The scale mode of the texture.
9857 * @param resolution - The resolution / device pixel ratio of the texture being generated.
9858 * @param [region] - The region of the displayObject, that shall be rendered,
9859 * if no region is specified, defaults to the local bounds of the displayObject.
9860 * @return A texture of the graphics object.
9861 */
9862 AbstractRenderer.prototype.generateTexture = function (displayObject, scaleMode, resolution, region) {
9863 region = region || displayObject.getLocalBounds(null, true);
9864 // minimum texture size is 1x1, 0x0 will throw an error
9865 if (region.width === 0)
9866 { region.width = 1; }
9867 if (region.height === 0)
9868 { region.height = 1; }
9869 var renderTexture = RenderTexture.create({
9870 width: region.width | 0,
9871 height: region.height | 0,
9872 scaleMode: scaleMode,
9873 resolution: resolution,
9874 });
9875 tempMatrix$1.tx = -region.x;
9876 tempMatrix$1.ty = -region.y;
9877 this.render(displayObject, {
9878 renderTexture: renderTexture,
9879 clear: false,
9880 transform: tempMatrix$1,
9881 skipUpdateTransform: !!displayObject.parent
9882 });
9883 return renderTexture;
9884 };
9885 /**
9886 * Removes everything from the renderer and optionally removes the Canvas DOM element.
9887 *
9888 * @param [removeView=false] - Removes the Canvas element from the DOM.
9889 */
9890 AbstractRenderer.prototype.destroy = function (removeView) {
9891 for (var o in this.plugins) {
9892 this.plugins[o].destroy();
9893 this.plugins[o] = null;
9894 }
9895 if (removeView && this.view.parentNode) {
9896 this.view.parentNode.removeChild(this.view);
9897 }
9898 var thisAny = this;
9899 // null-ing all objects, that's a tradition!
9900 thisAny.plugins = null;
9901 thisAny.type = RENDERER_TYPE.UNKNOWN;
9902 thisAny.view = null;
9903 thisAny.screen = null;
9904 thisAny._tempDisplayObjectParent = null;
9905 thisAny.options = null;
9906 this._backgroundColorRgba = null;
9907 this._backgroundColorString = null;
9908 this._lastObjectRendered = null;
9909 };
9910 Object.defineProperty(AbstractRenderer.prototype, "backgroundColor", {
9911 /**
9912 * The background color to fill if not transparent
9913 *
9914 * @member {number}
9915 */
9916 get: function () {
9917 return this._backgroundColor;
9918 },
9919 set: function (value) {
9920 this._backgroundColor = value;
9921 this._backgroundColorString = hex2string(value);
9922 hex2rgb(value, this._backgroundColorRgba);
9923 },
9924 enumerable: false,
9925 configurable: true
9926 });
9927 Object.defineProperty(AbstractRenderer.prototype, "backgroundAlpha", {
9928 /**
9929 * The background color alpha. Setting this to 0 will make the canvas transparent.
9930 *
9931 * @member {number}
9932 */
9933 get: function () {
9934 return this._backgroundColorRgba[3];
9935 },
9936 set: function (value) {
9937 this._backgroundColorRgba[3] = value;
9938 },
9939 enumerable: false,
9940 configurable: true
9941 });
9942 return AbstractRenderer;
9943}(EventEmitter));
9944
9945/**
9946 * The Renderer draws the scene and all its content onto a WebGL enabled canvas.
9947 *
9948 * This renderer should be used for browsers that support WebGL.
9949 *
9950 * This renderer works by automatically managing WebGLBatchesm, so no need for Sprite Batches or Sprite Clouds.
9951 * Don't forget to add the view to your DOM or you will not see anything!
9952 *
9953 * Renderer is composed of systems that manage specific tasks. The following systems are added by default
9954 * whenever you create a renderer:
9955 *
9956 * | System | Description |
9957 * | ------------------------------------ | ----------------------------------------------------------------------------- |
9958 * | {@link PIXI.BatchSystem} | This manages object renderers that defer rendering until a flush. |
9959 * | {@link PIXI.ContextSystem} | This manages the WebGL context and extensions. |
9960 * | {@link PIXI.FilterSystem} | This manages the filtering pipeline for post-processing effects. |
9961 * | {@link PIXI.FramebufferSystem} | This manages framebuffers, which are used for offscreen rendering. |
9962 * | {@link PIXI.GeometrySystem} | This manages geometries & buffers, which are used to draw object meshes. |
9963 * | {@link PIXI.MaskSystem} | This manages masking operations. |
9964 * | {@link PIXI.ProjectionSystem} | This manages the `projectionMatrix`, used by shaders to get NDC coordinates. |
9965 * | {@link PIXI.RenderTextureSystem} | This manages render-textures, which are an abstraction over framebuffers. |
9966 * | {@link PIXI.ScissorSystem} | This handles scissor masking, and is used internally by {@link MaskSystem} |
9967 * | {@link PIXI.ShaderSystem} | This manages shaders, programs that run on the GPU to calculate 'em pixels. |
9968 * | {@link PIXI.StateSystem} | This manages the WebGL state variables like blend mode, depth testing, etc. |
9969 * | {@link PIXI.StencilSystem} | This handles stencil masking, and is used internally by {@link MaskSystem} |
9970 * | {@link PIXI.TextureSystem} | This manages textures and their resources on the GPU. |
9971 * | {@link PIXI.TextureGCSystem} | This will automatically remove textures from the GPU if they are not used. |
9972 *
9973 * The breadth of the API surface provided by the renderer is contained within these systems.
9974 *
9975 * @class
9976 * @memberof PIXI
9977 * @extends PIXI.AbstractRenderer
9978 */
9979var Renderer = /** @class */ (function (_super) {
9980 __extends(Renderer, _super);
9981 /**
9982 * @param [options] - The optional renderer parameters.
9983 * @param {number} [options.width=800] - The width of the screen.
9984 * @param {number} [options.height=600] - The height of the screen.
9985 * @param {HTMLCanvasElement} [options.view] - The canvas to use as a view, optional.
9986 * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property.
9987 * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the
9988 * canvas needs to be opaque, possibly for performance reasons on some older devices.
9989 * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for
9990 * resolutions other than 1.
9991 * @param {boolean} [options.antialias=false] - Sets antialias. If not available natively then FXAA
9992 * antialiasing is used.
9993 * @param {number} [options.resolution=1] - The resolution / device pixel ratio of the renderer.
9994 * The resolution of the renderer retina would be 2.
9995 * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear
9996 * the canvas or not before the new render pass. If you wish to set this to false, you *must* set
9997 * preserveDrawingBuffer to `true`.
9998 * @param {boolean} [options.preserveDrawingBuffer=false] - Enables drawing buffer preservation,
9999 * enable this if you need to call toDataUrl on the WebGL context.
10000 * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area
10001 * (shown if not transparent).
10002 * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque).
10003 * @param {string} [options.powerPreference] - Parameter passed to WebGL context, set to "high-performance"
10004 * for devices with dual graphics card.
10005 * @param {object} [options.context] - If WebGL context already exists, all parameters must be taken from it.
10006 * @public
10007 */
10008 function Renderer(options) {
10009 var _this = _super.call(this, RENDERER_TYPE.WEBGL, options) || this;
10010 // the options will have been modified here in the super constructor with pixi's default settings..
10011 options = _this.options;
10012 /**
10013 * WebGL context, set by the contextSystem (this.context)
10014 *
10015 * @readonly
10016 * @member {WebGLRenderingContext}
10017 */
10018 _this.gl = null;
10019 _this.CONTEXT_UID = 0;
10020 /**
10021 * Internal signal instances of **runner**, these
10022 * are assigned to each system created.
10023 * @see PIXI.Runner
10024 * @name runners
10025 * @private
10026 * @type {object}
10027 * @readonly
10028 * @property {PIXI.Runner} destroy - Destroy runner
10029 * @property {PIXI.Runner} contextChange - Context change runner
10030 * @property {PIXI.Runner} reset - Reset runner
10031 * @property {PIXI.Runner} update - Update runner
10032 * @property {PIXI.Runner} postrender - Post-render runner
10033 * @property {PIXI.Runner} prerender - Pre-render runner
10034 * @property {PIXI.Runner} resize - Resize runner
10035 */
10036 _this.runners = {
10037 destroy: new Runner('destroy'),
10038 contextChange: new Runner('contextChange'),
10039 reset: new Runner('reset'),
10040 update: new Runner('update'),
10041 postrender: new Runner('postrender'),
10042 prerender: new Runner('prerender'),
10043 resize: new Runner('resize'),
10044 };
10045 /**
10046 * Global uniforms
10047 * @member {PIXI.UniformGroup}
10048 */
10049 _this.globalUniforms = new UniformGroup({
10050 projectionMatrix: new Matrix(),
10051 }, true);
10052 /**
10053 * Mask system instance
10054 * @member {PIXI.MaskSystem} mask
10055 * @memberof PIXI.Renderer#
10056 * @readonly
10057 */
10058 _this.addSystem(MaskSystem, 'mask')
10059 /**
10060 * Context system instance
10061 * @member {PIXI.ContextSystem} context
10062 * @memberof PIXI.Renderer#
10063 * @readonly
10064 */
10065 .addSystem(ContextSystem, 'context')
10066 /**
10067 * State system instance
10068 * @member {PIXI.StateSystem} state
10069 * @memberof PIXI.Renderer#
10070 * @readonly
10071 */
10072 .addSystem(StateSystem, 'state')
10073 /**
10074 * Shader system instance
10075 * @member {PIXI.ShaderSystem} shader
10076 * @memberof PIXI.Renderer#
10077 * @readonly
10078 */
10079 .addSystem(ShaderSystem, 'shader')
10080 /**
10081 * Texture system instance
10082 * @member {PIXI.TextureSystem} texture
10083 * @memberof PIXI.Renderer#
10084 * @readonly
10085 */
10086 .addSystem(TextureSystem, 'texture')
10087 /**
10088 * Geometry system instance
10089 * @member {PIXI.GeometrySystem} geometry
10090 * @memberof PIXI.Renderer#
10091 * @readonly
10092 */
10093 .addSystem(GeometrySystem, 'geometry')
10094 /**
10095 * Framebuffer system instance
10096 * @member {PIXI.FramebufferSystem} framebuffer
10097 * @memberof PIXI.Renderer#
10098 * @readonly
10099 */
10100 .addSystem(FramebufferSystem, 'framebuffer')
10101 /**
10102 * Scissor system instance
10103 * @member {PIXI.ScissorSystem} scissor
10104 * @memberof PIXI.Renderer#
10105 * @readonly
10106 */
10107 .addSystem(ScissorSystem, 'scissor')
10108 /**
10109 * Stencil system instance
10110 * @member {PIXI.StencilSystem} stencil
10111 * @memberof PIXI.Renderer#
10112 * @readonly
10113 */
10114 .addSystem(StencilSystem, 'stencil')
10115 /**
10116 * Projection system instance
10117 * @member {PIXI.ProjectionSystem} projection
10118 * @memberof PIXI.Renderer#
10119 * @readonly
10120 */
10121 .addSystem(ProjectionSystem, 'projection')
10122 /**
10123 * Texture garbage collector system instance
10124 * @member {PIXI.TextureGCSystem} textureGC
10125 * @memberof PIXI.Renderer#
10126 * @readonly
10127 */
10128 .addSystem(TextureGCSystem, 'textureGC')
10129 /**
10130 * Filter system instance
10131 * @member {PIXI.FilterSystem} filter
10132 * @memberof PIXI.Renderer#
10133 * @readonly
10134 */
10135 .addSystem(FilterSystem, 'filter')
10136 /**
10137 * RenderTexture system instance
10138 * @member {PIXI.RenderTextureSystem} renderTexture
10139 * @memberof PIXI.Renderer#
10140 * @readonly
10141 */
10142 .addSystem(RenderTextureSystem, 'renderTexture')
10143 /**
10144 * Batch system instance
10145 * @member {PIXI.BatchSystem} batch
10146 * @memberof PIXI.Renderer#
10147 * @readonly
10148 */
10149 .addSystem(BatchSystem, 'batch');
10150 _this.initPlugins(Renderer.__plugins);
10151 /*
10152 * The options passed in to create a new WebGL context.
10153 */
10154 if (options.context) {
10155 _this.context.initFromContext(options.context);
10156 }
10157 else {
10158 _this.context.initFromOptions({
10159 alpha: !!_this.useContextAlpha,
10160 antialias: options.antialias,
10161 premultipliedAlpha: _this.useContextAlpha && _this.useContextAlpha !== 'notMultiplied',
10162 stencil: true,
10163 preserveDrawingBuffer: options.preserveDrawingBuffer,
10164 powerPreference: _this.options.powerPreference,
10165 });
10166 }
10167 /**
10168 * Flag if we are rendering to the screen vs renderTexture
10169 * @member {boolean}
10170 * @readonly
10171 * @default true
10172 */
10173 _this.renderingToScreen = true;
10174 sayHello(_this.context.webGLVersion === 2 ? 'WebGL 2' : 'WebGL 1');
10175 _this.resize(_this.options.width, _this.options.height);
10176 return _this;
10177 }
10178 /**
10179 * Create renderer if WebGL is available. Overrideable
10180 * by the **@pixi/canvas-renderer** package to allow fallback.
10181 * throws error if WebGL is not available.
10182 * @static
10183 * @private
10184 */
10185 Renderer.create = function (options) {
10186 if (isWebGLSupported()) {
10187 return new Renderer(options);
10188 }
10189 throw new Error('WebGL unsupported in this browser, use "pixi.js-legacy" for fallback canvas2d support.');
10190 };
10191 /**
10192 * Add a new system to the renderer.
10193 * @param ClassRef - Class reference
10194 * @param [name] - Property name for system, if not specified
10195 * will use a static `name` property on the class itself. This
10196 * name will be assigned as s property on the Renderer so make
10197 * sure it doesn't collide with properties on Renderer.
10198 * @return {PIXI.Renderer} Return instance of renderer
10199 */
10200 Renderer.prototype.addSystem = function (ClassRef, name) {
10201 if (!name) {
10202 name = ClassRef.name;
10203 }
10204 var system = new ClassRef(this);
10205 if (this[name]) {
10206 throw new Error("Whoops! The name \"" + name + "\" is already in use");
10207 }
10208 this[name] = system;
10209 for (var i in this.runners) {
10210 this.runners[i].add(system);
10211 }
10212 /**
10213 * Fired after rendering finishes.
10214 *
10215 * @event PIXI.Renderer#postrender
10216 */
10217 /**
10218 * Fired before rendering starts.
10219 *
10220 * @event PIXI.Renderer#prerender
10221 */
10222 /**
10223 * Fired when the WebGL context is set.
10224 *
10225 * @event PIXI.Renderer#context
10226 * @param {WebGLRenderingContext} gl - WebGL context.
10227 */
10228 return this;
10229 };
10230 /**
10231 * @ignore
10232 */
10233 Renderer.prototype.render = function (displayObject, options) {
10234 var renderTexture;
10235 var clear;
10236 var transform;
10237 var skipUpdateTransform;
10238 if (options) {
10239 if (options instanceof RenderTexture) {
10240 deprecation('6.0.0', 'Renderer#render arguments changed, use options instead.');
10241 /* eslint-disable prefer-rest-params */
10242 renderTexture = options;
10243 clear = arguments[2];
10244 transform = arguments[3];
10245 skipUpdateTransform = arguments[4];
10246 /* eslint-enable prefer-rest-params */
10247 }
10248 else {
10249 renderTexture = options.renderTexture;
10250 clear = options.clear;
10251 transform = options.transform;
10252 skipUpdateTransform = options.skipUpdateTransform;
10253 }
10254 }
10255 // can be handy to know!
10256 this.renderingToScreen = !renderTexture;
10257 this.runners.prerender.emit();
10258 this.emit('prerender');
10259 // apply a transform at a GPU level
10260 this.projection.transform = transform;
10261 // no point rendering if our context has been blown up!
10262 if (this.context.isLost) {
10263 return;
10264 }
10265 if (!renderTexture) {
10266 this._lastObjectRendered = displayObject;
10267 }
10268 if (!skipUpdateTransform) {
10269 // update the scene graph
10270 var cacheParent = displayObject.enableTempParent();
10271 displayObject.updateTransform();
10272 displayObject.disableTempParent(cacheParent);
10273 // displayObject.hitArea = //TODO add a temp hit area
10274 }
10275 this.renderTexture.bind(renderTexture);
10276 this.batch.currentRenderer.start();
10277 if (clear !== undefined ? clear : this.clearBeforeRender) {
10278 this.renderTexture.clear();
10279 }
10280 displayObject.render(this);
10281 // apply transform..
10282 this.batch.currentRenderer.flush();
10283 if (renderTexture) {
10284 renderTexture.baseTexture.update();
10285 }
10286 this.runners.postrender.emit();
10287 // reset transform after render
10288 this.projection.transform = null;
10289 this.emit('postrender');
10290 };
10291 /**
10292 * Resizes the WebGL view to the specified width and height.
10293 *
10294 * @param screenWidth - The new width of the screen.
10295 * @param screenHeight - The new height of the screen.
10296 */
10297 Renderer.prototype.resize = function (screenWidth, screenHeight) {
10298 _super.prototype.resize.call(this, screenWidth, screenHeight);
10299 this.runners.resize.emit(screenWidth, screenHeight);
10300 };
10301 /**
10302 * Resets the WebGL state so you can render things however you fancy!
10303 *
10304 * @return {PIXI.Renderer} Returns itself.
10305 */
10306 Renderer.prototype.reset = function () {
10307 this.runners.reset.emit();
10308 return this;
10309 };
10310 /**
10311 * Clear the frame buffer
10312 */
10313 Renderer.prototype.clear = function () {
10314 this.renderTexture.bind();
10315 this.renderTexture.clear();
10316 };
10317 /**
10318 * Removes everything from the renderer (event listeners, spritebatch, etc...)
10319 *
10320 * @param [removeView=false] - Removes the Canvas element from the DOM.
10321 * See: https://github.com/pixijs/pixi.js/issues/2233
10322 */
10323 Renderer.prototype.destroy = function (removeView) {
10324 this.runners.destroy.emit();
10325 for (var r in this.runners) {
10326 this.runners[r].destroy();
10327 }
10328 // call base destroy
10329 _super.prototype.destroy.call(this, removeView);
10330 // TODO nullify all the managers..
10331 this.gl = null;
10332 };
10333 Object.defineProperty(Renderer.prototype, "extract", {
10334 /**
10335 * Please use `plugins.extract` instead.
10336 * @member {PIXI.Extract} extract
10337 * @deprecated since 6.0.0
10338 * @readonly
10339 */
10340 get: function () {
10341 deprecation('6.0.0', 'Renderer#extract has been deprecated, please use Renderer#plugins.extract instead.');
10342 return this.plugins.extract;
10343 },
10344 enumerable: false,
10345 configurable: true
10346 });
10347 /**
10348 * Adds a plugin to the renderer.
10349 *
10350 * @method
10351 * @param pluginName - The name of the plugin.
10352 * @param ctor - The constructor function or class for the plugin.
10353 */
10354 Renderer.registerPlugin = function (pluginName, ctor) {
10355 Renderer.__plugins = Renderer.__plugins || {};
10356 Renderer.__plugins[pluginName] = ctor;
10357 };
10358 return Renderer;
10359}(AbstractRenderer));
10360
10361/**
10362 * This helper function will automatically detect which renderer you should be using.
10363 * WebGL is the preferred renderer as it is a lot faster. If WebGL is not supported by
10364 * the browser then this function will return a canvas renderer
10365 *
10366 * @memberof PIXI
10367 * @function autoDetectRenderer
10368 * @param {object} [options] - The optional renderer parameters
10369 * @param {number} [options.width=800] - the width of the renderers view
10370 * @param {number} [options.height=600] - the height of the renderers view
10371 * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional
10372 * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property.
10373 * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the
10374 * canvas needs to be opaque, possibly for performance reasons on some older devices.
10375 * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for
10376 * resolutions other than 1
10377 * @param {boolean} [options.antialias=false] - sets antialias
10378 * @param {boolean} [options.preserveDrawingBuffer=false] - enables drawing buffer preservation, enable this if you
10379 * need to call toDataUrl on the webgl context
10380 * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area
10381 * (shown if not transparent).
10382 * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque).
10383 * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or
10384 * not before the new render pass.
10385 * @param {number} [options.resolution=1] - The resolution / device pixel ratio of the renderer, retina would be 2
10386 * @param {boolean} [options.forceCanvas=false] - prevents selection of WebGL renderer, even if such is present, this
10387 * option only is available when using **pixi.js-legacy** or **@pixi/canvas-renderer** modules, otherwise
10388 * it is ignored.
10389 * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance"
10390 * for devices with dual graphics card **webgl only**
10391 * @return {PIXI.Renderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer
10392 */
10393function autoDetectRenderer(options) {
10394 return Renderer.create(options);
10395}
10396
10397var $defaultVertex = "attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}";
10398
10399var $defaultFilterVertex = "attribute vec2 aVertexPosition;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nuniform vec4 inputSize;\nuniform vec4 outputFrame;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;\n\n return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aVertexPosition * (outputFrame.zw * inputSize.zw);\n}\n\nvoid main(void)\n{\n gl_Position = filterVertexPosition();\n vTextureCoord = filterTextureCoord();\n}\n";
10400
10401/**
10402 * Default vertex shader
10403 * @memberof PIXI
10404 * @member {string} defaultVertex
10405 */
10406/**
10407 * Default filter vertex shader
10408 * @memberof PIXI
10409 * @member {string} defaultFilterVertex
10410 */
10411// NOTE: This black magic is so that @microsoft/api-extractor does not complain! This explicitly specifies the types
10412// of defaultVertex, defaultFilterVertex.
10413var defaultVertex$2 = $defaultVertex;
10414var defaultFilterVertex = $defaultFilterVertex;
10415
10416/**
10417 * Used by the batcher to draw batches.
10418 * Each one of these contains all information required to draw a bound geometry.
10419 *
10420 * @class
10421 * @memberof PIXI
10422 */
10423var BatchDrawCall = /** @class */ (function () {
10424 function BatchDrawCall() {
10425 this.texArray = null;
10426 this.blend = 0;
10427 this.type = DRAW_MODES.TRIANGLES;
10428 this.start = 0;
10429 this.size = 0;
10430 /**
10431 * data for uniforms or custom webgl state
10432 * @member {object}
10433 */
10434 this.data = null;
10435 }
10436 return BatchDrawCall;
10437}());
10438
10439/**
10440 * Used by the batcher to build texture batches.
10441 * Holds list of textures and their respective locations.
10442 *
10443 * @class
10444 * @memberof PIXI
10445 */
10446var BatchTextureArray = /** @class */ (function () {
10447 function BatchTextureArray() {
10448 /**
10449 * inside textures array
10450 * @member {PIXI.BaseTexture[]}
10451 */
10452 this.elements = [];
10453 /**
10454 * Respective locations for textures
10455 * @member {number[]}
10456 */
10457 this.ids = [];
10458 /**
10459 * number of filled elements
10460 * @member {number}
10461 */
10462 this.count = 0;
10463 }
10464 BatchTextureArray.prototype.clear = function () {
10465 for (var i = 0; i < this.count; i++) {
10466 this.elements[i] = null;
10467 }
10468 this.count = 0;
10469 };
10470 return BatchTextureArray;
10471}());
10472
10473/**
10474 * Flexible wrapper around `ArrayBuffer` that also provides typed array views on demand.
10475 *
10476 * @class
10477 * @memberof PIXI
10478 */
10479var ViewableBuffer = /** @class */ (function () {
10480 function ViewableBuffer(sizeOrBuffer) {
10481 if (typeof sizeOrBuffer === 'number') {
10482 /**
10483 * Underlying `ArrayBuffer` that holds all the data and is of capacity `this.size`.
10484 *
10485 * @member {ArrayBuffer}
10486 */
10487 this.rawBinaryData = new ArrayBuffer(sizeOrBuffer);
10488 }
10489 else if (sizeOrBuffer instanceof Uint8Array) {
10490 this.rawBinaryData = sizeOrBuffer.buffer;
10491 }
10492 else {
10493 this.rawBinaryData = sizeOrBuffer;
10494 }
10495 /**
10496 * View on the raw binary data as a `Uint32Array`.
10497 *
10498 * @member {Uint32Array}
10499 */
10500 this.uint32View = new Uint32Array(this.rawBinaryData);
10501 /**
10502 * View on the raw binary data as a `Float32Array`.
10503 *
10504 * @member {Float32Array}
10505 */
10506 this.float32View = new Float32Array(this.rawBinaryData);
10507 }
10508 Object.defineProperty(ViewableBuffer.prototype, "int8View", {
10509 /**
10510 * View on the raw binary data as a `Int8Array`.
10511 *
10512 * @member {Int8Array}
10513 */
10514 get: function () {
10515 if (!this._int8View) {
10516 this._int8View = new Int8Array(this.rawBinaryData);
10517 }
10518 return this._int8View;
10519 },
10520 enumerable: false,
10521 configurable: true
10522 });
10523 Object.defineProperty(ViewableBuffer.prototype, "uint8View", {
10524 /**
10525 * View on the raw binary data as a `Uint8Array`.
10526 *
10527 * @member {Uint8Array}
10528 */
10529 get: function () {
10530 if (!this._uint8View) {
10531 this._uint8View = new Uint8Array(this.rawBinaryData);
10532 }
10533 return this._uint8View;
10534 },
10535 enumerable: false,
10536 configurable: true
10537 });
10538 Object.defineProperty(ViewableBuffer.prototype, "int16View", {
10539 /**
10540 * View on the raw binary data as a `Int16Array`.
10541 *
10542 * @member {Int16Array}
10543 */
10544 get: function () {
10545 if (!this._int16View) {
10546 this._int16View = new Int16Array(this.rawBinaryData);
10547 }
10548 return this._int16View;
10549 },
10550 enumerable: false,
10551 configurable: true
10552 });
10553 Object.defineProperty(ViewableBuffer.prototype, "uint16View", {
10554 /**
10555 * View on the raw binary data as a `Uint16Array`.
10556 *
10557 * @member {Uint16Array}
10558 */
10559 get: function () {
10560 if (!this._uint16View) {
10561 this._uint16View = new Uint16Array(this.rawBinaryData);
10562 }
10563 return this._uint16View;
10564 },
10565 enumerable: false,
10566 configurable: true
10567 });
10568 Object.defineProperty(ViewableBuffer.prototype, "int32View", {
10569 /**
10570 * View on the raw binary data as a `Int32Array`.
10571 *
10572 * @member {Int32Array}
10573 */
10574 get: function () {
10575 if (!this._int32View) {
10576 this._int32View = new Int32Array(this.rawBinaryData);
10577 }
10578 return this._int32View;
10579 },
10580 enumerable: false,
10581 configurable: true
10582 });
10583 /**
10584 * Returns the view of the given type.
10585 *
10586 * @param {string} type - One of `int8`, `uint8`, `int16`,
10587 * `uint16`, `int32`, `uint32`, and `float32`.
10588 * @return {object} typed array of given type
10589 */
10590 ViewableBuffer.prototype.view = function (type) {
10591 return this[type + "View"];
10592 };
10593 /**
10594 * Destroys all buffer references. Do not use after calling
10595 * this.
10596 */
10597 ViewableBuffer.prototype.destroy = function () {
10598 this.rawBinaryData = null;
10599 this._int8View = null;
10600 this._uint8View = null;
10601 this._int16View = null;
10602 this._uint16View = null;
10603 this._int32View = null;
10604 this.uint32View = null;
10605 this.float32View = null;
10606 };
10607 ViewableBuffer.sizeOf = function (type) {
10608 switch (type) {
10609 case 'int8':
10610 case 'uint8':
10611 return 1;
10612 case 'int16':
10613 case 'uint16':
10614 return 2;
10615 case 'int32':
10616 case 'uint32':
10617 case 'float32':
10618 return 4;
10619 default:
10620 throw new Error(type + " isn't a valid view type");
10621 }
10622 };
10623 return ViewableBuffer;
10624}());
10625
10626/**
10627 * Renderer dedicated to drawing and batching sprites.
10628 *
10629 * This is the default batch renderer. It buffers objects
10630 * with texture-based geometries and renders them in
10631 * batches. It uploads multiple textures to the GPU to
10632 * reduce to the number of draw calls.
10633 *
10634 * @class
10635 * @protected
10636 * @memberof PIXI
10637 * @extends PIXI.ObjectRenderer
10638 */
10639var AbstractBatchRenderer = /** @class */ (function (_super) {
10640 __extends(AbstractBatchRenderer, _super);
10641 /**
10642 * This will hook onto the renderer's `contextChange`
10643 * and `prerender` signals.
10644 *
10645 * @param {PIXI.Renderer} renderer - The renderer this works for.
10646 */
10647 function AbstractBatchRenderer(renderer) {
10648 var _this = _super.call(this, renderer) || this;
10649 /**
10650 * This is used to generate a shader that can
10651 * color each vertex based on a `aTextureId`
10652 * attribute that points to an texture in `uSampler`.
10653 *
10654 * This enables the objects with different textures
10655 * to be drawn in the same draw call.
10656 *
10657 * You can customize your shader by creating your
10658 * custom shader generator.
10659 *
10660 * @member {PIXI.BatchShaderGenerator}
10661 * @protected
10662 */
10663 _this.shaderGenerator = null;
10664 /**
10665 * The class that represents the geometry of objects
10666 * that are going to be batched with this.
10667 *
10668 * @member {object}
10669 * @default PIXI.BatchGeometry
10670 * @protected
10671 */
10672 _this.geometryClass = null;
10673 /**
10674 * Size of data being buffered per vertex in the
10675 * attribute buffers (in floats). By default, the
10676 * batch-renderer plugin uses 6:
10677 *
10678 * | aVertexPosition | 2 |
10679 * |-----------------|---|
10680 * | aTextureCoords | 2 |
10681 * | aColor | 1 |
10682 * | aTextureId | 1 |
10683 *
10684 * @member {number}
10685 * @readonly
10686 */
10687 _this.vertexSize = null;
10688 /**
10689 * The WebGL state in which this renderer will work.
10690 *
10691 * @member {PIXI.State}
10692 * @readonly
10693 */
10694 _this.state = State.for2d();
10695 /**
10696 * The number of bufferable objects before a flush
10697 * occurs automatically.
10698 *
10699 * @member {number}
10700 * @default settings.SPRITE_BATCH_SIZE * 4
10701 */
10702 _this.size = settings.SPRITE_BATCH_SIZE * 4;
10703 /**
10704 * Total count of all vertices used by the currently
10705 * buffered objects.
10706 *
10707 * @member {number}
10708 * @private
10709 */
10710 _this._vertexCount = 0;
10711 /**
10712 * Total count of all indices used by the currently
10713 * buffered objects.
10714 *
10715 * @member {number}
10716 * @private
10717 */
10718 _this._indexCount = 0;
10719 /**
10720 * Buffer of objects that are yet to be rendered.
10721 *
10722 * @member {PIXI.DisplayObject[]}
10723 * @private
10724 */
10725 _this._bufferedElements = [];
10726 /**
10727 * Data for texture batch builder, helps to save a bit of CPU on a pass.
10728 * @type {PIXI.BaseTexture[]}
10729 * @private
10730 */
10731 _this._bufferedTextures = [];
10732 /**
10733 * Number of elements that are buffered and are
10734 * waiting to be flushed.
10735 *
10736 * @member {number}
10737 * @private
10738 */
10739 _this._bufferSize = 0;
10740 /**
10741 * This shader is generated by `this.shaderGenerator`.
10742 *
10743 * It is generated specifically to handle the required
10744 * number of textures being batched together.
10745 *
10746 * @member {PIXI.Shader}
10747 * @protected
10748 */
10749 _this._shader = null;
10750 /**
10751 * Pool of `this.geometryClass` geometry objects
10752 * that store buffers. They are used to pass data
10753 * to the shader on each draw call.
10754 *
10755 * These are never re-allocated again, unless a
10756 * context change occurs; however, the pool may
10757 * be expanded if required.
10758 *
10759 * @member {PIXI.Geometry[]}
10760 * @private
10761 * @see PIXI.AbstractBatchRenderer.contextChange
10762 */
10763 _this._packedGeometries = [];
10764 /**
10765 * Size of `this._packedGeometries`. It can be expanded
10766 * if more than `this._packedGeometryPoolSize` flushes
10767 * occur in a single frame.
10768 *
10769 * @member {number}
10770 * @private
10771 */
10772 _this._packedGeometryPoolSize = 2;
10773 /**
10774 * A flush may occur multiple times in a single
10775 * frame. On iOS devices or when
10776 * `settings.CAN_UPLOAD_SAME_BUFFER` is false, the
10777 * batch renderer does not upload data to the same
10778 * `WebGLBuffer` for performance reasons.
10779 *
10780 * This is the index into `packedGeometries` that points to
10781 * geometry holding the most recent buffers.
10782 *
10783 * @member {number}
10784 * @private
10785 */
10786 _this._flushId = 0;
10787 /**
10788 * Pool of `ViewableBuffer` objects that are sorted in
10789 * order of increasing size. The flush method uses
10790 * the buffer with the least size above the amount
10791 * it requires. These are used for passing attributes.
10792 *
10793 * The first buffer has a size of 8; each subsequent
10794 * buffer has double capacity of its previous.
10795 *
10796 * @member {PIXI.ViewableBuffer[]}
10797 * @private
10798 * @see PIXI.AbstractBatchRenderer#getAttributeBuffer
10799 */
10800 _this._aBuffers = {};
10801 /**
10802 * Pool of `Uint16Array` objects that are sorted in
10803 * order of increasing size. The flush method uses
10804 * the buffer with the least size above the amount
10805 * it requires. These are used for passing indices.
10806 *
10807 * The first buffer has a size of 12; each subsequent
10808 * buffer has double capacity of its previous.
10809 *
10810 * @member {Uint16Array[]}
10811 * @private
10812 * @see PIXI.AbstractBatchRenderer#getIndexBuffer
10813 */
10814 _this._iBuffers = {};
10815 /**
10816 * Maximum number of textures that can be uploaded to
10817 * the GPU under the current context. It is initialized
10818 * properly in `this.contextChange`.
10819 *
10820 * @member {number}
10821 * @see PIXI.AbstractBatchRenderer#contextChange
10822 * @readonly
10823 */
10824 _this.MAX_TEXTURES = 1;
10825 _this.renderer.on('prerender', _this.onPrerender, _this);
10826 renderer.runners.contextChange.add(_this);
10827 _this._dcIndex = 0;
10828 _this._aIndex = 0;
10829 _this._iIndex = 0;
10830 _this._attributeBuffer = null;
10831 _this._indexBuffer = null;
10832 _this._tempBoundTextures = [];
10833 return _this;
10834 }
10835 /**
10836 * Handles the `contextChange` signal.
10837 *
10838 * It calculates `this.MAX_TEXTURES` and allocating the
10839 * packed-geometry object pool.
10840 */
10841 AbstractBatchRenderer.prototype.contextChange = function () {
10842 var gl = this.renderer.gl;
10843 if (settings.PREFER_ENV === ENV.WEBGL_LEGACY) {
10844 this.MAX_TEXTURES = 1;
10845 }
10846 else {
10847 // step 1: first check max textures the GPU can handle.
10848 this.MAX_TEXTURES = Math.min(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS), settings.SPRITE_MAX_TEXTURES);
10849 // step 2: check the maximum number of if statements the shader can have too..
10850 this.MAX_TEXTURES = checkMaxIfStatementsInShader(this.MAX_TEXTURES, gl);
10851 }
10852 this._shader = this.shaderGenerator.generateShader(this.MAX_TEXTURES);
10853 // we use the second shader as the first one depending on your browser
10854 // may omit aTextureId as it is not used by the shader so is optimized out.
10855 for (var i = 0; i < this._packedGeometryPoolSize; i++) {
10856 /* eslint-disable max-len */
10857 this._packedGeometries[i] = new (this.geometryClass)();
10858 }
10859 this.initFlushBuffers();
10860 };
10861 /**
10862 * Makes sure that static and dynamic flush pooled objects have correct dimensions
10863 */
10864 AbstractBatchRenderer.prototype.initFlushBuffers = function () {
10865 var _drawCallPool = AbstractBatchRenderer._drawCallPool, _textureArrayPool = AbstractBatchRenderer._textureArrayPool;
10866 // max draw calls
10867 var MAX_SPRITES = this.size / 4;
10868 // max texture arrays
10869 var MAX_TA = Math.floor(MAX_SPRITES / this.MAX_TEXTURES) + 1;
10870 while (_drawCallPool.length < MAX_SPRITES) {
10871 _drawCallPool.push(new BatchDrawCall());
10872 }
10873 while (_textureArrayPool.length < MAX_TA) {
10874 _textureArrayPool.push(new BatchTextureArray());
10875 }
10876 for (var i = 0; i < this.MAX_TEXTURES; i++) {
10877 this._tempBoundTextures[i] = null;
10878 }
10879 };
10880 /**
10881 * Handles the `prerender` signal.
10882 *
10883 * It ensures that flushes start from the first geometry
10884 * object again.
10885 */
10886 AbstractBatchRenderer.prototype.onPrerender = function () {
10887 this._flushId = 0;
10888 };
10889 /**
10890 * Buffers the "batchable" object. It need not be rendered
10891 * immediately.
10892 *
10893 * @param {PIXI.DisplayObject} element - the element to render when
10894 * using this renderer
10895 */
10896 AbstractBatchRenderer.prototype.render = function (element) {
10897 if (!element._texture.valid) {
10898 return;
10899 }
10900 if (this._vertexCount + (element.vertexData.length / 2) > this.size) {
10901 this.flush();
10902 }
10903 this._vertexCount += element.vertexData.length / 2;
10904 this._indexCount += element.indices.length;
10905 this._bufferedTextures[this._bufferSize] = element._texture.baseTexture;
10906 this._bufferedElements[this._bufferSize++] = element;
10907 };
10908 AbstractBatchRenderer.prototype.buildTexturesAndDrawCalls = function () {
10909 var _a = this, textures = _a._bufferedTextures, MAX_TEXTURES = _a.MAX_TEXTURES;
10910 var textureArrays = AbstractBatchRenderer._textureArrayPool;
10911 var batch = this.renderer.batch;
10912 var boundTextures = this._tempBoundTextures;
10913 var touch = this.renderer.textureGC.count;
10914 var TICK = ++BaseTexture._globalBatch;
10915 var countTexArrays = 0;
10916 var texArray = textureArrays[0];
10917 var start = 0;
10918 batch.copyBoundTextures(boundTextures, MAX_TEXTURES);
10919 for (var i = 0; i < this._bufferSize; ++i) {
10920 var tex = textures[i];
10921 textures[i] = null;
10922 if (tex._batchEnabled === TICK) {
10923 continue;
10924 }
10925 if (texArray.count >= MAX_TEXTURES) {
10926 batch.boundArray(texArray, boundTextures, TICK, MAX_TEXTURES);
10927 this.buildDrawCalls(texArray, start, i);
10928 start = i;
10929 texArray = textureArrays[++countTexArrays];
10930 ++TICK;
10931 }
10932 tex._batchEnabled = TICK;
10933 tex.touched = touch;
10934 texArray.elements[texArray.count++] = tex;
10935 }
10936 if (texArray.count > 0) {
10937 batch.boundArray(texArray, boundTextures, TICK, MAX_TEXTURES);
10938 this.buildDrawCalls(texArray, start, this._bufferSize);
10939 ++countTexArrays;
10940 ++TICK;
10941 }
10942 // Clean-up
10943 for (var i = 0; i < boundTextures.length; i++) {
10944 boundTextures[i] = null;
10945 }
10946 BaseTexture._globalBatch = TICK;
10947 };
10948 /**
10949 * Populating drawcalls for rendering
10950 *
10951 * @param {PIXI.BatchTextureArray} texArray
10952 * @param {number} start
10953 * @param {number} finish
10954 */
10955 AbstractBatchRenderer.prototype.buildDrawCalls = function (texArray, start, finish) {
10956 var _a = this, elements = _a._bufferedElements, _attributeBuffer = _a._attributeBuffer, _indexBuffer = _a._indexBuffer, vertexSize = _a.vertexSize;
10957 var drawCalls = AbstractBatchRenderer._drawCallPool;
10958 var dcIndex = this._dcIndex;
10959 var aIndex = this._aIndex;
10960 var iIndex = this._iIndex;
10961 var drawCall = drawCalls[dcIndex];
10962 drawCall.start = this._iIndex;
10963 drawCall.texArray = texArray;
10964 for (var i = start; i < finish; ++i) {
10965 var sprite = elements[i];
10966 var tex = sprite._texture.baseTexture;
10967 var spriteBlendMode = premultiplyBlendMode[tex.alphaMode ? 1 : 0][sprite.blendMode];
10968 elements[i] = null;
10969 if (start < i && drawCall.blend !== spriteBlendMode) {
10970 drawCall.size = iIndex - drawCall.start;
10971 start = i;
10972 drawCall = drawCalls[++dcIndex];
10973 drawCall.texArray = texArray;
10974 drawCall.start = iIndex;
10975 }
10976 this.packInterleavedGeometry(sprite, _attributeBuffer, _indexBuffer, aIndex, iIndex);
10977 aIndex += sprite.vertexData.length / 2 * vertexSize;
10978 iIndex += sprite.indices.length;
10979 drawCall.blend = spriteBlendMode;
10980 }
10981 if (start < finish) {
10982 drawCall.size = iIndex - drawCall.start;
10983 ++dcIndex;
10984 }
10985 this._dcIndex = dcIndex;
10986 this._aIndex = aIndex;
10987 this._iIndex = iIndex;
10988 };
10989 /**
10990 * Bind textures for current rendering
10991 *
10992 * @param {PIXI.BatchTextureArray} texArray
10993 */
10994 AbstractBatchRenderer.prototype.bindAndClearTexArray = function (texArray) {
10995 var textureSystem = this.renderer.texture;
10996 for (var j = 0; j < texArray.count; j++) {
10997 textureSystem.bind(texArray.elements[j], texArray.ids[j]);
10998 texArray.elements[j] = null;
10999 }
11000 texArray.count = 0;
11001 };
11002 AbstractBatchRenderer.prototype.updateGeometry = function () {
11003 var _a = this, packedGeometries = _a._packedGeometries, attributeBuffer = _a._attributeBuffer, indexBuffer = _a._indexBuffer;
11004 if (!settings.CAN_UPLOAD_SAME_BUFFER) { /* Usually on iOS devices, where the browser doesn't
11005 like uploads to the same buffer in a single frame. */
11006 if (this._packedGeometryPoolSize <= this._flushId) {
11007 this._packedGeometryPoolSize++;
11008 packedGeometries[this._flushId] = new (this.geometryClass)();
11009 }
11010 packedGeometries[this._flushId]._buffer.update(attributeBuffer.rawBinaryData);
11011 packedGeometries[this._flushId]._indexBuffer.update(indexBuffer);
11012 this.renderer.geometry.bind(packedGeometries[this._flushId]);
11013 this.renderer.geometry.updateBuffers();
11014 this._flushId++;
11015 }
11016 else {
11017 // lets use the faster option, always use buffer number 0
11018 packedGeometries[this._flushId]._buffer.update(attributeBuffer.rawBinaryData);
11019 packedGeometries[this._flushId]._indexBuffer.update(indexBuffer);
11020 this.renderer.geometry.updateBuffers();
11021 }
11022 };
11023 AbstractBatchRenderer.prototype.drawBatches = function () {
11024 var dcCount = this._dcIndex;
11025 var _a = this.renderer, gl = _a.gl, stateSystem = _a.state;
11026 var drawCalls = AbstractBatchRenderer._drawCallPool;
11027 var curTexArray = null;
11028 // Upload textures and do the draw calls
11029 for (var i = 0; i < dcCount; i++) {
11030 var _b = drawCalls[i], texArray = _b.texArray, type = _b.type, size = _b.size, start = _b.start, blend = _b.blend;
11031 if (curTexArray !== texArray) {
11032 curTexArray = texArray;
11033 this.bindAndClearTexArray(texArray);
11034 }
11035 this.state.blendMode = blend;
11036 stateSystem.set(this.state);
11037 gl.drawElements(type, size, gl.UNSIGNED_SHORT, start * 2);
11038 }
11039 };
11040 /**
11041 * Renders the content _now_ and empties the current batch.
11042 */
11043 AbstractBatchRenderer.prototype.flush = function () {
11044 if (this._vertexCount === 0) {
11045 return;
11046 }
11047 this._attributeBuffer = this.getAttributeBuffer(this._vertexCount);
11048 this._indexBuffer = this.getIndexBuffer(this._indexCount);
11049 this._aIndex = 0;
11050 this._iIndex = 0;
11051 this._dcIndex = 0;
11052 this.buildTexturesAndDrawCalls();
11053 this.updateGeometry();
11054 this.drawBatches();
11055 // reset elements buffer for the next flush
11056 this._bufferSize = 0;
11057 this._vertexCount = 0;
11058 this._indexCount = 0;
11059 };
11060 /**
11061 * Starts a new sprite batch.
11062 */
11063 AbstractBatchRenderer.prototype.start = function () {
11064 this.renderer.state.set(this.state);
11065 this.renderer.shader.bind(this._shader);
11066 if (settings.CAN_UPLOAD_SAME_BUFFER) {
11067 // bind buffer #0, we don't need others
11068 this.renderer.geometry.bind(this._packedGeometries[this._flushId]);
11069 }
11070 };
11071 /**
11072 * Stops and flushes the current batch.
11073 */
11074 AbstractBatchRenderer.prototype.stop = function () {
11075 this.flush();
11076 };
11077 /**
11078 * Destroys this `AbstractBatchRenderer`. It cannot be used again.
11079 */
11080 AbstractBatchRenderer.prototype.destroy = function () {
11081 for (var i = 0; i < this._packedGeometryPoolSize; i++) {
11082 if (this._packedGeometries[i]) {
11083 this._packedGeometries[i].destroy();
11084 }
11085 }
11086 this.renderer.off('prerender', this.onPrerender, this);
11087 this._aBuffers = null;
11088 this._iBuffers = null;
11089 this._packedGeometries = null;
11090 this._attributeBuffer = null;
11091 this._indexBuffer = null;
11092 if (this._shader) {
11093 this._shader.destroy();
11094 this._shader = null;
11095 }
11096 _super.prototype.destroy.call(this);
11097 };
11098 /**
11099 * Fetches an attribute buffer from `this._aBuffers` that
11100 * can hold atleast `size` floats.
11101 *
11102 * @param {number} size - minimum capacity required
11103 * @return {ViewableBuffer} - buffer than can hold atleast `size` floats
11104 * @private
11105 */
11106 AbstractBatchRenderer.prototype.getAttributeBuffer = function (size) {
11107 // 8 vertices is enough for 2 quads
11108 var roundedP2 = nextPow2(Math.ceil(size / 8));
11109 var roundedSizeIndex = log2(roundedP2);
11110 var roundedSize = roundedP2 * 8;
11111 if (this._aBuffers.length <= roundedSizeIndex) {
11112 this._iBuffers.length = roundedSizeIndex + 1;
11113 }
11114 var buffer = this._aBuffers[roundedSize];
11115 if (!buffer) {
11116 this._aBuffers[roundedSize] = buffer = new ViewableBuffer(roundedSize * this.vertexSize * 4);
11117 }
11118 return buffer;
11119 };
11120 /**
11121 * Fetches an index buffer from `this._iBuffers` that can
11122 * have at least `size` capacity.
11123 *
11124 * @param {number} size - minimum required capacity
11125 * @return {Uint16Array} - buffer that can fit `size`
11126 * indices.
11127 * @private
11128 */
11129 AbstractBatchRenderer.prototype.getIndexBuffer = function (size) {
11130 // 12 indices is enough for 2 quads
11131 var roundedP2 = nextPow2(Math.ceil(size / 12));
11132 var roundedSizeIndex = log2(roundedP2);
11133 var roundedSize = roundedP2 * 12;
11134 if (this._iBuffers.length <= roundedSizeIndex) {
11135 this._iBuffers.length = roundedSizeIndex + 1;
11136 }
11137 var buffer = this._iBuffers[roundedSizeIndex];
11138 if (!buffer) {
11139 this._iBuffers[roundedSizeIndex] = buffer = new Uint16Array(roundedSize);
11140 }
11141 return buffer;
11142 };
11143 /**
11144 * Takes the four batching parameters of `element`, interleaves
11145 * and pushes them into the batching attribute/index buffers given.
11146 *
11147 * It uses these properties: `vertexData` `uvs`, `textureId` and
11148 * `indicies`. It also uses the "tint" of the base-texture, if
11149 * present.
11150 *
11151 * @param {PIXI.Sprite} element - element being rendered
11152 * @param {PIXI.ViewableBuffer} attributeBuffer - attribute buffer.
11153 * @param {Uint16Array} indexBuffer - index buffer
11154 * @param {number} aIndex - number of floats already in the attribute buffer
11155 * @param {number} iIndex - number of indices already in `indexBuffer`
11156 */
11157 AbstractBatchRenderer.prototype.packInterleavedGeometry = function (element, attributeBuffer, indexBuffer, aIndex, iIndex) {
11158 var uint32View = attributeBuffer.uint32View, float32View = attributeBuffer.float32View;
11159 var packedVertices = aIndex / this.vertexSize;
11160 var uvs = element.uvs;
11161 var indicies = element.indices;
11162 var vertexData = element.vertexData;
11163 var textureId = element._texture.baseTexture._batchLocation;
11164 var alpha = Math.min(element.worldAlpha, 1.0);
11165 var argb = (alpha < 1.0
11166 && element._texture.baseTexture.alphaMode)
11167 ? premultiplyTint(element._tintRGB, alpha)
11168 : element._tintRGB + (alpha * 255 << 24);
11169 // lets not worry about tint! for now..
11170 for (var i = 0; i < vertexData.length; i += 2) {
11171 float32View[aIndex++] = vertexData[i];
11172 float32View[aIndex++] = vertexData[i + 1];
11173 float32View[aIndex++] = uvs[i];
11174 float32View[aIndex++] = uvs[i + 1];
11175 uint32View[aIndex++] = argb;
11176 float32View[aIndex++] = textureId;
11177 }
11178 for (var i = 0; i < indicies.length; i++) {
11179 indexBuffer[iIndex++] = packedVertices + indicies[i];
11180 }
11181 };
11182 /**
11183 * Pool of `BatchDrawCall` objects that `flush` used
11184 * to create "batches" of the objects being rendered.
11185 *
11186 * These are never re-allocated again.
11187 * Shared between all batch renderers because it can be only one "flush" working at the moment.
11188 *
11189 * @static
11190 * @member {PIXI.BatchDrawCall[]}
11191 */
11192 AbstractBatchRenderer._drawCallPool = [];
11193 /**
11194 * Pool of `BatchDrawCall` objects that `flush` used
11195 * to create "batches" of the objects being rendered.
11196 *
11197 * These are never re-allocated again.
11198 * Shared between all batch renderers because it can be only one "flush" working at the moment.
11199 *
11200 * @static
11201 * @member {PIXI.BatchTextureArray[]}
11202 */
11203 AbstractBatchRenderer._textureArrayPool = [];
11204 return AbstractBatchRenderer;
11205}(ObjectRenderer));
11206
11207/**
11208 * Helper that generates batching multi-texture shader. Use it with your new BatchRenderer
11209 *
11210 * @class
11211 * @memberof PIXI
11212 */
11213var BatchShaderGenerator = /** @class */ (function () {
11214 /**
11215 * @param {string} vertexSrc - Vertex shader
11216 * @param {string} fragTemplate - Fragment shader template
11217 */
11218 function BatchShaderGenerator(vertexSrc, fragTemplate) {
11219 /**
11220 * Reference to the vertex shader source.
11221 *
11222 * @member {string}
11223 */
11224 this.vertexSrc = vertexSrc;
11225 /**
11226 * Reference to the fragment shader template. Must contain "%count%" and "%forloop%".
11227 *
11228 * @member {string}
11229 */
11230 this.fragTemplate = fragTemplate;
11231 this.programCache = {};
11232 this.defaultGroupCache = {};
11233 if (fragTemplate.indexOf('%count%') < 0) {
11234 throw new Error('Fragment template must contain "%count%".');
11235 }
11236 if (fragTemplate.indexOf('%forloop%') < 0) {
11237 throw new Error('Fragment template must contain "%forloop%".');
11238 }
11239 }
11240 BatchShaderGenerator.prototype.generateShader = function (maxTextures) {
11241 if (!this.programCache[maxTextures]) {
11242 var sampleValues = new Int32Array(maxTextures);
11243 for (var i = 0; i < maxTextures; i++) {
11244 sampleValues[i] = i;
11245 }
11246 this.defaultGroupCache[maxTextures] = UniformGroup.from({ uSamplers: sampleValues }, true);
11247 var fragmentSrc = this.fragTemplate;
11248 fragmentSrc = fragmentSrc.replace(/%count%/gi, "" + maxTextures);
11249 fragmentSrc = fragmentSrc.replace(/%forloop%/gi, this.generateSampleSrc(maxTextures));
11250 this.programCache[maxTextures] = new Program(this.vertexSrc, fragmentSrc);
11251 }
11252 var uniforms = {
11253 tint: new Float32Array([1, 1, 1, 1]),
11254 translationMatrix: new Matrix(),
11255 default: this.defaultGroupCache[maxTextures],
11256 };
11257 return new Shader(this.programCache[maxTextures], uniforms);
11258 };
11259 BatchShaderGenerator.prototype.generateSampleSrc = function (maxTextures) {
11260 var src = '';
11261 src += '\n';
11262 src += '\n';
11263 for (var i = 0; i < maxTextures; i++) {
11264 if (i > 0) {
11265 src += '\nelse ';
11266 }
11267 if (i < maxTextures - 1) {
11268 src += "if(vTextureId < " + i + ".5)";
11269 }
11270 src += '\n{';
11271 src += "\n\tcolor = texture2D(uSamplers[" + i + "], vTextureCoord);";
11272 src += '\n}';
11273 }
11274 src += '\n';
11275 src += '\n';
11276 return src;
11277 };
11278 return BatchShaderGenerator;
11279}());
11280
11281/**
11282 * Geometry used to batch standard PIXI content (e.g. Mesh, Sprite, Graphics objects).
11283 *
11284 * @class
11285 * @memberof PIXI
11286 */
11287var BatchGeometry = /** @class */ (function (_super) {
11288 __extends(BatchGeometry, _super);
11289 /**
11290 * @param {boolean} [_static=false] - Optimization flag, where `false`
11291 * is updated every frame, `true` doesn't change frame-to-frame.
11292 */
11293 function BatchGeometry(_static) {
11294 if (_static === void 0) { _static = false; }
11295 var _this = _super.call(this) || this;
11296 /**
11297 * Buffer used for position, color, texture IDs
11298 *
11299 * @member {PIXI.Buffer}
11300 * @protected
11301 */
11302 _this._buffer = new Buffer(null, _static, false);
11303 /**
11304 * Index buffer data
11305 *
11306 * @member {PIXI.Buffer}
11307 * @protected
11308 */
11309 _this._indexBuffer = new Buffer(null, _static, true);
11310 _this.addAttribute('aVertexPosition', _this._buffer, 2, false, TYPES.FLOAT)
11311 .addAttribute('aTextureCoord', _this._buffer, 2, false, TYPES.FLOAT)
11312 .addAttribute('aColor', _this._buffer, 4, true, TYPES.UNSIGNED_BYTE)
11313 .addAttribute('aTextureId', _this._buffer, 1, true, TYPES.FLOAT)
11314 .addIndex(_this._indexBuffer);
11315 return _this;
11316 }
11317 return BatchGeometry;
11318}(Geometry));
11319
11320var defaultVertex$3 = "precision highp float;\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\nuniform mat3 translationMatrix;\nuniform vec4 tint;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = aColor * tint;\n}\n";
11321
11322var defaultFragment$2 = "varying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\nuniform sampler2D uSamplers[%count%];\n\nvoid main(void){\n vec4 color;\n %forloop%\n gl_FragColor = color * vColor;\n}\n";
11323
11324/**
11325 * @class
11326 * @memberof PIXI
11327 * @hideconstructor
11328 */
11329var BatchPluginFactory = /** @class */ (function () {
11330 function BatchPluginFactory() {
11331 }
11332 /**
11333 * Create a new BatchRenderer plugin for Renderer. this convenience can provide an easy way
11334 * to extend BatchRenderer with all the necessary pieces.
11335 * @example
11336 * const fragment = `
11337 * varying vec2 vTextureCoord;
11338 * varying vec4 vColor;
11339 * varying float vTextureId;
11340 * uniform sampler2D uSamplers[%count%];
11341 *
11342 * void main(void){
11343 * vec4 color;
11344 * %forloop%
11345 * gl_FragColor = vColor * vec4(color.a - color.rgb, color.a);
11346 * }
11347 * `;
11348 * const InvertBatchRenderer = PIXI.BatchPluginFactory.create({ fragment });
11349 * PIXI.Renderer.registerPlugin('invert', InvertBatchRenderer);
11350 * const sprite = new PIXI.Sprite();
11351 * sprite.pluginName = 'invert';
11352 *
11353 * @static
11354 * @param {object} [options]
11355 * @param {string} [options.vertex=PIXI.BatchPluginFactory.defaultVertexSrc] - Vertex shader source
11356 * @param {string} [options.fragment=PIXI.BatchPluginFactory.defaultFragmentTemplate] - Fragment shader template
11357 * @param {number} [options.vertexSize=6] - Vertex size
11358 * @param {object} [options.geometryClass=PIXI.BatchGeometry]
11359 * @return {*} New batch renderer plugin
11360 */
11361 BatchPluginFactory.create = function (options) {
11362 var _a = Object.assign({
11363 vertex: defaultVertex$3,
11364 fragment: defaultFragment$2,
11365 geometryClass: BatchGeometry,
11366 vertexSize: 6,
11367 }, options), vertex = _a.vertex, fragment = _a.fragment, vertexSize = _a.vertexSize, geometryClass = _a.geometryClass;
11368 return /** @class */ (function (_super) {
11369 __extends(BatchPlugin, _super);
11370 function BatchPlugin(renderer) {
11371 var _this = _super.call(this, renderer) || this;
11372 _this.shaderGenerator = new BatchShaderGenerator(vertex, fragment);
11373 _this.geometryClass = geometryClass;
11374 _this.vertexSize = vertexSize;
11375 return _this;
11376 }
11377 return BatchPlugin;
11378 }(AbstractBatchRenderer));
11379 };
11380 Object.defineProperty(BatchPluginFactory, "defaultVertexSrc", {
11381 /**
11382 * The default vertex shader source
11383 *
11384 * @static
11385 * @type {string}
11386 * @constant
11387 */
11388 get: function () {
11389 return defaultVertex$3;
11390 },
11391 enumerable: false,
11392 configurable: true
11393 });
11394 Object.defineProperty(BatchPluginFactory, "defaultFragmentTemplate", {
11395 /**
11396 * The default fragment shader source
11397 *
11398 * @static
11399 * @type {string}
11400 * @constant
11401 */
11402 get: function () {
11403 return defaultFragment$2;
11404 },
11405 enumerable: false,
11406 configurable: true
11407 });
11408 return BatchPluginFactory;
11409}());
11410// Setup the default BatchRenderer plugin, this is what
11411// we'll actually export at the root level
11412var BatchRenderer = BatchPluginFactory.create();
11413
11414/**
11415 * @memberof PIXI
11416 * @namespace resources
11417 * @see PIXI
11418 * @deprecated since 6.0.0
11419 */
11420var resources = {};
11421var _loop_1 = function (name) {
11422 Object.defineProperty(resources, name, {
11423 get: function () {
11424 deprecation('6.0.0', "PIXI.systems." + name + " has moved to PIXI." + name);
11425 return _resources[name];
11426 },
11427 });
11428};
11429for (var name in _resources) {
11430 _loop_1(name);
11431}
11432/**
11433 * @memberof PIXI
11434 * @namespace systems
11435 * @see PIXI
11436 * @deprecated since 6.0.0
11437 */
11438var systems = {};
11439var _loop_2 = function (name) {
11440 Object.defineProperty(systems, name, {
11441 get: function () {
11442 deprecation('6.0.0', "PIXI.resources." + name + " has moved to PIXI." + name);
11443 return _systems[name];
11444 },
11445 });
11446};
11447for (var name in _systems) {
11448 _loop_2(name);
11449}
11450
11451export { AbstractBatchRenderer, AbstractMultiResource, AbstractRenderer, ArrayResource, Attribute, BaseImageResource, BaseRenderTexture, BaseTexture, BatchDrawCall, BatchGeometry, BatchPluginFactory, BatchRenderer, BatchShaderGenerator, BatchSystem, BatchTextureArray, Buffer, BufferResource, CanvasResource, ContextSystem, CubeResource, Filter, FilterState, FilterSystem, Framebuffer, FramebufferSystem, GLFramebuffer, GLProgram, GLTexture, Geometry, GeometrySystem, IGLUniformData, INSTALLED, ImageBitmapResource, ImageResource, MaskData, MaskSystem, ObjectRenderer, Program, ProjectionSystem, Quad, QuadUv, RenderTexture, RenderTexturePool, RenderTextureSystem, Renderer, Resource, SVGResource, ScissorSystem, Shader, ShaderSystem, SpriteMaskFilter, State, StateSystem, StencilSystem, System, Texture, TextureGCSystem, TextureMatrix, TextureSystem, TextureUvs, UniformGroup, VideoResource, ViewableBuffer, autoDetectRenderer, autoDetectResource, checkMaxIfStatementsInShader, defaultFilterVertex, defaultVertex$2 as defaultVertex, resources, systems, uniformParsers };
11452//# sourceMappingURL=core.js.map