/*!
 * PixiJS - v8.15.0
 * Compiled Mon, 05 Jan 2026 10:10:58 UTC
 *
 * PixiJS is licensed under the MIT License.
 * http://www.opensource.org/licenses/mit-license
 */
var PIXI = (function (exports) {
    'use strict';

    "use strict";
    const BrowserAdapter = {
      createCanvas: (width, height) => {
        const canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        return canvas;
      },
      createImage: () => new Image(),
      getCanvasRenderingContext2D: () => CanvasRenderingContext2D,
      getWebGLRenderingContext: () => WebGLRenderingContext,
      getNavigator: () => navigator,
      getBaseUrl: () => {
        var _a;
        return (_a = document.baseURI) != null ? _a : window.location.href;
      },
      getFontFaceSet: () => document.fonts,
      fetch: (url, options) => fetch(url, options),
      parseXML: (xml) => {
        const parser = new DOMParser();
        return parser.parseFromString(xml, "text/xml");
      }
    };

    "use strict";
    let currentAdapter = BrowserAdapter;
    const DOMAdapter = {
      /**
       * Returns the current adapter.
       * @returns {environment.Adapter} The current adapter.
       */
      get() {
        return currentAdapter;
      },
      /**
       * Sets the current adapter.
       * @param adapter - The new adapter.
       */
      set(adapter) {
        currentAdapter = adapter;
      }
    };

    var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

    function getDefaultExportFromCjs (x) {
    	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
    }

    function getDefaultExportFromNamespaceIfPresent (n) {
    	return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n['default'] : n;
    }

    function getDefaultExportFromNamespaceIfNotNamed (n) {
    	return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
    }

    function getAugmentedNamespace(n) {
      if (n.__esModule) return n;
      var f = n.default;
    	if (typeof f == "function") {
    		var a = function a () {
    			if (this instanceof a) {
            return Reflect.construct(f, arguments, this.constructor);
    			}
    			return f.apply(this, arguments);
    		};
    		a.prototype = f.prototype;
      } else a = {};
      Object.defineProperty(a, '__esModule', {value: true});
    	Object.keys(n).forEach(function (k) {
    		var d = Object.getOwnPropertyDescriptor(n, k);
    		Object.defineProperty(a, k, d.get ? d : {
    			enumerable: true,
    			get: function () {
    				return n[k];
    			}
    		});
    	});
    	return a;
    }

    var lib = {};

    var dom$2 = {};

    var conventions$2 = {};

    'use strict';

    /**
     * Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes.
     *
     * Works with anything that has a `length` property and index access properties, including NodeList.
     *
     * @template {unknown} T
     * @param {Array<T> | ({length:number, [number]: T})} list
     * @param {function (item: T, index: number, list:Array<T> | ({length:number, [number]: T})):boolean} predicate
     * @param {Partial<Pick<ArrayConstructor['prototype'], 'find'>>?} ac `Array.prototype` by default,
     * 				allows injecting a custom implementation in tests
     * @returns {T | undefined}
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
     * @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find
     */
    function find$1(list, predicate, ac) {
    	if (ac === undefined) {
    		ac = Array.prototype;
    	}
    	if (list && typeof ac.find === 'function') {
    		return ac.find.call(list, predicate);
    	}
    	for (var i = 0; i < list.length; i++) {
    		if (Object.prototype.hasOwnProperty.call(list, i)) {
    			var item = list[i];
    			if (predicate.call(undefined, item, i, list)) {
    				return item;
    			}
    		}
    	}
    }

    /**
     * "Shallow freezes" an object to render it immutable.
     * Uses `Object.freeze` if available,
     * otherwise the immutability is only in the type.
     *
     * Is used to create "enum like" objects.
     *
     * @template T
     * @param {T} object the object to freeze
     * @param {Pick<ObjectConstructor, 'freeze'> = Object} oc `Object` by default,
     * 				allows to inject custom object constructor for tests
     * @returns {Readonly<T>}
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
     */
    function freeze(object, oc) {
    	if (oc === undefined) {
    		oc = Object;
    	}
    	return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object
    }

    /**
     * Since we can not rely on `Object.assign` we provide a simplified version
     * that is sufficient for our needs.
     *
     * @param {Object} target
     * @param {Object | null | undefined} source
     *
     * @returns {Object} target
     * @throws TypeError if target is not an object
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
     * @see https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.assign
     */
    function assign(target, source) {
    	if (target === null || typeof target !== 'object') {
    		throw new TypeError('target is not an object')
    	}
    	for (var key in source) {
    		if (Object.prototype.hasOwnProperty.call(source, key)) {
    			target[key] = source[key];
    		}
    	}
    	return target
    }

    /**
     * All mime types that are allowed as input to `DOMParser.parseFromString`
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02 MDN
     * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype WHATWG HTML Spec
     * @see DOMParser.prototype.parseFromString
     */
    var MIME_TYPE = freeze({
    	/**
    	 * `text/html`, the only mime type that triggers treating an XML document as HTML.
    	 *
    	 * @see DOMParser.SupportedType.isHTML
    	 * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
    	 * @see https://en.wikipedia.org/wiki/HTML Wikipedia
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
    	 * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec
    	 */
    	HTML: 'text/html',

    	/**
    	 * Helper method to check a mime type if it indicates an HTML document
    	 *
    	 * @param {string} [value]
    	 * @returns {boolean}
    	 *
    	 * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
    	 * @see https://en.wikipedia.org/wiki/HTML Wikipedia
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
    	 * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring 	 */
    	isHTML: function (value) {
    		return value === MIME_TYPE.HTML
    	},

    	/**
    	 * `application/xml`, the standard mime type for XML documents.
    	 *
    	 * @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration
    	 * @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303
    	 * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
    	 */
    	XML_APPLICATION: 'application/xml',

    	/**
    	 * `text/html`, an alias for `application/xml`.
    	 *
    	 * @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303
    	 * @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration
    	 * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
    	 */
    	XML_TEXT: 'text/xml',

    	/**
    	 * `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,
    	 * but is parsed as an XML document.
    	 *
    	 * @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration
    	 * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec
    	 * @see https://en.wikipedia.org/wiki/XHTML Wikipedia
    	 */
    	XML_XHTML_APPLICATION: 'application/xhtml+xml',

    	/**
    	 * `image/svg+xml`,
    	 *
    	 * @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration
    	 * @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1
    	 * @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
    	 */
    	XML_SVG_IMAGE: 'image/svg+xml',
    });

    /**
     * Namespaces that are used in this code base.
     *
     * @see http://www.w3.org/TR/REC-xml-names
     */
    var NAMESPACE$3 = freeze({
    	/**
    	 * The XHTML namespace.
    	 *
    	 * @see http://www.w3.org/1999/xhtml
    	 */
    	HTML: 'http://www.w3.org/1999/xhtml',

    	/**
    	 * Checks if `uri` equals `NAMESPACE.HTML`.
    	 *
    	 * @param {string} [uri]
    	 *
    	 * @see NAMESPACE.HTML
    	 */
    	isHTML: function (uri) {
    		return uri === NAMESPACE$3.HTML
    	},

    	/**
    	 * The SVG namespace.
    	 *
    	 * @see http://www.w3.org/2000/svg
    	 */
    	SVG: 'http://www.w3.org/2000/svg',

    	/**
    	 * The `xml:` namespace.
    	 *
    	 * @see http://www.w3.org/XML/1998/namespace
    	 */
    	XML: 'http://www.w3.org/XML/1998/namespace',

    	/**
    	 * The `xmlns:` namespace
    	 *
    	 * @see https://www.w3.org/2000/xmlns/
    	 */
    	XMLNS: 'http://www.w3.org/2000/xmlns/',
    });

    var assign_1 = conventions$2.assign = assign;
    var find_1 = conventions$2.find = find$1;
    var freeze_1 = conventions$2.freeze = freeze;
    var MIME_TYPE_1 = conventions$2.MIME_TYPE = MIME_TYPE;
    var NAMESPACE_1 = conventions$2.NAMESPACE = NAMESPACE$3;

    var conventions$1 = conventions$2;

    var find = conventions$1.find;
    var NAMESPACE$2 = conventions$1.NAMESPACE;

    /**
     * A prerequisite for `[].filter`, to drop elements that are empty
     * @param {string} input
     * @returns {boolean}
     */
    function notEmptyString (input) {
    	return input !== ''
    }
    /**
     * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace
     * @see https://infra.spec.whatwg.org/#ascii-whitespace
     *
     * @param {string} input
     * @returns {string[]} (can be empty)
     */
    function splitOnASCIIWhitespace(input) {
    	// U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE
    	return input ? input.split(/[\t\n\f\r ]+/).filter(notEmptyString) : []
    }

    /**
     * Adds element as a key to current if it is not already present.
     *
     * @param {Record<string, boolean | undefined>} current
     * @param {string} element
     * @returns {Record<string, boolean | undefined>}
     */
    function orderedSetReducer (current, element) {
    	if (!current.hasOwnProperty(element)) {
    		current[element] = true;
    	}
    	return current;
    }

    /**
     * @see https://infra.spec.whatwg.org/#ordered-set
     * @param {string} input
     * @returns {string[]}
     */
    function toOrderedSet(input) {
    	if (!input) return [];
    	var list = splitOnASCIIWhitespace(input);
    	return Object.keys(list.reduce(orderedSetReducer, {}))
    }

    /**
     * Uses `list.indexOf` to implement something like `Array.prototype.includes`,
     * which we can not rely on being available.
     *
     * @param {any[]} list
     * @returns {function(any): boolean}
     */
    function arrayIncludes (list) {
    	return function(element) {
    		return list && list.indexOf(element) !== -1;
    	}
    }

    function copy(src,dest){
    	for(var p in src){
    		if (Object.prototype.hasOwnProperty.call(src, p)) {
    			dest[p] = src[p];
    		}
    	}
    }

    /**
    ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
    ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
     */
    function _extends(Class,Super){
    	var pt = Class.prototype;
    	if(!(pt instanceof Super)){
    		function t(){};
    		t.prototype = Super.prototype;
    		t = new t();
    		copy(pt,t);
    		Class.prototype = pt = t;
    	}
    	if(pt.constructor != Class){
    		if(typeof Class != 'function'){
    			console.error("unknown Class:"+Class);
    		}
    		pt.constructor = Class;
    	}
    }

    // Node Types
    var NodeType = {};
    var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
    var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
    var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
    var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
    var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
    var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
    var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
    var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
    var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
    var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
    var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
    var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;

    // ExceptionCode
    var ExceptionCode = {};
    var ExceptionMessage = {};
    var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
    var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
    var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
    var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
    var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
    var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
    var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
    var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
    var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
    var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
    //level2
    var INVALID_STATE_ERR        	= ExceptionCode.INVALID_STATE_ERR        	= ((ExceptionMessage[11]="Invalid state"),11);
    var SYNTAX_ERR               	= ExceptionCode.SYNTAX_ERR               	= ((ExceptionMessage[12]="Syntax error"),12);
    var INVALID_MODIFICATION_ERR 	= ExceptionCode.INVALID_MODIFICATION_ERR 	= ((ExceptionMessage[13]="Invalid modification"),13);
    var NAMESPACE_ERR            	= ExceptionCode.NAMESPACE_ERR           	= ((ExceptionMessage[14]="Invalid namespace"),14);
    var INVALID_ACCESS_ERR       	= ExceptionCode.INVALID_ACCESS_ERR      	= ((ExceptionMessage[15]="Invalid access"),15);

    /**
     * DOM Level 2
     * Object DOMException
     * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
     * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
     */
    function DOMException(code, message) {
    	if(message instanceof Error){
    		var error = message;
    	}else {
    		error = this;
    		Error.call(this, ExceptionMessage[code]);
    		this.message = ExceptionMessage[code];
    		if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
    	}
    	error.code = code;
    	if(message) this.message = this.message + ": " + message;
    	return error;
    };
    DOMException.prototype = Error.prototype;
    copy(ExceptionCode,DOMException);

    /**
     * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
     * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
     * The items in the NodeList are accessible via an integral index, starting from 0.
     */
    function NodeList() {
    };
    NodeList.prototype = {
    	/**
    	 * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
    	 * @standard level1
    	 */
    	length:0,
    	/**
    	 * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
    	 * @standard level1
    	 * @param index  unsigned long
    	 *   Index into the collection.
    	 * @return Node
    	 * 	The node at the indexth position in the NodeList, or null if that is not a valid index.
    	 */
    	item: function(index) {
    		return index >= 0 && index < this.length ? this[index] : null;
    	},
    	toString:function(isHTML,nodeFilter){
    		for(var buf = [], i = 0;i<this.length;i++){
    			serializeToString(this[i],buf,isHTML,nodeFilter);
    		}
    		return buf.join('');
    	},
    	/**
    	 * @private
    	 * @param {function (Node):boolean} predicate
    	 * @returns {Node[]}
    	 */
    	filter: function (predicate) {
    		return Array.prototype.filter.call(this, predicate);
    	},
    	/**
    	 * @private
    	 * @param {Node} item
    	 * @returns {number}
    	 */
    	indexOf: function (item) {
    		return Array.prototype.indexOf.call(this, item);
    	},
    };

    function LiveNodeList(node,refresh){
    	this._node = node;
    	this._refresh = refresh;
    	_updateLiveList(this);
    }
    function _updateLiveList(list){
    	var inc = list._node._inc || list._node.ownerDocument._inc;
    	if (list._inc !== inc) {
    		var ls = list._refresh(list._node);
    		__set__(list,'length',ls.length);
    		if (!list.$$length || ls.length < list.$$length) {
    			for (var i = ls.length; i in list; i++) {
    				if (Object.prototype.hasOwnProperty.call(list, i)) {
    					delete list[i];
    				}
    			}
    		}
    		copy(ls,list);
    		list._inc = inc;
    	}
    }
    LiveNodeList.prototype.item = function(i){
    	_updateLiveList(this);
    	return this[i] || null;
    };

    _extends(LiveNodeList,NodeList);

    /**
     * Objects implementing the NamedNodeMap interface are used
     * to represent collections of nodes that can be accessed by name.
     * Note that NamedNodeMap does not inherit from NodeList;
     * NamedNodeMaps are not maintained in any particular order.
     * Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index,
     * but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,
     * and does not imply that the DOM specifies an order to these Nodes.
     * NamedNodeMap objects in the DOM are live.
     * used for attributes or DocumentType entities
     */
    function NamedNodeMap() {
    };

    function _findNodeIndex(list,node){
    	var i = list.length;
    	while(i--){
    		if(list[i] === node){return i}
    	}
    }

    function _addNamedNode(el,list,newAttr,oldAttr){
    	if(oldAttr){
    		list[_findNodeIndex(list,oldAttr)] = newAttr;
    	}else {
    		list[list.length++] = newAttr;
    	}
    	if(el){
    		newAttr.ownerElement = el;
    		var doc = el.ownerDocument;
    		if(doc){
    			oldAttr && _onRemoveAttribute(doc,el,oldAttr);
    			_onAddAttribute(doc,el,newAttr);
    		}
    	}
    }
    function _removeNamedNode(el,list,attr){
    	//console.log('remove attr:'+attr)
    	var i = _findNodeIndex(list,attr);
    	if(i>=0){
    		var lastIndex = list.length-1;
    		while(i<lastIndex){
    			list[i] = list[++i];
    		}
    		list.length = lastIndex;
    		if(el){
    			var doc = el.ownerDocument;
    			if(doc){
    				_onRemoveAttribute(doc,el,attr);
    				attr.ownerElement = null;
    			}
    		}
    	}else {
    		throw new DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
    	}
    }
    NamedNodeMap.prototype = {
    	length:0,
    	item:NodeList.prototype.item,
    	getNamedItem: function(key) {
    //		if(key.indexOf(':')>0 || key == 'xmlns'){
    //			return null;
    //		}
    		//console.log()
    		var i = this.length;
    		while(i--){
    			var attr = this[i];
    			//console.log(attr.nodeName,key)
    			if(attr.nodeName == key){
    				return attr;
    			}
    		}
    	},
    	setNamedItem: function(attr) {
    		var el = attr.ownerElement;
    		if(el && el!=this._ownerElement){
    			throw new DOMException(INUSE_ATTRIBUTE_ERR);
    		}
    		var oldAttr = this.getNamedItem(attr.nodeName);
    		_addNamedNode(this._ownerElement,this,attr,oldAttr);
    		return oldAttr;
    	},
    	/* returns Node */
    	setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
    		var el = attr.ownerElement, oldAttr;
    		if(el && el!=this._ownerElement){
    			throw new DOMException(INUSE_ATTRIBUTE_ERR);
    		}
    		oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
    		_addNamedNode(this._ownerElement,this,attr,oldAttr);
    		return oldAttr;
    	},

    	/* returns Node */
    	removeNamedItem: function(key) {
    		var attr = this.getNamedItem(key);
    		_removeNamedNode(this._ownerElement,this,attr);
    		return attr;


    	},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR

    	//for level2
    	removeNamedItemNS:function(namespaceURI,localName){
    		var attr = this.getNamedItemNS(namespaceURI,localName);
    		_removeNamedNode(this._ownerElement,this,attr);
    		return attr;
    	},
    	getNamedItemNS: function(namespaceURI, localName) {
    		var i = this.length;
    		while(i--){
    			var node = this[i];
    			if(node.localName == localName && node.namespaceURI == namespaceURI){
    				return node;
    			}
    		}
    		return null;
    	}
    };

    /**
     * The DOMImplementation interface represents an object providing methods
     * which are not dependent on any particular document.
     * Such an object is returned by the `Document.implementation` property.
     *
     * __The individual methods describe the differences compared to the specs.__
     *
     * @constructor
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation MDN
     * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core (Initial)
     * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-102161490 DOM Level 2 Core
     * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490 DOM Level 3 Core
     * @see https://dom.spec.whatwg.org/#domimplementation DOM Living Standard
     */
    function DOMImplementation$2() {
    }

    DOMImplementation$2.prototype = {
    	/**
    	 * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported.
    	 * The different implementations fairly diverged in what kind of features were reported.
    	 * The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use.
    	 *
    	 * @deprecated It is deprecated and modern browsers return true in all cases.
    	 *
    	 * @param {string} feature
    	 * @param {string} [version]
    	 * @returns {boolean} always true
    	 *
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN
    	 * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core
    	 * @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard
    	 */
    	hasFeature: function(feature, version) {
    			return true;
    	},
    	/**
    	 * Creates an XML Document object of the specified type with its document element.
    	 *
    	 * __It behaves slightly different from the description in the living standard__:
    	 * - There is no interface/class `XMLDocument`, it returns a `Document` instance.
    	 * - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared.
    	 * - this implementation is not validating names or qualified names
    	 *   (when parsing XML strings, the SAX parser takes care of that)
    	 *
    	 * @param {string|null} namespaceURI
    	 * @param {string} qualifiedName
    	 * @param {DocumentType=null} doctype
    	 * @returns {Document}
    	 *
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN
    	 * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)
    	 * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument  DOM Level 2 Core
    	 *
    	 * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
    	 * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
    	 * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
    	 */
    	createDocument: function(namespaceURI,  qualifiedName, doctype){
    		var doc = new Document();
    		doc.implementation = this;
    		doc.childNodes = new NodeList();
    		doc.doctype = doctype || null;
    		if (doctype){
    			doc.appendChild(doctype);
    		}
    		if (qualifiedName){
    			var root = doc.createElementNS(namespaceURI, qualifiedName);
    			doc.appendChild(root);
    		}
    		return doc;
    	},
    	/**
    	 * Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.
    	 *
    	 * __This behavior is slightly different from the in the specs__:
    	 * - this implementation is not validating names or qualified names
    	 *   (when parsing XML strings, the SAX parser takes care of that)
    	 *
    	 * @param {string} qualifiedName
    	 * @param {string} [publicId]
    	 * @param {string} [systemId]
    	 * @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation
    	 * 				  or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()`
    	 *
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN
    	 * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core
    	 * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard
    	 *
    	 * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
    	 * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
    	 * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
    	 */
    	createDocumentType: function(qualifiedName, publicId, systemId){
    		var node = new DocumentType();
    		node.name = qualifiedName;
    		node.nodeName = qualifiedName;
    		node.publicId = publicId || '';
    		node.systemId = systemId || '';

    		return node;
    	}
    };


    /**
     * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
     */

    function Node() {
    };

    Node.prototype = {
    	firstChild : null,
    	lastChild : null,
    	previousSibling : null,
    	nextSibling : null,
    	attributes : null,
    	parentNode : null,
    	childNodes : null,
    	ownerDocument : null,
    	nodeValue : null,
    	namespaceURI : null,
    	prefix : null,
    	localName : null,
    	// Modified in DOM Level 2:
    	insertBefore:function(newChild, refChild){//raises
    		return _insertBefore(this,newChild,refChild);
    	},
    	replaceChild:function(newChild, oldChild){//raises
    		_insertBefore(this, newChild,oldChild, assertPreReplacementValidityInDocument);
    		if(oldChild){
    			this.removeChild(oldChild);
    		}
    	},
    	removeChild:function(oldChild){
    		return _removeChild(this,oldChild);
    	},
    	appendChild:function(newChild){
    		return this.insertBefore(newChild,null);
    	},
    	hasChildNodes:function(){
    		return this.firstChild != null;
    	},
    	cloneNode:function(deep){
    		return cloneNode(this.ownerDocument||this,this,deep);
    	},
    	// Modified in DOM Level 2:
    	normalize:function(){
    		var child = this.firstChild;
    		while(child){
    			var next = child.nextSibling;
    			if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
    				this.removeChild(next);
    				child.appendData(next.data);
    			}else {
    				child.normalize();
    				child = next;
    			}
    		}
    	},
      	// Introduced in DOM Level 2:
    	isSupported:function(feature, version){
    		return this.ownerDocument.implementation.hasFeature(feature,version);
    	},
        // Introduced in DOM Level 2:
        hasAttributes:function(){
        	return this.attributes.length>0;
        },
    	/**
    	 * Look up the prefix associated to the given namespace URI, starting from this node.
    	 * **The default namespace declarations are ignored by this method.**
    	 * See Namespace Prefix Lookup for details on the algorithm used by this method.
    	 *
    	 * _Note: The implementation seems to be incomplete when compared to the algorithm described in the specs._
    	 *
    	 * @param {string | null} namespaceURI
    	 * @returns {string | null}
    	 * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
    	 * @see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo
    	 * @see https://dom.spec.whatwg.org/#dom-node-lookupprefix
    	 * @see https://github.com/xmldom/xmldom/issues/322
    	 */
        lookupPrefix:function(namespaceURI){
        	var el = this;
        	while(el){
        		var map = el._nsMap;
        		//console.dir(map)
        		if(map){
        			for(var n in map){
    						if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) {
    							return n;
    						}
        			}
        		}
        		el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
        	}
        	return null;
        },
        // Introduced in DOM Level 3:
        lookupNamespaceURI:function(prefix){
        	var el = this;
        	while(el){
        		var map = el._nsMap;
        		//console.dir(map)
        		if(map){
        			if(Object.prototype.hasOwnProperty.call(map, prefix)){
        				return map[prefix] ;
        			}
        		}
        		el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
        	}
        	return null;
        },
        // Introduced in DOM Level 3:
        isDefaultNamespace:function(namespaceURI){
        	var prefix = this.lookupPrefix(namespaceURI);
        	return prefix == null;
        }
    };


    function _xmlEncoder(c){
    	return c == '<' && '&lt;' ||
             c == '>' && '&gt;' ||
             c == '&' && '&amp;' ||
             c == '"' && '&quot;' ||
             '&#'+c.charCodeAt()+';'
    }


    copy(NodeType,Node);
    copy(NodeType,Node.prototype);

    /**
     * @param callback return true for continue,false for break
     * @return boolean true: break visit;
     */
    function _visitNode(node,callback){
    	if(callback(node)){
    		return true;
    	}
    	if(node = node.firstChild){
    		do{
    			if(_visitNode(node,callback)){return true}
            }while(node=node.nextSibling)
        }
    }



    function Document(){
    	this.ownerDocument = this;
    }

    function _onAddAttribute(doc,el,newAttr){
    	doc && doc._inc++;
    	var ns = newAttr.namespaceURI ;
    	if(ns === NAMESPACE$2.XMLNS){
    		//update namespace
    		el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
    	}
    }

    function _onRemoveAttribute(doc,el,newAttr,remove){
    	doc && doc._inc++;
    	var ns = newAttr.namespaceURI ;
    	if(ns === NAMESPACE$2.XMLNS){
    		//update namespace
    		delete el._nsMap[newAttr.prefix?newAttr.localName:''];
    	}
    }

    /**
     * Updates `el.childNodes`, updating the indexed items and it's `length`.
     * Passing `newChild` means it will be appended.
     * Otherwise it's assumed that an item has been removed,
     * and `el.firstNode` and it's `.nextSibling` are used
     * to walk the current list of child nodes.
     *
     * @param {Document} doc
     * @param {Node} el
     * @param {Node} [newChild]
     * @private
     */
    function _onUpdateChild (doc, el, newChild) {
    	if(doc && doc._inc){
    		doc._inc++;
    		//update childNodes
    		var cs = el.childNodes;
    		if (newChild) {
    			cs[cs.length++] = newChild;
    		} else {
    			var child = el.firstChild;
    			var i = 0;
    			while (child) {
    				cs[i++] = child;
    				child = child.nextSibling;
    			}
    			cs.length = i;
    			delete cs[cs.length];
    		}
    	}
    }

    /**
     * Removes the connections between `parentNode` and `child`
     * and any existing `child.previousSibling` or `child.nextSibling`.
     *
     * @see https://github.com/xmldom/xmldom/issues/135
     * @see https://github.com/xmldom/xmldom/issues/145
     *
     * @param {Node} parentNode
     * @param {Node} child
     * @returns {Node} the child that was removed.
     * @private
     */
    function _removeChild (parentNode, child) {
    	var previous = child.previousSibling;
    	var next = child.nextSibling;
    	if (previous) {
    		previous.nextSibling = next;
    	} else {
    		parentNode.firstChild = next;
    	}
    	if (next) {
    		next.previousSibling = previous;
    	} else {
    		parentNode.lastChild = previous;
    	}
    	child.parentNode = null;
    	child.previousSibling = null;
    	child.nextSibling = null;
    	_onUpdateChild(parentNode.ownerDocument, parentNode);
    	return child;
    }

    /**
     * Returns `true` if `node` can be a parent for insertion.
     * @param {Node} node
     * @returns {boolean}
     */
    function hasValidParentNodeType(node) {
    	return (
    		node &&
    		(node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.ELEMENT_NODE)
    	);
    }

    /**
     * Returns `true` if `node` can be inserted according to it's `nodeType`.
     * @param {Node} node
     * @returns {boolean}
     */
    function hasInsertableNodeType(node) {
    	return (
    		node &&
    		(isElementNode(node) ||
    			isTextNode(node) ||
    			isDocTypeNode(node) ||
    			node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ||
    			node.nodeType === Node.COMMENT_NODE ||
    			node.nodeType === Node.PROCESSING_INSTRUCTION_NODE)
    	);
    }

    /**
     * Returns true if `node` is a DOCTYPE node
     * @param {Node} node
     * @returns {boolean}
     */
    function isDocTypeNode(node) {
    	return node && node.nodeType === Node.DOCUMENT_TYPE_NODE;
    }

    /**
     * Returns true if the node is an element
     * @param {Node} node
     * @returns {boolean}
     */
    function isElementNode(node) {
    	return node && node.nodeType === Node.ELEMENT_NODE;
    }
    /**
     * Returns true if `node` is a text node
     * @param {Node} node
     * @returns {boolean}
     */
    function isTextNode(node) {
    	return node && node.nodeType === Node.TEXT_NODE;
    }

    /**
     * Check if en element node can be inserted before `child`, or at the end if child is falsy,
     * according to the presence and position of a doctype node on the same level.
     *
     * @param {Document} doc The document node
     * @param {Node} child the node that would become the nextSibling if the element would be inserted
     * @returns {boolean} `true` if an element can be inserted before child
     * @private
     * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     */
    function isElementInsertionPossible(doc, child) {
    	var parentChildNodes = doc.childNodes || [];
    	if (find(parentChildNodes, isElementNode) || isDocTypeNode(child)) {
    		return false;
    	}
    	var docTypeNode = find(parentChildNodes, isDocTypeNode);
    	return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
    }

    /**
     * Check if en element node can be inserted before `child`, or at the end if child is falsy,
     * according to the presence and position of a doctype node on the same level.
     *
     * @param {Node} doc The document node
     * @param {Node} child the node that would become the nextSibling if the element would be inserted
     * @returns {boolean} `true` if an element can be inserted before child
     * @private
     * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     */
    function isElementReplacementPossible(doc, child) {
    	var parentChildNodes = doc.childNodes || [];

    	function hasElementChildThatIsNotChild(node) {
    		return isElementNode(node) && node !== child;
    	}

    	if (find(parentChildNodes, hasElementChildThatIsNotChild)) {
    		return false;
    	}
    	var docTypeNode = find(parentChildNodes, isDocTypeNode);
    	return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
    }

    /**
     * @private
     * Steps 1-5 of the checks before inserting and before replacing a child are the same.
     *
     * @param {Node} parent the parent node to insert `node` into
     * @param {Node} node the node to insert
     * @param {Node=} child the node that should become the `nextSibling` of `node`
     * @returns {Node}
     * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
     * @throws DOMException if `child` is provided but is not a child of `parent`.
     * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     * @see https://dom.spec.whatwg.org/#concept-node-replace
     */
    function assertPreInsertionValidity1to5(parent, node, child) {
    	// 1. If `parent` is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
    	if (!hasValidParentNodeType(parent)) {
    		throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType);
    	}
    	// 2. If `node` is a host-including inclusive ancestor of `parent`, then throw a "HierarchyRequestError" DOMException.
    	// not implemented!
    	// 3. If `child` is non-null and its parent is not `parent`, then throw a "NotFoundError" DOMException.
    	if (child && child.parentNode !== parent) {
    		throw new DOMException(NOT_FOUND_ERR, 'child not in parent');
    	}
    	if (
    		// 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
    		!hasInsertableNodeType(node) ||
    		// 5. If either `node` is a Text node and `parent` is a document,
    		// the sax parser currently adds top level text nodes, this will be fixed in 0.9.0
    		// || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE)
    		// or `node` is a doctype and `parent` is not a document, then throw a "HierarchyRequestError" DOMException.
    		(isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE)
    	) {
    		throw new DOMException(
    			HIERARCHY_REQUEST_ERR,
    			'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType
    		);
    	}
    }

    /**
     * @private
     * Step 6 of the checks before inserting and before replacing a child are different.
     *
     * @param {Document} parent the parent node to insert `node` into
     * @param {Node} node the node to insert
     * @param {Node | undefined} child the node that should become the `nextSibling` of `node`
     * @returns {Node}
     * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
     * @throws DOMException if `child` is provided but is not a child of `parent`.
     * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     * @see https://dom.spec.whatwg.org/#concept-node-replace
     */
    function assertPreInsertionValidityInDocument(parent, node, child) {
    	var parentChildNodes = parent.childNodes || [];
    	var nodeChildNodes = node.childNodes || [];

    	// DocumentFragment
    	if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
    		var nodeChildElements = nodeChildNodes.filter(isElementNode);
    		// If node has more than one element child or has a Text node child.
    		if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
    		}
    		// Otherwise, if `node` has one element child and either `parent` has an element child,
    		// `child` is a doctype, or `child` is non-null and a doctype is following `child`.
    		if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
    		}
    	}
    	// Element
    	if (isElementNode(node)) {
    		// `parent` has an element child, `child` is a doctype,
    		// or `child` is non-null and a doctype is following `child`.
    		if (!isElementInsertionPossible(parent, child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
    		}
    	}
    	// DocumentType
    	if (isDocTypeNode(node)) {
    		// `parent` has a doctype child,
    		if (find(parentChildNodes, isDocTypeNode)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
    		}
    		var parentElementChild = find(parentChildNodes, isElementNode);
    		// `child` is non-null and an element is preceding `child`,
    		if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
    		}
    		// or `child` is null and `parent` has an element child.
    		if (!child && parentElementChild) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
    		}
    	}
    }

    /**
     * @private
     * Step 6 of the checks before inserting and before replacing a child are different.
     *
     * @param {Document} parent the parent node to insert `node` into
     * @param {Node} node the node to insert
     * @param {Node | undefined} child the node that should become the `nextSibling` of `node`
     * @returns {Node}
     * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
     * @throws DOMException if `child` is provided but is not a child of `parent`.
     * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     * @see https://dom.spec.whatwg.org/#concept-node-replace
     */
    function assertPreReplacementValidityInDocument(parent, node, child) {
    	var parentChildNodes = parent.childNodes || [];
    	var nodeChildNodes = node.childNodes || [];

    	// DocumentFragment
    	if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
    		var nodeChildElements = nodeChildNodes.filter(isElementNode);
    		// If `node` has more than one element child or has a Text node child.
    		if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
    		}
    		// Otherwise, if `node` has one element child and either `parent` has an element child that is not `child` or a doctype is following `child`.
    		if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
    		}
    	}
    	// Element
    	if (isElementNode(node)) {
    		// `parent` has an element child that is not `child` or a doctype is following `child`.
    		if (!isElementReplacementPossible(parent, child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
    		}
    	}
    	// DocumentType
    	if (isDocTypeNode(node)) {
    		function hasDoctypeChildThatIsNotChild(node) {
    			return isDocTypeNode(node) && node !== child;
    		}

    		// `parent` has a doctype child that is not `child`,
    		if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
    		}
    		var parentElementChild = find(parentChildNodes, isElementNode);
    		// or an element is preceding `child`.
    		if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
    			throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
    		}
    	}
    }

    /**
     * @private
     * @param {Node} parent the parent node to insert `node` into
     * @param {Node} node the node to insert
     * @param {Node=} child the node that should become the `nextSibling` of `node`
     * @returns {Node}
     * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
     * @throws DOMException if `child` is provided but is not a child of `parent`.
     * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
     */
    function _insertBefore(parent, node, child, _inDocumentAssertion) {
    	// To ensure pre-insertion validity of a node into a parent before a child, run these steps:
    	assertPreInsertionValidity1to5(parent, node, child);

    	// If parent is a document, and any of the statements below, switched on the interface node implements,
    	// are true, then throw a "HierarchyRequestError" DOMException.
    	if (parent.nodeType === Node.DOCUMENT_NODE) {
    		(_inDocumentAssertion || assertPreInsertionValidityInDocument)(parent, node, child);
    	}

    	var cp = node.parentNode;
    	if(cp){
    		cp.removeChild(node);//remove and update
    	}
    	if(node.nodeType === DOCUMENT_FRAGMENT_NODE){
    		var newFirst = node.firstChild;
    		if (newFirst == null) {
    			return node;
    		}
    		var newLast = node.lastChild;
    	}else {
    		newFirst = newLast = node;
    	}
    	var pre = child ? child.previousSibling : parent.lastChild;

    	newFirst.previousSibling = pre;
    	newLast.nextSibling = child;


    	if(pre){
    		pre.nextSibling = newFirst;
    	}else {
    		parent.firstChild = newFirst;
    	}
    	if(child == null){
    		parent.lastChild = newLast;
    	}else {
    		child.previousSibling = newLast;
    	}
    	do{
    		newFirst.parentNode = parent;
    	}while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
    	_onUpdateChild(parent.ownerDocument||parent, parent);
    	//console.log(parent.lastChild.nextSibling == null)
    	if (node.nodeType == DOCUMENT_FRAGMENT_NODE) {
    		node.firstChild = node.lastChild = null;
    	}
    	return node;
    }

    /**
     * Appends `newChild` to `parentNode`.
     * If `newChild` is already connected to a `parentNode` it is first removed from it.
     *
     * @see https://github.com/xmldom/xmldom/issues/135
     * @see https://github.com/xmldom/xmldom/issues/145
     * @param {Node} parentNode
     * @param {Node} newChild
     * @returns {Node}
     * @private
     */
    function _appendSingleChild (parentNode, newChild) {
    	if (newChild.parentNode) {
    		newChild.parentNode.removeChild(newChild);
    	}
    	newChild.parentNode = parentNode;
    	newChild.previousSibling = parentNode.lastChild;
    	newChild.nextSibling = null;
    	if (newChild.previousSibling) {
    		newChild.previousSibling.nextSibling = newChild;
    	} else {
    		parentNode.firstChild = newChild;
    	}
    	parentNode.lastChild = newChild;
    	_onUpdateChild(parentNode.ownerDocument, parentNode, newChild);
    	return newChild;
    }

    Document.prototype = {
    	//implementation : null,
    	nodeName :  '#document',
    	nodeType :  DOCUMENT_NODE,
    	/**
    	 * The DocumentType node of the document.
    	 *
    	 * @readonly
    	 * @type DocumentType
    	 */
    	doctype :  null,
    	documentElement :  null,
    	_inc : 1,

    	insertBefore :  function(newChild, refChild){//raises
    		if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
    			var child = newChild.firstChild;
    			while(child){
    				var next = child.nextSibling;
    				this.insertBefore(child,refChild);
    				child = next;
    			}
    			return newChild;
    		}
    		_insertBefore(this, newChild, refChild);
    		newChild.ownerDocument = this;
    		if (this.documentElement === null && newChild.nodeType === ELEMENT_NODE) {
    			this.documentElement = newChild;
    		}

    		return newChild;
    	},
    	removeChild :  function(oldChild){
    		if(this.documentElement == oldChild){
    			this.documentElement = null;
    		}
    		return _removeChild(this,oldChild);
    	},
    	replaceChild: function (newChild, oldChild) {
    		//raises
    		_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
    		newChild.ownerDocument = this;
    		if (oldChild) {
    			this.removeChild(oldChild);
    		}
    		if (isElementNode(newChild)) {
    			this.documentElement = newChild;
    		}
    	},
    	// Introduced in DOM Level 2:
    	importNode : function(importedNode,deep){
    		return importNode(this,importedNode,deep);
    	},
    	// Introduced in DOM Level 2:
    	getElementById :	function(id){
    		var rtv = null;
    		_visitNode(this.documentElement,function(node){
    			if(node.nodeType == ELEMENT_NODE){
    				if(node.getAttribute('id') == id){
    					rtv = node;
    					return true;
    				}
    			}
    		});
    		return rtv;
    	},

    	/**
    	 * The `getElementsByClassName` method of `Document` interface returns an array-like object
    	 * of all child elements which have **all** of the given class name(s).
    	 *
    	 * Returns an empty list if `classeNames` is an empty string or only contains HTML white space characters.
    	 *
    	 *
    	 * Warning: This is a live LiveNodeList.
    	 * Changes in the DOM will reflect in the array as the changes occur.
    	 * If an element selected by this array no longer qualifies for the selector,
    	 * it will automatically be removed. Be aware of this for iteration purposes.
    	 *
    	 * @param {string} classNames is a string representing the class name(s) to match; multiple class names are separated by (ASCII-)whitespace
    	 *
    	 * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
    	 * @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname
    	 */
    	getElementsByClassName: function(classNames) {
    		var classNamesSet = toOrderedSet(classNames);
    		return new LiveNodeList(this, function(base) {
    			var ls = [];
    			if (classNamesSet.length > 0) {
    				_visitNode(base.documentElement, function(node) {
    					if(node !== base && node.nodeType === ELEMENT_NODE) {
    						var nodeClassNames = node.getAttribute('class');
    						// can be null if the attribute does not exist
    						if (nodeClassNames) {
    							// before splitting and iterating just compare them for the most common case
    							var matches = classNames === nodeClassNames;
    							if (!matches) {
    								var nodeClassNamesSet = toOrderedSet(nodeClassNames);
    								matches = classNamesSet.every(arrayIncludes(nodeClassNamesSet));
    							}
    							if(matches) {
    								ls.push(node);
    							}
    						}
    					}
    				});
    			}
    			return ls;
    		});
    	},

    	//document factory method:
    	createElement :	function(tagName){
    		var node = new Element();
    		node.ownerDocument = this;
    		node.nodeName = tagName;
    		node.tagName = tagName;
    		node.localName = tagName;
    		node.childNodes = new NodeList();
    		var attrs	= node.attributes = new NamedNodeMap();
    		attrs._ownerElement = node;
    		return node;
    	},
    	createDocumentFragment :	function(){
    		var node = new DocumentFragment();
    		node.ownerDocument = this;
    		node.childNodes = new NodeList();
    		return node;
    	},
    	createTextNode :	function(data){
    		var node = new Text$1();
    		node.ownerDocument = this;
    		node.appendData(data);
    		return node;
    	},
    	createComment :	function(data){
    		var node = new Comment();
    		node.ownerDocument = this;
    		node.appendData(data);
    		return node;
    	},
    	createCDATASection :	function(data){
    		var node = new CDATASection();
    		node.ownerDocument = this;
    		node.appendData(data);
    		return node;
    	},
    	createProcessingInstruction :	function(target,data){
    		var node = new ProcessingInstruction();
    		node.ownerDocument = this;
    		node.tagName = node.nodeName = node.target = target;
    		node.nodeValue = node.data = data;
    		return node;
    	},
    	createAttribute :	function(name){
    		var node = new Attr();
    		node.ownerDocument	= this;
    		node.name = name;
    		node.nodeName	= name;
    		node.localName = name;
    		node.specified = true;
    		return node;
    	},
    	createEntityReference :	function(name){
    		var node = new EntityReference();
    		node.ownerDocument	= this;
    		node.nodeName	= name;
    		return node;
    	},
    	// Introduced in DOM Level 2:
    	createElementNS :	function(namespaceURI,qualifiedName){
    		var node = new Element();
    		var pl = qualifiedName.split(':');
    		var attrs	= node.attributes = new NamedNodeMap();
    		node.childNodes = new NodeList();
    		node.ownerDocument = this;
    		node.nodeName = qualifiedName;
    		node.tagName = qualifiedName;
    		node.namespaceURI = namespaceURI;
    		if(pl.length == 2){
    			node.prefix = pl[0];
    			node.localName = pl[1];
    		}else {
    			//el.prefix = null;
    			node.localName = qualifiedName;
    		}
    		attrs._ownerElement = node;
    		return node;
    	},
    	// Introduced in DOM Level 2:
    	createAttributeNS :	function(namespaceURI,qualifiedName){
    		var node = new Attr();
    		var pl = qualifiedName.split(':');
    		node.ownerDocument = this;
    		node.nodeName = qualifiedName;
    		node.name = qualifiedName;
    		node.namespaceURI = namespaceURI;
    		node.specified = true;
    		if(pl.length == 2){
    			node.prefix = pl[0];
    			node.localName = pl[1];
    		}else {
    			//el.prefix = null;
    			node.localName = qualifiedName;
    		}
    		return node;
    	}
    };
    _extends(Document,Node);


    function Element() {
    	this._nsMap = {};
    };
    Element.prototype = {
    	nodeType : ELEMENT_NODE,
    	hasAttribute : function(name){
    		return this.getAttributeNode(name)!=null;
    	},
    	getAttribute : function(name){
    		var attr = this.getAttributeNode(name);
    		return attr && attr.value || '';
    	},
    	getAttributeNode : function(name){
    		return this.attributes.getNamedItem(name);
    	},
    	setAttribute : function(name, value){
    		var attr = this.ownerDocument.createAttribute(name);
    		attr.value = attr.nodeValue = "" + value;
    		this.setAttributeNode(attr);
    	},
    	removeAttribute : function(name){
    		var attr = this.getAttributeNode(name);
    		attr && this.removeAttributeNode(attr);
    	},

    	//four real opeartion method
    	appendChild:function(newChild){
    		if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
    			return this.insertBefore(newChild,null);
    		}else {
    			return _appendSingleChild(this,newChild);
    		}
    	},
    	setAttributeNode : function(newAttr){
    		return this.attributes.setNamedItem(newAttr);
    	},
    	setAttributeNodeNS : function(newAttr){
    		return this.attributes.setNamedItemNS(newAttr);
    	},
    	removeAttributeNode : function(oldAttr){
    		//console.log(this == oldAttr.ownerElement)
    		return this.attributes.removeNamedItem(oldAttr.nodeName);
    	},
    	//get real attribute name,and remove it by removeAttributeNode
    	removeAttributeNS : function(namespaceURI, localName){
    		var old = this.getAttributeNodeNS(namespaceURI, localName);
    		old && this.removeAttributeNode(old);
    	},

    	hasAttributeNS : function(namespaceURI, localName){
    		return this.getAttributeNodeNS(namespaceURI, localName)!=null;
    	},
    	getAttributeNS : function(namespaceURI, localName){
    		var attr = this.getAttributeNodeNS(namespaceURI, localName);
    		return attr && attr.value || '';
    	},
    	setAttributeNS : function(namespaceURI, qualifiedName, value){
    		var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
    		attr.value = attr.nodeValue = "" + value;
    		this.setAttributeNode(attr);
    	},
    	getAttributeNodeNS : function(namespaceURI, localName){
    		return this.attributes.getNamedItemNS(namespaceURI, localName);
    	},

    	getElementsByTagName : function(tagName){
    		return new LiveNodeList(this,function(base){
    			var ls = [];
    			_visitNode(base,function(node){
    				if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
    					ls.push(node);
    				}
    			});
    			return ls;
    		});
    	},
    	getElementsByTagNameNS : function(namespaceURI, localName){
    		return new LiveNodeList(this,function(base){
    			var ls = [];
    			_visitNode(base,function(node){
    				if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
    					ls.push(node);
    				}
    			});
    			return ls;

    		});
    	}
    };
    Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
    Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;


    _extends(Element,Node);
    function Attr() {
    };
    Attr.prototype.nodeType = ATTRIBUTE_NODE;
    _extends(Attr,Node);


    function CharacterData() {
    };
    CharacterData.prototype = {
    	data : '',
    	substringData : function(offset, count) {
    		return this.data.substring(offset, offset+count);
    	},
    	appendData: function(text) {
    		text = this.data+text;
    		this.nodeValue = this.data = text;
    		this.length = text.length;
    	},
    	insertData: function(offset,text) {
    		this.replaceData(offset,0,text);

    	},
    	appendChild:function(newChild){
    		throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
    	},
    	deleteData: function(offset, count) {
    		this.replaceData(offset,count,"");
    	},
    	replaceData: function(offset, count, text) {
    		var start = this.data.substring(0,offset);
    		var end = this.data.substring(offset+count);
    		text = start + text + end;
    		this.nodeValue = this.data = text;
    		this.length = text.length;
    	}
    };
    _extends(CharacterData,Node);
    function Text$1() {
    };
    Text$1.prototype = {
    	nodeName : "#text",
    	nodeType : TEXT_NODE,
    	splitText : function(offset) {
    		var text = this.data;
    		var newText = text.substring(offset);
    		text = text.substring(0, offset);
    		this.data = this.nodeValue = text;
    		this.length = text.length;
    		var newNode = this.ownerDocument.createTextNode(newText);
    		if(this.parentNode){
    			this.parentNode.insertBefore(newNode, this.nextSibling);
    		}
    		return newNode;
    	}
    };
    _extends(Text$1,CharacterData);
    function Comment() {
    };
    Comment.prototype = {
    	nodeName : "#comment",
    	nodeType : COMMENT_NODE
    };
    _extends(Comment,CharacterData);

    function CDATASection() {
    };
    CDATASection.prototype = {
    	nodeName : "#cdata-section",
    	nodeType : CDATA_SECTION_NODE
    };
    _extends(CDATASection,CharacterData);


    function DocumentType() {
    };
    DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
    _extends(DocumentType,Node);

    function Notation() {
    };
    Notation.prototype.nodeType = NOTATION_NODE;
    _extends(Notation,Node);

    function Entity() {
    };
    Entity.prototype.nodeType = ENTITY_NODE;
    _extends(Entity,Node);

    function EntityReference() {
    };
    EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
    _extends(EntityReference,Node);

    function DocumentFragment() {
    };
    DocumentFragment.prototype.nodeName =	"#document-fragment";
    DocumentFragment.prototype.nodeType =	DOCUMENT_FRAGMENT_NODE;
    _extends(DocumentFragment,Node);


    function ProcessingInstruction() {
    }
    ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
    _extends(ProcessingInstruction,Node);
    function XMLSerializer$2(){}
    XMLSerializer$2.prototype.serializeToString = function(node,isHtml,nodeFilter){
    	return nodeSerializeToString.call(node,isHtml,nodeFilter);
    };
    Node.prototype.toString = nodeSerializeToString;
    function nodeSerializeToString(isHtml,nodeFilter){
    	var buf = [];
    	var refNode = this.nodeType == 9 && this.documentElement || this;
    	var prefix = refNode.prefix;
    	var uri = refNode.namespaceURI;

    	if(uri && prefix == null){
    		//console.log(prefix)
    		var prefix = refNode.lookupPrefix(uri);
    		if(prefix == null){
    			//isHTML = true;
    			var visibleNamespaces=[
    			{namespace:uri,prefix:null}
    			//{namespace:uri,prefix:''}
    			];
    		}
    	}
    	serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
    	//console.log('###',this.nodeType,uri,prefix,buf.join(''))
    	return buf.join('');
    }

    function needNamespaceDefine(node, isHTML, visibleNamespaces) {
    	var prefix = node.prefix || '';
    	var uri = node.namespaceURI;
    	// According to [Namespaces in XML 1.0](https://www.w3.org/TR/REC-xml-names/#ns-using) ,
    	// and more specifically https://www.w3.org/TR/REC-xml-names/#nsc-NoPrefixUndecl :
    	// > In a namespace declaration for a prefix [...], the attribute value MUST NOT be empty.
    	// in a similar manner [Namespaces in XML 1.1](https://www.w3.org/TR/xml-names11/#ns-using)
    	// and more specifically https://www.w3.org/TR/xml-names11/#nsc-NSDeclared :
    	// > [...] Furthermore, the attribute value [...] must not be an empty string.
    	// so serializing empty namespace value like xmlns:ds="" would produce an invalid XML document.
    	if (!uri) {
    		return false;
    	}
    	if (prefix === "xml" && uri === NAMESPACE$2.XML || uri === NAMESPACE$2.XMLNS) {
    		return false;
    	}

    	var i = visibleNamespaces.length;
    	while (i--) {
    		var ns = visibleNamespaces[i];
    		// get namespace prefix
    		if (ns.prefix === prefix) {
    			return ns.namespace !== uri;
    		}
    	}
    	return true;
    }
    /**
     * Well-formed constraint: No < in Attribute Values
     * > The replacement text of any entity referred to directly or indirectly
     * > in an attribute value must not contain a <.
     * @see https://www.w3.org/TR/xml11/#CleanAttrVals
     * @see https://www.w3.org/TR/xml11/#NT-AttValue
     *
     * Literal whitespace other than space that appear in attribute values
     * are serialized as their entity references, so they will be preserved.
     * (In contrast to whitespace literals in the input which are normalized to spaces)
     * @see https://www.w3.org/TR/xml11/#AVNormalize
     * @see https://w3c.github.io/DOM-Parsing/#serializing-an-element-s-attributes
     */
    function addSerializedAttribute(buf, qualifiedName, value) {
    	buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"');
    }

    function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
    	if (!visibleNamespaces) {
    		visibleNamespaces = [];
    	}

    	if(nodeFilter){
    		node = nodeFilter(node);
    		if(node){
    			if(typeof node == 'string'){
    				buf.push(node);
    				return;
    			}
    		}else {
    			return;
    		}
    		//buf.sort.apply(attrs, attributeSorter);
    	}

    	switch(node.nodeType){
    	case ELEMENT_NODE:
    		var attrs = node.attributes;
    		var len = attrs.length;
    		var child = node.firstChild;
    		var nodeName = node.tagName;

    		isHTML = NAMESPACE$2.isHTML(node.namespaceURI) || isHTML;

    		var prefixedNodeName = nodeName;
    		if (!isHTML && !node.prefix && node.namespaceURI) {
    			var defaultNS;
    			// lookup current default ns from `xmlns` attribute
    			for (var ai = 0; ai < attrs.length; ai++) {
    				if (attrs.item(ai).name === 'xmlns') {
    					defaultNS = attrs.item(ai).value;
    					break
    				}
    			}
    			if (!defaultNS) {
    				// lookup current default ns in visibleNamespaces
    				for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
    					var namespace = visibleNamespaces[nsi];
    					if (namespace.prefix === '' && namespace.namespace === node.namespaceURI) {
    						defaultNS = namespace.namespace;
    						break
    					}
    				}
    			}
    			if (defaultNS !== node.namespaceURI) {
    				for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
    					var namespace = visibleNamespaces[nsi];
    					if (namespace.namespace === node.namespaceURI) {
    						if (namespace.prefix) {
    							prefixedNodeName = namespace.prefix + ':' + nodeName;
    						}
    						break
    					}
    				}
    			}
    		}

    		buf.push('<', prefixedNodeName);

    		for(var i=0;i<len;i++){
    			// add namespaces for attributes
    			var attr = attrs.item(i);
    			if (attr.prefix == 'xmlns') {
    				visibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });
    			}else if(attr.nodeName == 'xmlns'){
    				visibleNamespaces.push({ prefix: '', namespace: attr.value });
    			}
    		}

    		for(var i=0;i<len;i++){
    			var attr = attrs.item(i);
    			if (needNamespaceDefine(attr,isHTML, visibleNamespaces)) {
    				var prefix = attr.prefix||'';
    				var uri = attr.namespaceURI;
    				addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
    				visibleNamespaces.push({ prefix: prefix, namespace:uri });
    			}
    			serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
    		}

    		// add namespace for current node
    		if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) {
    			var prefix = node.prefix||'';
    			var uri = node.namespaceURI;
    			addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
    			visibleNamespaces.push({ prefix: prefix, namespace:uri });
    		}

    		if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
    			buf.push('>');
    			//if is cdata child node
    			if(isHTML && /^script$/i.test(nodeName)){
    				while(child){
    					if(child.data){
    						buf.push(child.data);
    					}else {
    						serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
    					}
    					child = child.nextSibling;
    				}
    			}else
    			{
    				while(child){
    					serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
    					child = child.nextSibling;
    				}
    			}
    			buf.push('</',prefixedNodeName,'>');
    		}else {
    			buf.push('/>');
    		}
    		// remove added visible namespaces
    		//visibleNamespaces.length = startVisibleNamespaces;
    		return;
    	case DOCUMENT_NODE:
    	case DOCUMENT_FRAGMENT_NODE:
    		var child = node.firstChild;
    		while(child){
    			serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
    			child = child.nextSibling;
    		}
    		return;
    	case ATTRIBUTE_NODE:
    		return addSerializedAttribute(buf, node.name, node.value);
    	case TEXT_NODE:
    		/**
    		 * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
    		 * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.
    		 * If they are needed elsewhere, they must be escaped using either numeric character references or the strings
    		 * `&amp;` and `&lt;` respectively.
    		 * The right angle bracket (>) may be represented using the string " &gt; ", and must, for compatibility,
    		 * be escaped using either `&gt;` or a character reference when it appears in the string `]]>` in content,
    		 * when that string is not marking the end of a CDATA section.
    		 *
    		 * In the content of elements, character data is any string of characters
    		 * which does not contain the start-delimiter of any markup
    		 * and does not include the CDATA-section-close delimiter, `]]>`.
    		 *
    		 * @see https://www.w3.org/TR/xml/#NT-CharData
    		 * @see https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node
    		 */
    		return buf.push(node.data
    			.replace(/[<&>]/g,_xmlEncoder)
    		);
    	case CDATA_SECTION_NODE:
    		return buf.push( '<![CDATA[',node.data,']]>');
    	case COMMENT_NODE:
    		return buf.push( "<!--",node.data,"-->");
    	case DOCUMENT_TYPE_NODE:
    		var pubid = node.publicId;
    		var sysid = node.systemId;
    		buf.push('<!DOCTYPE ',node.name);
    		if(pubid){
    			buf.push(' PUBLIC ', pubid);
    			if (sysid && sysid!='.') {
    				buf.push(' ', sysid);
    			}
    			buf.push('>');
    		}else if(sysid && sysid!='.'){
    			buf.push(' SYSTEM ', sysid, '>');
    		}else {
    			var sub = node.internalSubset;
    			if(sub){
    				buf.push(" [",sub,"]");
    			}
    			buf.push(">");
    		}
    		return;
    	case PROCESSING_INSTRUCTION_NODE:
    		return buf.push( "<?",node.target," ",node.data,"?>");
    	case ENTITY_REFERENCE_NODE:
    		return buf.push( '&',node.nodeName,';');
    	//case ENTITY_NODE:
    	//case NOTATION_NODE:
    	default:
    		buf.push('??',node.nodeName);
    	}
    }
    function importNode(doc,node,deep){
    	var node2;
    	switch (node.nodeType) {
    	case ELEMENT_NODE:
    		node2 = node.cloneNode(false);
    		node2.ownerDocument = doc;
    		//var attrs = node2.attributes;
    		//var len = attrs.length;
    		//for(var i=0;i<len;i++){
    			//node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
    		//}
    	case DOCUMENT_FRAGMENT_NODE:
    		break;
    	case ATTRIBUTE_NODE:
    		deep = true;
    		break;
    	//case ENTITY_REFERENCE_NODE:
    	//case PROCESSING_INSTRUCTION_NODE:
    	////case TEXT_NODE:
    	//case CDATA_SECTION_NODE:
    	//case COMMENT_NODE:
    	//	deep = false;
    	//	break;
    	//case DOCUMENT_NODE:
    	//case DOCUMENT_TYPE_NODE:
    	//cannot be imported.
    	//case ENTITY_NODE:
    	//case NOTATION_NODE：
    	//can not hit in level3
    	//default:throw e;
    	}
    	if(!node2){
    		node2 = node.cloneNode(false);//false
    	}
    	node2.ownerDocument = doc;
    	node2.parentNode = null;
    	if(deep){
    		var child = node.firstChild;
    		while(child){
    			node2.appendChild(importNode(doc,child,deep));
    			child = child.nextSibling;
    		}
    	}
    	return node2;
    }
    //
    //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
    //					attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
    function cloneNode(doc,node,deep){
    	var node2 = new node.constructor();
    	for (var n in node) {
    		if (Object.prototype.hasOwnProperty.call(node, n)) {
    			var v = node[n];
    			if (typeof v != "object") {
    				if (v != node2[n]) {
    					node2[n] = v;
    				}
    			}
    		}
    	}
    	if(node.childNodes){
    		node2.childNodes = new NodeList();
    	}
    	node2.ownerDocument = doc;
    	switch (node2.nodeType) {
    	case ELEMENT_NODE:
    		var attrs	= node.attributes;
    		var attrs2	= node2.attributes = new NamedNodeMap();
    		var len = attrs.length;
    		attrs2._ownerElement = node2;
    		for(var i=0;i<len;i++){
    			node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
    		}
    		break;;
    	case ATTRIBUTE_NODE:
    		deep = true;
    	}
    	if(deep){
    		var child = node.firstChild;
    		while(child){
    			node2.appendChild(cloneNode(doc,child,deep));
    			child = child.nextSibling;
    		}
    	}
    	return node2;
    }

    function __set__(object,key,value){
    	object[key] = value;
    }
    //do dynamic
    try{
    	if(Object.defineProperty){
    		Object.defineProperty(LiveNodeList.prototype,'length',{
    			get:function(){
    				_updateLiveList(this);
    				return this.$$length;
    			}
    		});

    		Object.defineProperty(Node.prototype,'textContent',{
    			get:function(){
    				return getTextContent(this);
    			},

    			set:function(data){
    				switch(this.nodeType){
    				case ELEMENT_NODE:
    				case DOCUMENT_FRAGMENT_NODE:
    					while(this.firstChild){
    						this.removeChild(this.firstChild);
    					}
    					if(data || String(data)){
    						this.appendChild(this.ownerDocument.createTextNode(data));
    					}
    					break;

    				default:
    					this.data = data;
    					this.value = data;
    					this.nodeValue = data;
    				}
    			}
    		});

    		function getTextContent(node){
    			switch(node.nodeType){
    			case ELEMENT_NODE:
    			case DOCUMENT_FRAGMENT_NODE:
    				var buf = [];
    				node = node.firstChild;
    				while(node){
    					if(node.nodeType!==7 && node.nodeType !==8){
    						buf.push(getTextContent(node));
    					}
    					node = node.nextSibling;
    				}
    				return buf.join('');
    			default:
    				return node.nodeValue;
    			}
    		}

    		__set__ = function(object,key,value){
    			//console.log(value)
    			object['$$'+key] = value;
    		};
    	}
    }catch(e){//ie8
    }

    //if(typeof require == 'function'){
    	var DocumentType_1 = dom$2.DocumentType = DocumentType;
    	var DOMException_1 = dom$2.DOMException = DOMException;
    	var DOMImplementation_1 = dom$2.DOMImplementation = DOMImplementation$2;
    	var Element_1 = dom$2.Element = Element;
    	var Node_1 = dom$2.Node = Node;
    	var NodeList_1 = dom$2.NodeList = NodeList;
    	var XMLSerializer_1 = dom$2.XMLSerializer = XMLSerializer$2;

    var domParser = {};

    var entities$2 = {};

    (function (exports) {
    	'use strict';

    	var freeze = conventions$2.freeze;

    	/**
    	 * The entities that are predefined in every XML document.
    	 *
    	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#sec-predefined-ent W3C XML 1.1
    	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent W3C XML 1.0
    	 * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML Wikipedia
    	 */
    	exports.XML_ENTITIES = freeze({
    		amp: '&',
    		apos: "'",
    		gt: '>',
    		lt: '<',
    		quot: '"',
    	});

    	/**
    	 * A map of all entities that are detected in an HTML document.
    	 * They contain all entries from `XML_ENTITIES`.
    	 *
    	 * @see XML_ENTITIES
    	 * @see DOMParser.parseFromString
    	 * @see DOMImplementation.prototype.createHTMLDocument
    	 * @see https://html.spec.whatwg.org/#named-character-references WHATWG HTML(5) Spec
    	 * @see https://html.spec.whatwg.org/entities.json JSON
    	 * @see https://www.w3.org/TR/xml-entity-names/ W3C XML Entity Names
    	 * @see https://www.w3.org/TR/html4/sgml/entities.html W3C HTML4/SGML
    	 * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_entity_references_in_HTML Wikipedia (HTML)
    	 * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Entities_representing_special_characters_in_XHTML Wikpedia (XHTML)
    	 */
    	exports.HTML_ENTITIES = freeze({
    		Aacute: '\u00C1',
    		aacute: '\u00E1',
    		Abreve: '\u0102',
    		abreve: '\u0103',
    		ac: '\u223E',
    		acd: '\u223F',
    		acE: '\u223E\u0333',
    		Acirc: '\u00C2',
    		acirc: '\u00E2',
    		acute: '\u00B4',
    		Acy: '\u0410',
    		acy: '\u0430',
    		AElig: '\u00C6',
    		aelig: '\u00E6',
    		af: '\u2061',
    		Afr: '\uD835\uDD04',
    		afr: '\uD835\uDD1E',
    		Agrave: '\u00C0',
    		agrave: '\u00E0',
    		alefsym: '\u2135',
    		aleph: '\u2135',
    		Alpha: '\u0391',
    		alpha: '\u03B1',
    		Amacr: '\u0100',
    		amacr: '\u0101',
    		amalg: '\u2A3F',
    		AMP: '\u0026',
    		amp: '\u0026',
    		And: '\u2A53',
    		and: '\u2227',
    		andand: '\u2A55',
    		andd: '\u2A5C',
    		andslope: '\u2A58',
    		andv: '\u2A5A',
    		ang: '\u2220',
    		ange: '\u29A4',
    		angle: '\u2220',
    		angmsd: '\u2221',
    		angmsdaa: '\u29A8',
    		angmsdab: '\u29A9',
    		angmsdac: '\u29AA',
    		angmsdad: '\u29AB',
    		angmsdae: '\u29AC',
    		angmsdaf: '\u29AD',
    		angmsdag: '\u29AE',
    		angmsdah: '\u29AF',
    		angrt: '\u221F',
    		angrtvb: '\u22BE',
    		angrtvbd: '\u299D',
    		angsph: '\u2222',
    		angst: '\u00C5',
    		angzarr: '\u237C',
    		Aogon: '\u0104',
    		aogon: '\u0105',
    		Aopf: '\uD835\uDD38',
    		aopf: '\uD835\uDD52',
    		ap: '\u2248',
    		apacir: '\u2A6F',
    		apE: '\u2A70',
    		ape: '\u224A',
    		apid: '\u224B',
    		apos: '\u0027',
    		ApplyFunction: '\u2061',
    		approx: '\u2248',
    		approxeq: '\u224A',
    		Aring: '\u00C5',
    		aring: '\u00E5',
    		Ascr: '\uD835\uDC9C',
    		ascr: '\uD835\uDCB6',
    		Assign: '\u2254',
    		ast: '\u002A',
    		asymp: '\u2248',
    		asympeq: '\u224D',
    		Atilde: '\u00C3',
    		atilde: '\u00E3',
    		Auml: '\u00C4',
    		auml: '\u00E4',
    		awconint: '\u2233',
    		awint: '\u2A11',
    		backcong: '\u224C',
    		backepsilon: '\u03F6',
    		backprime: '\u2035',
    		backsim: '\u223D',
    		backsimeq: '\u22CD',
    		Backslash: '\u2216',
    		Barv: '\u2AE7',
    		barvee: '\u22BD',
    		Barwed: '\u2306',
    		barwed: '\u2305',
    		barwedge: '\u2305',
    		bbrk: '\u23B5',
    		bbrktbrk: '\u23B6',
    		bcong: '\u224C',
    		Bcy: '\u0411',
    		bcy: '\u0431',
    		bdquo: '\u201E',
    		becaus: '\u2235',
    		Because: '\u2235',
    		because: '\u2235',
    		bemptyv: '\u29B0',
    		bepsi: '\u03F6',
    		bernou: '\u212C',
    		Bernoullis: '\u212C',
    		Beta: '\u0392',
    		beta: '\u03B2',
    		beth: '\u2136',
    		between: '\u226C',
    		Bfr: '\uD835\uDD05',
    		bfr: '\uD835\uDD1F',
    		bigcap: '\u22C2',
    		bigcirc: '\u25EF',
    		bigcup: '\u22C3',
    		bigodot: '\u2A00',
    		bigoplus: '\u2A01',
    		bigotimes: '\u2A02',
    		bigsqcup: '\u2A06',
    		bigstar: '\u2605',
    		bigtriangledown: '\u25BD',
    		bigtriangleup: '\u25B3',
    		biguplus: '\u2A04',
    		bigvee: '\u22C1',
    		bigwedge: '\u22C0',
    		bkarow: '\u290D',
    		blacklozenge: '\u29EB',
    		blacksquare: '\u25AA',
    		blacktriangle: '\u25B4',
    		blacktriangledown: '\u25BE',
    		blacktriangleleft: '\u25C2',
    		blacktriangleright: '\u25B8',
    		blank: '\u2423',
    		blk12: '\u2592',
    		blk14: '\u2591',
    		blk34: '\u2593',
    		block: '\u2588',
    		bne: '\u003D\u20E5',
    		bnequiv: '\u2261\u20E5',
    		bNot: '\u2AED',
    		bnot: '\u2310',
    		Bopf: '\uD835\uDD39',
    		bopf: '\uD835\uDD53',
    		bot: '\u22A5',
    		bottom: '\u22A5',
    		bowtie: '\u22C8',
    		boxbox: '\u29C9',
    		boxDL: '\u2557',
    		boxDl: '\u2556',
    		boxdL: '\u2555',
    		boxdl: '\u2510',
    		boxDR: '\u2554',
    		boxDr: '\u2553',
    		boxdR: '\u2552',
    		boxdr: '\u250C',
    		boxH: '\u2550',
    		boxh: '\u2500',
    		boxHD: '\u2566',
    		boxHd: '\u2564',
    		boxhD: '\u2565',
    		boxhd: '\u252C',
    		boxHU: '\u2569',
    		boxHu: '\u2567',
    		boxhU: '\u2568',
    		boxhu: '\u2534',
    		boxminus: '\u229F',
    		boxplus: '\u229E',
    		boxtimes: '\u22A0',
    		boxUL: '\u255D',
    		boxUl: '\u255C',
    		boxuL: '\u255B',
    		boxul: '\u2518',
    		boxUR: '\u255A',
    		boxUr: '\u2559',
    		boxuR: '\u2558',
    		boxur: '\u2514',
    		boxV: '\u2551',
    		boxv: '\u2502',
    		boxVH: '\u256C',
    		boxVh: '\u256B',
    		boxvH: '\u256A',
    		boxvh: '\u253C',
    		boxVL: '\u2563',
    		boxVl: '\u2562',
    		boxvL: '\u2561',
    		boxvl: '\u2524',
    		boxVR: '\u2560',
    		boxVr: '\u255F',
    		boxvR: '\u255E',
    		boxvr: '\u251C',
    		bprime: '\u2035',
    		Breve: '\u02D8',
    		breve: '\u02D8',
    		brvbar: '\u00A6',
    		Bscr: '\u212C',
    		bscr: '\uD835\uDCB7',
    		bsemi: '\u204F',
    		bsim: '\u223D',
    		bsime: '\u22CD',
    		bsol: '\u005C',
    		bsolb: '\u29C5',
    		bsolhsub: '\u27C8',
    		bull: '\u2022',
    		bullet: '\u2022',
    		bump: '\u224E',
    		bumpE: '\u2AAE',
    		bumpe: '\u224F',
    		Bumpeq: '\u224E',
    		bumpeq: '\u224F',
    		Cacute: '\u0106',
    		cacute: '\u0107',
    		Cap: '\u22D2',
    		cap: '\u2229',
    		capand: '\u2A44',
    		capbrcup: '\u2A49',
    		capcap: '\u2A4B',
    		capcup: '\u2A47',
    		capdot: '\u2A40',
    		CapitalDifferentialD: '\u2145',
    		caps: '\u2229\uFE00',
    		caret: '\u2041',
    		caron: '\u02C7',
    		Cayleys: '\u212D',
    		ccaps: '\u2A4D',
    		Ccaron: '\u010C',
    		ccaron: '\u010D',
    		Ccedil: '\u00C7',
    		ccedil: '\u00E7',
    		Ccirc: '\u0108',
    		ccirc: '\u0109',
    		Cconint: '\u2230',
    		ccups: '\u2A4C',
    		ccupssm: '\u2A50',
    		Cdot: '\u010A',
    		cdot: '\u010B',
    		cedil: '\u00B8',
    		Cedilla: '\u00B8',
    		cemptyv: '\u29B2',
    		cent: '\u00A2',
    		CenterDot: '\u00B7',
    		centerdot: '\u00B7',
    		Cfr: '\u212D',
    		cfr: '\uD835\uDD20',
    		CHcy: '\u0427',
    		chcy: '\u0447',
    		check: '\u2713',
    		checkmark: '\u2713',
    		Chi: '\u03A7',
    		chi: '\u03C7',
    		cir: '\u25CB',
    		circ: '\u02C6',
    		circeq: '\u2257',
    		circlearrowleft: '\u21BA',
    		circlearrowright: '\u21BB',
    		circledast: '\u229B',
    		circledcirc: '\u229A',
    		circleddash: '\u229D',
    		CircleDot: '\u2299',
    		circledR: '\u00AE',
    		circledS: '\u24C8',
    		CircleMinus: '\u2296',
    		CirclePlus: '\u2295',
    		CircleTimes: '\u2297',
    		cirE: '\u29C3',
    		cire: '\u2257',
    		cirfnint: '\u2A10',
    		cirmid: '\u2AEF',
    		cirscir: '\u29C2',
    		ClockwiseContourIntegral: '\u2232',
    		CloseCurlyDoubleQuote: '\u201D',
    		CloseCurlyQuote: '\u2019',
    		clubs: '\u2663',
    		clubsuit: '\u2663',
    		Colon: '\u2237',
    		colon: '\u003A',
    		Colone: '\u2A74',
    		colone: '\u2254',
    		coloneq: '\u2254',
    		comma: '\u002C',
    		commat: '\u0040',
    		comp: '\u2201',
    		compfn: '\u2218',
    		complement: '\u2201',
    		complexes: '\u2102',
    		cong: '\u2245',
    		congdot: '\u2A6D',
    		Congruent: '\u2261',
    		Conint: '\u222F',
    		conint: '\u222E',
    		ContourIntegral: '\u222E',
    		Copf: '\u2102',
    		copf: '\uD835\uDD54',
    		coprod: '\u2210',
    		Coproduct: '\u2210',
    		COPY: '\u00A9',
    		copy: '\u00A9',
    		copysr: '\u2117',
    		CounterClockwiseContourIntegral: '\u2233',
    		crarr: '\u21B5',
    		Cross: '\u2A2F',
    		cross: '\u2717',
    		Cscr: '\uD835\uDC9E',
    		cscr: '\uD835\uDCB8',
    		csub: '\u2ACF',
    		csube: '\u2AD1',
    		csup: '\u2AD0',
    		csupe: '\u2AD2',
    		ctdot: '\u22EF',
    		cudarrl: '\u2938',
    		cudarrr: '\u2935',
    		cuepr: '\u22DE',
    		cuesc: '\u22DF',
    		cularr: '\u21B6',
    		cularrp: '\u293D',
    		Cup: '\u22D3',
    		cup: '\u222A',
    		cupbrcap: '\u2A48',
    		CupCap: '\u224D',
    		cupcap: '\u2A46',
    		cupcup: '\u2A4A',
    		cupdot: '\u228D',
    		cupor: '\u2A45',
    		cups: '\u222A\uFE00',
    		curarr: '\u21B7',
    		curarrm: '\u293C',
    		curlyeqprec: '\u22DE',
    		curlyeqsucc: '\u22DF',
    		curlyvee: '\u22CE',
    		curlywedge: '\u22CF',
    		curren: '\u00A4',
    		curvearrowleft: '\u21B6',
    		curvearrowright: '\u21B7',
    		cuvee: '\u22CE',
    		cuwed: '\u22CF',
    		cwconint: '\u2232',
    		cwint: '\u2231',
    		cylcty: '\u232D',
    		Dagger: '\u2021',
    		dagger: '\u2020',
    		daleth: '\u2138',
    		Darr: '\u21A1',
    		dArr: '\u21D3',
    		darr: '\u2193',
    		dash: '\u2010',
    		Dashv: '\u2AE4',
    		dashv: '\u22A3',
    		dbkarow: '\u290F',
    		dblac: '\u02DD',
    		Dcaron: '\u010E',
    		dcaron: '\u010F',
    		Dcy: '\u0414',
    		dcy: '\u0434',
    		DD: '\u2145',
    		dd: '\u2146',
    		ddagger: '\u2021',
    		ddarr: '\u21CA',
    		DDotrahd: '\u2911',
    		ddotseq: '\u2A77',
    		deg: '\u00B0',
    		Del: '\u2207',
    		Delta: '\u0394',
    		delta: '\u03B4',
    		demptyv: '\u29B1',
    		dfisht: '\u297F',
    		Dfr: '\uD835\uDD07',
    		dfr: '\uD835\uDD21',
    		dHar: '\u2965',
    		dharl: '\u21C3',
    		dharr: '\u21C2',
    		DiacriticalAcute: '\u00B4',
    		DiacriticalDot: '\u02D9',
    		DiacriticalDoubleAcute: '\u02DD',
    		DiacriticalGrave: '\u0060',
    		DiacriticalTilde: '\u02DC',
    		diam: '\u22C4',
    		Diamond: '\u22C4',
    		diamond: '\u22C4',
    		diamondsuit: '\u2666',
    		diams: '\u2666',
    		die: '\u00A8',
    		DifferentialD: '\u2146',
    		digamma: '\u03DD',
    		disin: '\u22F2',
    		div: '\u00F7',
    		divide: '\u00F7',
    		divideontimes: '\u22C7',
    		divonx: '\u22C7',
    		DJcy: '\u0402',
    		djcy: '\u0452',
    		dlcorn: '\u231E',
    		dlcrop: '\u230D',
    		dollar: '\u0024',
    		Dopf: '\uD835\uDD3B',
    		dopf: '\uD835\uDD55',
    		Dot: '\u00A8',
    		dot: '\u02D9',
    		DotDot: '\u20DC',
    		doteq: '\u2250',
    		doteqdot: '\u2251',
    		DotEqual: '\u2250',
    		dotminus: '\u2238',
    		dotplus: '\u2214',
    		dotsquare: '\u22A1',
    		doublebarwedge: '\u2306',
    		DoubleContourIntegral: '\u222F',
    		DoubleDot: '\u00A8',
    		DoubleDownArrow: '\u21D3',
    		DoubleLeftArrow: '\u21D0',
    		DoubleLeftRightArrow: '\u21D4',
    		DoubleLeftTee: '\u2AE4',
    		DoubleLongLeftArrow: '\u27F8',
    		DoubleLongLeftRightArrow: '\u27FA',
    		DoubleLongRightArrow: '\u27F9',
    		DoubleRightArrow: '\u21D2',
    		DoubleRightTee: '\u22A8',
    		DoubleUpArrow: '\u21D1',
    		DoubleUpDownArrow: '\u21D5',
    		DoubleVerticalBar: '\u2225',
    		DownArrow: '\u2193',
    		Downarrow: '\u21D3',
    		downarrow: '\u2193',
    		DownArrowBar: '\u2913',
    		DownArrowUpArrow: '\u21F5',
    		DownBreve: '\u0311',
    		downdownarrows: '\u21CA',
    		downharpoonleft: '\u21C3',
    		downharpoonright: '\u21C2',
    		DownLeftRightVector: '\u2950',
    		DownLeftTeeVector: '\u295E',
    		DownLeftVector: '\u21BD',
    		DownLeftVectorBar: '\u2956',
    		DownRightTeeVector: '\u295F',
    		DownRightVector: '\u21C1',
    		DownRightVectorBar: '\u2957',
    		DownTee: '\u22A4',
    		DownTeeArrow: '\u21A7',
    		drbkarow: '\u2910',
    		drcorn: '\u231F',
    		drcrop: '\u230C',
    		Dscr: '\uD835\uDC9F',
    		dscr: '\uD835\uDCB9',
    		DScy: '\u0405',
    		dscy: '\u0455',
    		dsol: '\u29F6',
    		Dstrok: '\u0110',
    		dstrok: '\u0111',
    		dtdot: '\u22F1',
    		dtri: '\u25BF',
    		dtrif: '\u25BE',
    		duarr: '\u21F5',
    		duhar: '\u296F',
    		dwangle: '\u29A6',
    		DZcy: '\u040F',
    		dzcy: '\u045F',
    		dzigrarr: '\u27FF',
    		Eacute: '\u00C9',
    		eacute: '\u00E9',
    		easter: '\u2A6E',
    		Ecaron: '\u011A',
    		ecaron: '\u011B',
    		ecir: '\u2256',
    		Ecirc: '\u00CA',
    		ecirc: '\u00EA',
    		ecolon: '\u2255',
    		Ecy: '\u042D',
    		ecy: '\u044D',
    		eDDot: '\u2A77',
    		Edot: '\u0116',
    		eDot: '\u2251',
    		edot: '\u0117',
    		ee: '\u2147',
    		efDot: '\u2252',
    		Efr: '\uD835\uDD08',
    		efr: '\uD835\uDD22',
    		eg: '\u2A9A',
    		Egrave: '\u00C8',
    		egrave: '\u00E8',
    		egs: '\u2A96',
    		egsdot: '\u2A98',
    		el: '\u2A99',
    		Element: '\u2208',
    		elinters: '\u23E7',
    		ell: '\u2113',
    		els: '\u2A95',
    		elsdot: '\u2A97',
    		Emacr: '\u0112',
    		emacr: '\u0113',
    		empty: '\u2205',
    		emptyset: '\u2205',
    		EmptySmallSquare: '\u25FB',
    		emptyv: '\u2205',
    		EmptyVerySmallSquare: '\u25AB',
    		emsp: '\u2003',
    		emsp13: '\u2004',
    		emsp14: '\u2005',
    		ENG: '\u014A',
    		eng: '\u014B',
    		ensp: '\u2002',
    		Eogon: '\u0118',
    		eogon: '\u0119',
    		Eopf: '\uD835\uDD3C',
    		eopf: '\uD835\uDD56',
    		epar: '\u22D5',
    		eparsl: '\u29E3',
    		eplus: '\u2A71',
    		epsi: '\u03B5',
    		Epsilon: '\u0395',
    		epsilon: '\u03B5',
    		epsiv: '\u03F5',
    		eqcirc: '\u2256',
    		eqcolon: '\u2255',
    		eqsim: '\u2242',
    		eqslantgtr: '\u2A96',
    		eqslantless: '\u2A95',
    		Equal: '\u2A75',
    		equals: '\u003D',
    		EqualTilde: '\u2242',
    		equest: '\u225F',
    		Equilibrium: '\u21CC',
    		equiv: '\u2261',
    		equivDD: '\u2A78',
    		eqvparsl: '\u29E5',
    		erarr: '\u2971',
    		erDot: '\u2253',
    		Escr: '\u2130',
    		escr: '\u212F',
    		esdot: '\u2250',
    		Esim: '\u2A73',
    		esim: '\u2242',
    		Eta: '\u0397',
    		eta: '\u03B7',
    		ETH: '\u00D0',
    		eth: '\u00F0',
    		Euml: '\u00CB',
    		euml: '\u00EB',
    		euro: '\u20AC',
    		excl: '\u0021',
    		exist: '\u2203',
    		Exists: '\u2203',
    		expectation: '\u2130',
    		ExponentialE: '\u2147',
    		exponentiale: '\u2147',
    		fallingdotseq: '\u2252',
    		Fcy: '\u0424',
    		fcy: '\u0444',
    		female: '\u2640',
    		ffilig: '\uFB03',
    		fflig: '\uFB00',
    		ffllig: '\uFB04',
    		Ffr: '\uD835\uDD09',
    		ffr: '\uD835\uDD23',
    		filig: '\uFB01',
    		FilledSmallSquare: '\u25FC',
    		FilledVerySmallSquare: '\u25AA',
    		fjlig: '\u0066\u006A',
    		flat: '\u266D',
    		fllig: '\uFB02',
    		fltns: '\u25B1',
    		fnof: '\u0192',
    		Fopf: '\uD835\uDD3D',
    		fopf: '\uD835\uDD57',
    		ForAll: '\u2200',
    		forall: '\u2200',
    		fork: '\u22D4',
    		forkv: '\u2AD9',
    		Fouriertrf: '\u2131',
    		fpartint: '\u2A0D',
    		frac12: '\u00BD',
    		frac13: '\u2153',
    		frac14: '\u00BC',
    		frac15: '\u2155',
    		frac16: '\u2159',
    		frac18: '\u215B',
    		frac23: '\u2154',
    		frac25: '\u2156',
    		frac34: '\u00BE',
    		frac35: '\u2157',
    		frac38: '\u215C',
    		frac45: '\u2158',
    		frac56: '\u215A',
    		frac58: '\u215D',
    		frac78: '\u215E',
    		frasl: '\u2044',
    		frown: '\u2322',
    		Fscr: '\u2131',
    		fscr: '\uD835\uDCBB',
    		gacute: '\u01F5',
    		Gamma: '\u0393',
    		gamma: '\u03B3',
    		Gammad: '\u03DC',
    		gammad: '\u03DD',
    		gap: '\u2A86',
    		Gbreve: '\u011E',
    		gbreve: '\u011F',
    		Gcedil: '\u0122',
    		Gcirc: '\u011C',
    		gcirc: '\u011D',
    		Gcy: '\u0413',
    		gcy: '\u0433',
    		Gdot: '\u0120',
    		gdot: '\u0121',
    		gE: '\u2267',
    		ge: '\u2265',
    		gEl: '\u2A8C',
    		gel: '\u22DB',
    		geq: '\u2265',
    		geqq: '\u2267',
    		geqslant: '\u2A7E',
    		ges: '\u2A7E',
    		gescc: '\u2AA9',
    		gesdot: '\u2A80',
    		gesdoto: '\u2A82',
    		gesdotol: '\u2A84',
    		gesl: '\u22DB\uFE00',
    		gesles: '\u2A94',
    		Gfr: '\uD835\uDD0A',
    		gfr: '\uD835\uDD24',
    		Gg: '\u22D9',
    		gg: '\u226B',
    		ggg: '\u22D9',
    		gimel: '\u2137',
    		GJcy: '\u0403',
    		gjcy: '\u0453',
    		gl: '\u2277',
    		gla: '\u2AA5',
    		glE: '\u2A92',
    		glj: '\u2AA4',
    		gnap: '\u2A8A',
    		gnapprox: '\u2A8A',
    		gnE: '\u2269',
    		gne: '\u2A88',
    		gneq: '\u2A88',
    		gneqq: '\u2269',
    		gnsim: '\u22E7',
    		Gopf: '\uD835\uDD3E',
    		gopf: '\uD835\uDD58',
    		grave: '\u0060',
    		GreaterEqual: '\u2265',
    		GreaterEqualLess: '\u22DB',
    		GreaterFullEqual: '\u2267',
    		GreaterGreater: '\u2AA2',
    		GreaterLess: '\u2277',
    		GreaterSlantEqual: '\u2A7E',
    		GreaterTilde: '\u2273',
    		Gscr: '\uD835\uDCA2',
    		gscr: '\u210A',
    		gsim: '\u2273',
    		gsime: '\u2A8E',
    		gsiml: '\u2A90',
    		Gt: '\u226B',
    		GT: '\u003E',
    		gt: '\u003E',
    		gtcc: '\u2AA7',
    		gtcir: '\u2A7A',
    		gtdot: '\u22D7',
    		gtlPar: '\u2995',
    		gtquest: '\u2A7C',
    		gtrapprox: '\u2A86',
    		gtrarr: '\u2978',
    		gtrdot: '\u22D7',
    		gtreqless: '\u22DB',
    		gtreqqless: '\u2A8C',
    		gtrless: '\u2277',
    		gtrsim: '\u2273',
    		gvertneqq: '\u2269\uFE00',
    		gvnE: '\u2269\uFE00',
    		Hacek: '\u02C7',
    		hairsp: '\u200A',
    		half: '\u00BD',
    		hamilt: '\u210B',
    		HARDcy: '\u042A',
    		hardcy: '\u044A',
    		hArr: '\u21D4',
    		harr: '\u2194',
    		harrcir: '\u2948',
    		harrw: '\u21AD',
    		Hat: '\u005E',
    		hbar: '\u210F',
    		Hcirc: '\u0124',
    		hcirc: '\u0125',
    		hearts: '\u2665',
    		heartsuit: '\u2665',
    		hellip: '\u2026',
    		hercon: '\u22B9',
    		Hfr: '\u210C',
    		hfr: '\uD835\uDD25',
    		HilbertSpace: '\u210B',
    		hksearow: '\u2925',
    		hkswarow: '\u2926',
    		hoarr: '\u21FF',
    		homtht: '\u223B',
    		hookleftarrow: '\u21A9',
    		hookrightarrow: '\u21AA',
    		Hopf: '\u210D',
    		hopf: '\uD835\uDD59',
    		horbar: '\u2015',
    		HorizontalLine: '\u2500',
    		Hscr: '\u210B',
    		hscr: '\uD835\uDCBD',
    		hslash: '\u210F',
    		Hstrok: '\u0126',
    		hstrok: '\u0127',
    		HumpDownHump: '\u224E',
    		HumpEqual: '\u224F',
    		hybull: '\u2043',
    		hyphen: '\u2010',
    		Iacute: '\u00CD',
    		iacute: '\u00ED',
    		ic: '\u2063',
    		Icirc: '\u00CE',
    		icirc: '\u00EE',
    		Icy: '\u0418',
    		icy: '\u0438',
    		Idot: '\u0130',
    		IEcy: '\u0415',
    		iecy: '\u0435',
    		iexcl: '\u00A1',
    		iff: '\u21D4',
    		Ifr: '\u2111',
    		ifr: '\uD835\uDD26',
    		Igrave: '\u00CC',
    		igrave: '\u00EC',
    		ii: '\u2148',
    		iiiint: '\u2A0C',
    		iiint: '\u222D',
    		iinfin: '\u29DC',
    		iiota: '\u2129',
    		IJlig: '\u0132',
    		ijlig: '\u0133',
    		Im: '\u2111',
    		Imacr: '\u012A',
    		imacr: '\u012B',
    		image: '\u2111',
    		ImaginaryI: '\u2148',
    		imagline: '\u2110',
    		imagpart: '\u2111',
    		imath: '\u0131',
    		imof: '\u22B7',
    		imped: '\u01B5',
    		Implies: '\u21D2',
    		in: '\u2208',
    		incare: '\u2105',
    		infin: '\u221E',
    		infintie: '\u29DD',
    		inodot: '\u0131',
    		Int: '\u222C',
    		int: '\u222B',
    		intcal: '\u22BA',
    		integers: '\u2124',
    		Integral: '\u222B',
    		intercal: '\u22BA',
    		Intersection: '\u22C2',
    		intlarhk: '\u2A17',
    		intprod: '\u2A3C',
    		InvisibleComma: '\u2063',
    		InvisibleTimes: '\u2062',
    		IOcy: '\u0401',
    		iocy: '\u0451',
    		Iogon: '\u012E',
    		iogon: '\u012F',
    		Iopf: '\uD835\uDD40',
    		iopf: '\uD835\uDD5A',
    		Iota: '\u0399',
    		iota: '\u03B9',
    		iprod: '\u2A3C',
    		iquest: '\u00BF',
    		Iscr: '\u2110',
    		iscr: '\uD835\uDCBE',
    		isin: '\u2208',
    		isindot: '\u22F5',
    		isinE: '\u22F9',
    		isins: '\u22F4',
    		isinsv: '\u22F3',
    		isinv: '\u2208',
    		it: '\u2062',
    		Itilde: '\u0128',
    		itilde: '\u0129',
    		Iukcy: '\u0406',
    		iukcy: '\u0456',
    		Iuml: '\u00CF',
    		iuml: '\u00EF',
    		Jcirc: '\u0134',
    		jcirc: '\u0135',
    		Jcy: '\u0419',
    		jcy: '\u0439',
    		Jfr: '\uD835\uDD0D',
    		jfr: '\uD835\uDD27',
    		jmath: '\u0237',
    		Jopf: '\uD835\uDD41',
    		jopf: '\uD835\uDD5B',
    		Jscr: '\uD835\uDCA5',
    		jscr: '\uD835\uDCBF',
    		Jsercy: '\u0408',
    		jsercy: '\u0458',
    		Jukcy: '\u0404',
    		jukcy: '\u0454',
    		Kappa: '\u039A',
    		kappa: '\u03BA',
    		kappav: '\u03F0',
    		Kcedil: '\u0136',
    		kcedil: '\u0137',
    		Kcy: '\u041A',
    		kcy: '\u043A',
    		Kfr: '\uD835\uDD0E',
    		kfr: '\uD835\uDD28',
    		kgreen: '\u0138',
    		KHcy: '\u0425',
    		khcy: '\u0445',
    		KJcy: '\u040C',
    		kjcy: '\u045C',
    		Kopf: '\uD835\uDD42',
    		kopf: '\uD835\uDD5C',
    		Kscr: '\uD835\uDCA6',
    		kscr: '\uD835\uDCC0',
    		lAarr: '\u21DA',
    		Lacute: '\u0139',
    		lacute: '\u013A',
    		laemptyv: '\u29B4',
    		lagran: '\u2112',
    		Lambda: '\u039B',
    		lambda: '\u03BB',
    		Lang: '\u27EA',
    		lang: '\u27E8',
    		langd: '\u2991',
    		langle: '\u27E8',
    		lap: '\u2A85',
    		Laplacetrf: '\u2112',
    		laquo: '\u00AB',
    		Larr: '\u219E',
    		lArr: '\u21D0',
    		larr: '\u2190',
    		larrb: '\u21E4',
    		larrbfs: '\u291F',
    		larrfs: '\u291D',
    		larrhk: '\u21A9',
    		larrlp: '\u21AB',
    		larrpl: '\u2939',
    		larrsim: '\u2973',
    		larrtl: '\u21A2',
    		lat: '\u2AAB',
    		lAtail: '\u291B',
    		latail: '\u2919',
    		late: '\u2AAD',
    		lates: '\u2AAD\uFE00',
    		lBarr: '\u290E',
    		lbarr: '\u290C',
    		lbbrk: '\u2772',
    		lbrace: '\u007B',
    		lbrack: '\u005B',
    		lbrke: '\u298B',
    		lbrksld: '\u298F',
    		lbrkslu: '\u298D',
    		Lcaron: '\u013D',
    		lcaron: '\u013E',
    		Lcedil: '\u013B',
    		lcedil: '\u013C',
    		lceil: '\u2308',
    		lcub: '\u007B',
    		Lcy: '\u041B',
    		lcy: '\u043B',
    		ldca: '\u2936',
    		ldquo: '\u201C',
    		ldquor: '\u201E',
    		ldrdhar: '\u2967',
    		ldrushar: '\u294B',
    		ldsh: '\u21B2',
    		lE: '\u2266',
    		le: '\u2264',
    		LeftAngleBracket: '\u27E8',
    		LeftArrow: '\u2190',
    		Leftarrow: '\u21D0',
    		leftarrow: '\u2190',
    		LeftArrowBar: '\u21E4',
    		LeftArrowRightArrow: '\u21C6',
    		leftarrowtail: '\u21A2',
    		LeftCeiling: '\u2308',
    		LeftDoubleBracket: '\u27E6',
    		LeftDownTeeVector: '\u2961',
    		LeftDownVector: '\u21C3',
    		LeftDownVectorBar: '\u2959',
    		LeftFloor: '\u230A',
    		leftharpoondown: '\u21BD',
    		leftharpoonup: '\u21BC',
    		leftleftarrows: '\u21C7',
    		LeftRightArrow: '\u2194',
    		Leftrightarrow: '\u21D4',
    		leftrightarrow: '\u2194',
    		leftrightarrows: '\u21C6',
    		leftrightharpoons: '\u21CB',
    		leftrightsquigarrow: '\u21AD',
    		LeftRightVector: '\u294E',
    		LeftTee: '\u22A3',
    		LeftTeeArrow: '\u21A4',
    		LeftTeeVector: '\u295A',
    		leftthreetimes: '\u22CB',
    		LeftTriangle: '\u22B2',
    		LeftTriangleBar: '\u29CF',
    		LeftTriangleEqual: '\u22B4',
    		LeftUpDownVector: '\u2951',
    		LeftUpTeeVector: '\u2960',
    		LeftUpVector: '\u21BF',
    		LeftUpVectorBar: '\u2958',
    		LeftVector: '\u21BC',
    		LeftVectorBar: '\u2952',
    		lEg: '\u2A8B',
    		leg: '\u22DA',
    		leq: '\u2264',
    		leqq: '\u2266',
    		leqslant: '\u2A7D',
    		les: '\u2A7D',
    		lescc: '\u2AA8',
    		lesdot: '\u2A7F',
    		lesdoto: '\u2A81',
    		lesdotor: '\u2A83',
    		lesg: '\u22DA\uFE00',
    		lesges: '\u2A93',
    		lessapprox: '\u2A85',
    		lessdot: '\u22D6',
    		lesseqgtr: '\u22DA',
    		lesseqqgtr: '\u2A8B',
    		LessEqualGreater: '\u22DA',
    		LessFullEqual: '\u2266',
    		LessGreater: '\u2276',
    		lessgtr: '\u2276',
    		LessLess: '\u2AA1',
    		lesssim: '\u2272',
    		LessSlantEqual: '\u2A7D',
    		LessTilde: '\u2272',
    		lfisht: '\u297C',
    		lfloor: '\u230A',
    		Lfr: '\uD835\uDD0F',
    		lfr: '\uD835\uDD29',
    		lg: '\u2276',
    		lgE: '\u2A91',
    		lHar: '\u2962',
    		lhard: '\u21BD',
    		lharu: '\u21BC',
    		lharul: '\u296A',
    		lhblk: '\u2584',
    		LJcy: '\u0409',
    		ljcy: '\u0459',
    		Ll: '\u22D8',
    		ll: '\u226A',
    		llarr: '\u21C7',
    		llcorner: '\u231E',
    		Lleftarrow: '\u21DA',
    		llhard: '\u296B',
    		lltri: '\u25FA',
    		Lmidot: '\u013F',
    		lmidot: '\u0140',
    		lmoust: '\u23B0',
    		lmoustache: '\u23B0',
    		lnap: '\u2A89',
    		lnapprox: '\u2A89',
    		lnE: '\u2268',
    		lne: '\u2A87',
    		lneq: '\u2A87',
    		lneqq: '\u2268',
    		lnsim: '\u22E6',
    		loang: '\u27EC',
    		loarr: '\u21FD',
    		lobrk: '\u27E6',
    		LongLeftArrow: '\u27F5',
    		Longleftarrow: '\u27F8',
    		longleftarrow: '\u27F5',
    		LongLeftRightArrow: '\u27F7',
    		Longleftrightarrow: '\u27FA',
    		longleftrightarrow: '\u27F7',
    		longmapsto: '\u27FC',
    		LongRightArrow: '\u27F6',
    		Longrightarrow: '\u27F9',
    		longrightarrow: '\u27F6',
    		looparrowleft: '\u21AB',
    		looparrowright: '\u21AC',
    		lopar: '\u2985',
    		Lopf: '\uD835\uDD43',
    		lopf: '\uD835\uDD5D',
    		loplus: '\u2A2D',
    		lotimes: '\u2A34',
    		lowast: '\u2217',
    		lowbar: '\u005F',
    		LowerLeftArrow: '\u2199',
    		LowerRightArrow: '\u2198',
    		loz: '\u25CA',
    		lozenge: '\u25CA',
    		lozf: '\u29EB',
    		lpar: '\u0028',
    		lparlt: '\u2993',
    		lrarr: '\u21C6',
    		lrcorner: '\u231F',
    		lrhar: '\u21CB',
    		lrhard: '\u296D',
    		lrm: '\u200E',
    		lrtri: '\u22BF',
    		lsaquo: '\u2039',
    		Lscr: '\u2112',
    		lscr: '\uD835\uDCC1',
    		Lsh: '\u21B0',
    		lsh: '\u21B0',
    		lsim: '\u2272',
    		lsime: '\u2A8D',
    		lsimg: '\u2A8F',
    		lsqb: '\u005B',
    		lsquo: '\u2018',
    		lsquor: '\u201A',
    		Lstrok: '\u0141',
    		lstrok: '\u0142',
    		Lt: '\u226A',
    		LT: '\u003C',
    		lt: '\u003C',
    		ltcc: '\u2AA6',
    		ltcir: '\u2A79',
    		ltdot: '\u22D6',
    		lthree: '\u22CB',
    		ltimes: '\u22C9',
    		ltlarr: '\u2976',
    		ltquest: '\u2A7B',
    		ltri: '\u25C3',
    		ltrie: '\u22B4',
    		ltrif: '\u25C2',
    		ltrPar: '\u2996',
    		lurdshar: '\u294A',
    		luruhar: '\u2966',
    		lvertneqq: '\u2268\uFE00',
    		lvnE: '\u2268\uFE00',
    		macr: '\u00AF',
    		male: '\u2642',
    		malt: '\u2720',
    		maltese: '\u2720',
    		Map: '\u2905',
    		map: '\u21A6',
    		mapsto: '\u21A6',
    		mapstodown: '\u21A7',
    		mapstoleft: '\u21A4',
    		mapstoup: '\u21A5',
    		marker: '\u25AE',
    		mcomma: '\u2A29',
    		Mcy: '\u041C',
    		mcy: '\u043C',
    		mdash: '\u2014',
    		mDDot: '\u223A',
    		measuredangle: '\u2221',
    		MediumSpace: '\u205F',
    		Mellintrf: '\u2133',
    		Mfr: '\uD835\uDD10',
    		mfr: '\uD835\uDD2A',
    		mho: '\u2127',
    		micro: '\u00B5',
    		mid: '\u2223',
    		midast: '\u002A',
    		midcir: '\u2AF0',
    		middot: '\u00B7',
    		minus: '\u2212',
    		minusb: '\u229F',
    		minusd: '\u2238',
    		minusdu: '\u2A2A',
    		MinusPlus: '\u2213',
    		mlcp: '\u2ADB',
    		mldr: '\u2026',
    		mnplus: '\u2213',
    		models: '\u22A7',
    		Mopf: '\uD835\uDD44',
    		mopf: '\uD835\uDD5E',
    		mp: '\u2213',
    		Mscr: '\u2133',
    		mscr: '\uD835\uDCC2',
    		mstpos: '\u223E',
    		Mu: '\u039C',
    		mu: '\u03BC',
    		multimap: '\u22B8',
    		mumap: '\u22B8',
    		nabla: '\u2207',
    		Nacute: '\u0143',
    		nacute: '\u0144',
    		nang: '\u2220\u20D2',
    		nap: '\u2249',
    		napE: '\u2A70\u0338',
    		napid: '\u224B\u0338',
    		napos: '\u0149',
    		napprox: '\u2249',
    		natur: '\u266E',
    		natural: '\u266E',
    		naturals: '\u2115',
    		nbsp: '\u00A0',
    		nbump: '\u224E\u0338',
    		nbumpe: '\u224F\u0338',
    		ncap: '\u2A43',
    		Ncaron: '\u0147',
    		ncaron: '\u0148',
    		Ncedil: '\u0145',
    		ncedil: '\u0146',
    		ncong: '\u2247',
    		ncongdot: '\u2A6D\u0338',
    		ncup: '\u2A42',
    		Ncy: '\u041D',
    		ncy: '\u043D',
    		ndash: '\u2013',
    		ne: '\u2260',
    		nearhk: '\u2924',
    		neArr: '\u21D7',
    		nearr: '\u2197',
    		nearrow: '\u2197',
    		nedot: '\u2250\u0338',
    		NegativeMediumSpace: '\u200B',
    		NegativeThickSpace: '\u200B',
    		NegativeThinSpace: '\u200B',
    		NegativeVeryThinSpace: '\u200B',
    		nequiv: '\u2262',
    		nesear: '\u2928',
    		nesim: '\u2242\u0338',
    		NestedGreaterGreater: '\u226B',
    		NestedLessLess: '\u226A',
    		NewLine: '\u000A',
    		nexist: '\u2204',
    		nexists: '\u2204',
    		Nfr: '\uD835\uDD11',
    		nfr: '\uD835\uDD2B',
    		ngE: '\u2267\u0338',
    		nge: '\u2271',
    		ngeq: '\u2271',
    		ngeqq: '\u2267\u0338',
    		ngeqslant: '\u2A7E\u0338',
    		nges: '\u2A7E\u0338',
    		nGg: '\u22D9\u0338',
    		ngsim: '\u2275',
    		nGt: '\u226B\u20D2',
    		ngt: '\u226F',
    		ngtr: '\u226F',
    		nGtv: '\u226B\u0338',
    		nhArr: '\u21CE',
    		nharr: '\u21AE',
    		nhpar: '\u2AF2',
    		ni: '\u220B',
    		nis: '\u22FC',
    		nisd: '\u22FA',
    		niv: '\u220B',
    		NJcy: '\u040A',
    		njcy: '\u045A',
    		nlArr: '\u21CD',
    		nlarr: '\u219A',
    		nldr: '\u2025',
    		nlE: '\u2266\u0338',
    		nle: '\u2270',
    		nLeftarrow: '\u21CD',
    		nleftarrow: '\u219A',
    		nLeftrightarrow: '\u21CE',
    		nleftrightarrow: '\u21AE',
    		nleq: '\u2270',
    		nleqq: '\u2266\u0338',
    		nleqslant: '\u2A7D\u0338',
    		nles: '\u2A7D\u0338',
    		nless: '\u226E',
    		nLl: '\u22D8\u0338',
    		nlsim: '\u2274',
    		nLt: '\u226A\u20D2',
    		nlt: '\u226E',
    		nltri: '\u22EA',
    		nltrie: '\u22EC',
    		nLtv: '\u226A\u0338',
    		nmid: '\u2224',
    		NoBreak: '\u2060',
    		NonBreakingSpace: '\u00A0',
    		Nopf: '\u2115',
    		nopf: '\uD835\uDD5F',
    		Not: '\u2AEC',
    		not: '\u00AC',
    		NotCongruent: '\u2262',
    		NotCupCap: '\u226D',
    		NotDoubleVerticalBar: '\u2226',
    		NotElement: '\u2209',
    		NotEqual: '\u2260',
    		NotEqualTilde: '\u2242\u0338',
    		NotExists: '\u2204',
    		NotGreater: '\u226F',
    		NotGreaterEqual: '\u2271',
    		NotGreaterFullEqual: '\u2267\u0338',
    		NotGreaterGreater: '\u226B\u0338',
    		NotGreaterLess: '\u2279',
    		NotGreaterSlantEqual: '\u2A7E\u0338',
    		NotGreaterTilde: '\u2275',
    		NotHumpDownHump: '\u224E\u0338',
    		NotHumpEqual: '\u224F\u0338',
    		notin: '\u2209',
    		notindot: '\u22F5\u0338',
    		notinE: '\u22F9\u0338',
    		notinva: '\u2209',
    		notinvb: '\u22F7',
    		notinvc: '\u22F6',
    		NotLeftTriangle: '\u22EA',
    		NotLeftTriangleBar: '\u29CF\u0338',
    		NotLeftTriangleEqual: '\u22EC',
    		NotLess: '\u226E',
    		NotLessEqual: '\u2270',
    		NotLessGreater: '\u2278',
    		NotLessLess: '\u226A\u0338',
    		NotLessSlantEqual: '\u2A7D\u0338',
    		NotLessTilde: '\u2274',
    		NotNestedGreaterGreater: '\u2AA2\u0338',
    		NotNestedLessLess: '\u2AA1\u0338',
    		notni: '\u220C',
    		notniva: '\u220C',
    		notnivb: '\u22FE',
    		notnivc: '\u22FD',
    		NotPrecedes: '\u2280',
    		NotPrecedesEqual: '\u2AAF\u0338',
    		NotPrecedesSlantEqual: '\u22E0',
    		NotReverseElement: '\u220C',
    		NotRightTriangle: '\u22EB',
    		NotRightTriangleBar: '\u29D0\u0338',
    		NotRightTriangleEqual: '\u22ED',
    		NotSquareSubset: '\u228F\u0338',
    		NotSquareSubsetEqual: '\u22E2',
    		NotSquareSuperset: '\u2290\u0338',
    		NotSquareSupersetEqual: '\u22E3',
    		NotSubset: '\u2282\u20D2',
    		NotSubsetEqual: '\u2288',
    		NotSucceeds: '\u2281',
    		NotSucceedsEqual: '\u2AB0\u0338',
    		NotSucceedsSlantEqual: '\u22E1',
    		NotSucceedsTilde: '\u227F\u0338',
    		NotSuperset: '\u2283\u20D2',
    		NotSupersetEqual: '\u2289',
    		NotTilde: '\u2241',
    		NotTildeEqual: '\u2244',
    		NotTildeFullEqual: '\u2247',
    		NotTildeTilde: '\u2249',
    		NotVerticalBar: '\u2224',
    		npar: '\u2226',
    		nparallel: '\u2226',
    		nparsl: '\u2AFD\u20E5',
    		npart: '\u2202\u0338',
    		npolint: '\u2A14',
    		npr: '\u2280',
    		nprcue: '\u22E0',
    		npre: '\u2AAF\u0338',
    		nprec: '\u2280',
    		npreceq: '\u2AAF\u0338',
    		nrArr: '\u21CF',
    		nrarr: '\u219B',
    		nrarrc: '\u2933\u0338',
    		nrarrw: '\u219D\u0338',
    		nRightarrow: '\u21CF',
    		nrightarrow: '\u219B',
    		nrtri: '\u22EB',
    		nrtrie: '\u22ED',
    		nsc: '\u2281',
    		nsccue: '\u22E1',
    		nsce: '\u2AB0\u0338',
    		Nscr: '\uD835\uDCA9',
    		nscr: '\uD835\uDCC3',
    		nshortmid: '\u2224',
    		nshortparallel: '\u2226',
    		nsim: '\u2241',
    		nsime: '\u2244',
    		nsimeq: '\u2244',
    		nsmid: '\u2224',
    		nspar: '\u2226',
    		nsqsube: '\u22E2',
    		nsqsupe: '\u22E3',
    		nsub: '\u2284',
    		nsubE: '\u2AC5\u0338',
    		nsube: '\u2288',
    		nsubset: '\u2282\u20D2',
    		nsubseteq: '\u2288',
    		nsubseteqq: '\u2AC5\u0338',
    		nsucc: '\u2281',
    		nsucceq: '\u2AB0\u0338',
    		nsup: '\u2285',
    		nsupE: '\u2AC6\u0338',
    		nsupe: '\u2289',
    		nsupset: '\u2283\u20D2',
    		nsupseteq: '\u2289',
    		nsupseteqq: '\u2AC6\u0338',
    		ntgl: '\u2279',
    		Ntilde: '\u00D1',
    		ntilde: '\u00F1',
    		ntlg: '\u2278',
    		ntriangleleft: '\u22EA',
    		ntrianglelefteq: '\u22EC',
    		ntriangleright: '\u22EB',
    		ntrianglerighteq: '\u22ED',
    		Nu: '\u039D',
    		nu: '\u03BD',
    		num: '\u0023',
    		numero: '\u2116',
    		numsp: '\u2007',
    		nvap: '\u224D\u20D2',
    		nVDash: '\u22AF',
    		nVdash: '\u22AE',
    		nvDash: '\u22AD',
    		nvdash: '\u22AC',
    		nvge: '\u2265\u20D2',
    		nvgt: '\u003E\u20D2',
    		nvHarr: '\u2904',
    		nvinfin: '\u29DE',
    		nvlArr: '\u2902',
    		nvle: '\u2264\u20D2',
    		nvlt: '\u003C\u20D2',
    		nvltrie: '\u22B4\u20D2',
    		nvrArr: '\u2903',
    		nvrtrie: '\u22B5\u20D2',
    		nvsim: '\u223C\u20D2',
    		nwarhk: '\u2923',
    		nwArr: '\u21D6',
    		nwarr: '\u2196',
    		nwarrow: '\u2196',
    		nwnear: '\u2927',
    		Oacute: '\u00D3',
    		oacute: '\u00F3',
    		oast: '\u229B',
    		ocir: '\u229A',
    		Ocirc: '\u00D4',
    		ocirc: '\u00F4',
    		Ocy: '\u041E',
    		ocy: '\u043E',
    		odash: '\u229D',
    		Odblac: '\u0150',
    		odblac: '\u0151',
    		odiv: '\u2A38',
    		odot: '\u2299',
    		odsold: '\u29BC',
    		OElig: '\u0152',
    		oelig: '\u0153',
    		ofcir: '\u29BF',
    		Ofr: '\uD835\uDD12',
    		ofr: '\uD835\uDD2C',
    		ogon: '\u02DB',
    		Ograve: '\u00D2',
    		ograve: '\u00F2',
    		ogt: '\u29C1',
    		ohbar: '\u29B5',
    		ohm: '\u03A9',
    		oint: '\u222E',
    		olarr: '\u21BA',
    		olcir: '\u29BE',
    		olcross: '\u29BB',
    		oline: '\u203E',
    		olt: '\u29C0',
    		Omacr: '\u014C',
    		omacr: '\u014D',
    		Omega: '\u03A9',
    		omega: '\u03C9',
    		Omicron: '\u039F',
    		omicron: '\u03BF',
    		omid: '\u29B6',
    		ominus: '\u2296',
    		Oopf: '\uD835\uDD46',
    		oopf: '\uD835\uDD60',
    		opar: '\u29B7',
    		OpenCurlyDoubleQuote: '\u201C',
    		OpenCurlyQuote: '\u2018',
    		operp: '\u29B9',
    		oplus: '\u2295',
    		Or: '\u2A54',
    		or: '\u2228',
    		orarr: '\u21BB',
    		ord: '\u2A5D',
    		order: '\u2134',
    		orderof: '\u2134',
    		ordf: '\u00AA',
    		ordm: '\u00BA',
    		origof: '\u22B6',
    		oror: '\u2A56',
    		orslope: '\u2A57',
    		orv: '\u2A5B',
    		oS: '\u24C8',
    		Oscr: '\uD835\uDCAA',
    		oscr: '\u2134',
    		Oslash: '\u00D8',
    		oslash: '\u00F8',
    		osol: '\u2298',
    		Otilde: '\u00D5',
    		otilde: '\u00F5',
    		Otimes: '\u2A37',
    		otimes: '\u2297',
    		otimesas: '\u2A36',
    		Ouml: '\u00D6',
    		ouml: '\u00F6',
    		ovbar: '\u233D',
    		OverBar: '\u203E',
    		OverBrace: '\u23DE',
    		OverBracket: '\u23B4',
    		OverParenthesis: '\u23DC',
    		par: '\u2225',
    		para: '\u00B6',
    		parallel: '\u2225',
    		parsim: '\u2AF3',
    		parsl: '\u2AFD',
    		part: '\u2202',
    		PartialD: '\u2202',
    		Pcy: '\u041F',
    		pcy: '\u043F',
    		percnt: '\u0025',
    		period: '\u002E',
    		permil: '\u2030',
    		perp: '\u22A5',
    		pertenk: '\u2031',
    		Pfr: '\uD835\uDD13',
    		pfr: '\uD835\uDD2D',
    		Phi: '\u03A6',
    		phi: '\u03C6',
    		phiv: '\u03D5',
    		phmmat: '\u2133',
    		phone: '\u260E',
    		Pi: '\u03A0',
    		pi: '\u03C0',
    		pitchfork: '\u22D4',
    		piv: '\u03D6',
    		planck: '\u210F',
    		planckh: '\u210E',
    		plankv: '\u210F',
    		plus: '\u002B',
    		plusacir: '\u2A23',
    		plusb: '\u229E',
    		pluscir: '\u2A22',
    		plusdo: '\u2214',
    		plusdu: '\u2A25',
    		pluse: '\u2A72',
    		PlusMinus: '\u00B1',
    		plusmn: '\u00B1',
    		plussim: '\u2A26',
    		plustwo: '\u2A27',
    		pm: '\u00B1',
    		Poincareplane: '\u210C',
    		pointint: '\u2A15',
    		Popf: '\u2119',
    		popf: '\uD835\uDD61',
    		pound: '\u00A3',
    		Pr: '\u2ABB',
    		pr: '\u227A',
    		prap: '\u2AB7',
    		prcue: '\u227C',
    		prE: '\u2AB3',
    		pre: '\u2AAF',
    		prec: '\u227A',
    		precapprox: '\u2AB7',
    		preccurlyeq: '\u227C',
    		Precedes: '\u227A',
    		PrecedesEqual: '\u2AAF',
    		PrecedesSlantEqual: '\u227C',
    		PrecedesTilde: '\u227E',
    		preceq: '\u2AAF',
    		precnapprox: '\u2AB9',
    		precneqq: '\u2AB5',
    		precnsim: '\u22E8',
    		precsim: '\u227E',
    		Prime: '\u2033',
    		prime: '\u2032',
    		primes: '\u2119',
    		prnap: '\u2AB9',
    		prnE: '\u2AB5',
    		prnsim: '\u22E8',
    		prod: '\u220F',
    		Product: '\u220F',
    		profalar: '\u232E',
    		profline: '\u2312',
    		profsurf: '\u2313',
    		prop: '\u221D',
    		Proportion: '\u2237',
    		Proportional: '\u221D',
    		propto: '\u221D',
    		prsim: '\u227E',
    		prurel: '\u22B0',
    		Pscr: '\uD835\uDCAB',
    		pscr: '\uD835\uDCC5',
    		Psi: '\u03A8',
    		psi: '\u03C8',
    		puncsp: '\u2008',
    		Qfr: '\uD835\uDD14',
    		qfr: '\uD835\uDD2E',
    		qint: '\u2A0C',
    		Qopf: '\u211A',
    		qopf: '\uD835\uDD62',
    		qprime: '\u2057',
    		Qscr: '\uD835\uDCAC',
    		qscr: '\uD835\uDCC6',
    		quaternions: '\u210D',
    		quatint: '\u2A16',
    		quest: '\u003F',
    		questeq: '\u225F',
    		QUOT: '\u0022',
    		quot: '\u0022',
    		rAarr: '\u21DB',
    		race: '\u223D\u0331',
    		Racute: '\u0154',
    		racute: '\u0155',
    		radic: '\u221A',
    		raemptyv: '\u29B3',
    		Rang: '\u27EB',
    		rang: '\u27E9',
    		rangd: '\u2992',
    		range: '\u29A5',
    		rangle: '\u27E9',
    		raquo: '\u00BB',
    		Rarr: '\u21A0',
    		rArr: '\u21D2',
    		rarr: '\u2192',
    		rarrap: '\u2975',
    		rarrb: '\u21E5',
    		rarrbfs: '\u2920',
    		rarrc: '\u2933',
    		rarrfs: '\u291E',
    		rarrhk: '\u21AA',
    		rarrlp: '\u21AC',
    		rarrpl: '\u2945',
    		rarrsim: '\u2974',
    		Rarrtl: '\u2916',
    		rarrtl: '\u21A3',
    		rarrw: '\u219D',
    		rAtail: '\u291C',
    		ratail: '\u291A',
    		ratio: '\u2236',
    		rationals: '\u211A',
    		RBarr: '\u2910',
    		rBarr: '\u290F',
    		rbarr: '\u290D',
    		rbbrk: '\u2773',
    		rbrace: '\u007D',
    		rbrack: '\u005D',
    		rbrke: '\u298C',
    		rbrksld: '\u298E',
    		rbrkslu: '\u2990',
    		Rcaron: '\u0158',
    		rcaron: '\u0159',
    		Rcedil: '\u0156',
    		rcedil: '\u0157',
    		rceil: '\u2309',
    		rcub: '\u007D',
    		Rcy: '\u0420',
    		rcy: '\u0440',
    		rdca: '\u2937',
    		rdldhar: '\u2969',
    		rdquo: '\u201D',
    		rdquor: '\u201D',
    		rdsh: '\u21B3',
    		Re: '\u211C',
    		real: '\u211C',
    		realine: '\u211B',
    		realpart: '\u211C',
    		reals: '\u211D',
    		rect: '\u25AD',
    		REG: '\u00AE',
    		reg: '\u00AE',
    		ReverseElement: '\u220B',
    		ReverseEquilibrium: '\u21CB',
    		ReverseUpEquilibrium: '\u296F',
    		rfisht: '\u297D',
    		rfloor: '\u230B',
    		Rfr: '\u211C',
    		rfr: '\uD835\uDD2F',
    		rHar: '\u2964',
    		rhard: '\u21C1',
    		rharu: '\u21C0',
    		rharul: '\u296C',
    		Rho: '\u03A1',
    		rho: '\u03C1',
    		rhov: '\u03F1',
    		RightAngleBracket: '\u27E9',
    		RightArrow: '\u2192',
    		Rightarrow: '\u21D2',
    		rightarrow: '\u2192',
    		RightArrowBar: '\u21E5',
    		RightArrowLeftArrow: '\u21C4',
    		rightarrowtail: '\u21A3',
    		RightCeiling: '\u2309',
    		RightDoubleBracket: '\u27E7',
    		RightDownTeeVector: '\u295D',
    		RightDownVector: '\u21C2',
    		RightDownVectorBar: '\u2955',
    		RightFloor: '\u230B',
    		rightharpoondown: '\u21C1',
    		rightharpoonup: '\u21C0',
    		rightleftarrows: '\u21C4',
    		rightleftharpoons: '\u21CC',
    		rightrightarrows: '\u21C9',
    		rightsquigarrow: '\u219D',
    		RightTee: '\u22A2',
    		RightTeeArrow: '\u21A6',
    		RightTeeVector: '\u295B',
    		rightthreetimes: '\u22CC',
    		RightTriangle: '\u22B3',
    		RightTriangleBar: '\u29D0',
    		RightTriangleEqual: '\u22B5',
    		RightUpDownVector: '\u294F',
    		RightUpTeeVector: '\u295C',
    		RightUpVector: '\u21BE',
    		RightUpVectorBar: '\u2954',
    		RightVector: '\u21C0',
    		RightVectorBar: '\u2953',
    		ring: '\u02DA',
    		risingdotseq: '\u2253',
    		rlarr: '\u21C4',
    		rlhar: '\u21CC',
    		rlm: '\u200F',
    		rmoust: '\u23B1',
    		rmoustache: '\u23B1',
    		rnmid: '\u2AEE',
    		roang: '\u27ED',
    		roarr: '\u21FE',
    		robrk: '\u27E7',
    		ropar: '\u2986',
    		Ropf: '\u211D',
    		ropf: '\uD835\uDD63',
    		roplus: '\u2A2E',
    		rotimes: '\u2A35',
    		RoundImplies: '\u2970',
    		rpar: '\u0029',
    		rpargt: '\u2994',
    		rppolint: '\u2A12',
    		rrarr: '\u21C9',
    		Rrightarrow: '\u21DB',
    		rsaquo: '\u203A',
    		Rscr: '\u211B',
    		rscr: '\uD835\uDCC7',
    		Rsh: '\u21B1',
    		rsh: '\u21B1',
    		rsqb: '\u005D',
    		rsquo: '\u2019',
    		rsquor: '\u2019',
    		rthree: '\u22CC',
    		rtimes: '\u22CA',
    		rtri: '\u25B9',
    		rtrie: '\u22B5',
    		rtrif: '\u25B8',
    		rtriltri: '\u29CE',
    		RuleDelayed: '\u29F4',
    		ruluhar: '\u2968',
    		rx: '\u211E',
    		Sacute: '\u015A',
    		sacute: '\u015B',
    		sbquo: '\u201A',
    		Sc: '\u2ABC',
    		sc: '\u227B',
    		scap: '\u2AB8',
    		Scaron: '\u0160',
    		scaron: '\u0161',
    		sccue: '\u227D',
    		scE: '\u2AB4',
    		sce: '\u2AB0',
    		Scedil: '\u015E',
    		scedil: '\u015F',
    		Scirc: '\u015C',
    		scirc: '\u015D',
    		scnap: '\u2ABA',
    		scnE: '\u2AB6',
    		scnsim: '\u22E9',
    		scpolint: '\u2A13',
    		scsim: '\u227F',
    		Scy: '\u0421',
    		scy: '\u0441',
    		sdot: '\u22C5',
    		sdotb: '\u22A1',
    		sdote: '\u2A66',
    		searhk: '\u2925',
    		seArr: '\u21D8',
    		searr: '\u2198',
    		searrow: '\u2198',
    		sect: '\u00A7',
    		semi: '\u003B',
    		seswar: '\u2929',
    		setminus: '\u2216',
    		setmn: '\u2216',
    		sext: '\u2736',
    		Sfr: '\uD835\uDD16',
    		sfr: '\uD835\uDD30',
    		sfrown: '\u2322',
    		sharp: '\u266F',
    		SHCHcy: '\u0429',
    		shchcy: '\u0449',
    		SHcy: '\u0428',
    		shcy: '\u0448',
    		ShortDownArrow: '\u2193',
    		ShortLeftArrow: '\u2190',
    		shortmid: '\u2223',
    		shortparallel: '\u2225',
    		ShortRightArrow: '\u2192',
    		ShortUpArrow: '\u2191',
    		shy: '\u00AD',
    		Sigma: '\u03A3',
    		sigma: '\u03C3',
    		sigmaf: '\u03C2',
    		sigmav: '\u03C2',
    		sim: '\u223C',
    		simdot: '\u2A6A',
    		sime: '\u2243',
    		simeq: '\u2243',
    		simg: '\u2A9E',
    		simgE: '\u2AA0',
    		siml: '\u2A9D',
    		simlE: '\u2A9F',
    		simne: '\u2246',
    		simplus: '\u2A24',
    		simrarr: '\u2972',
    		slarr: '\u2190',
    		SmallCircle: '\u2218',
    		smallsetminus: '\u2216',
    		smashp: '\u2A33',
    		smeparsl: '\u29E4',
    		smid: '\u2223',
    		smile: '\u2323',
    		smt: '\u2AAA',
    		smte: '\u2AAC',
    		smtes: '\u2AAC\uFE00',
    		SOFTcy: '\u042C',
    		softcy: '\u044C',
    		sol: '\u002F',
    		solb: '\u29C4',
    		solbar: '\u233F',
    		Sopf: '\uD835\uDD4A',
    		sopf: '\uD835\uDD64',
    		spades: '\u2660',
    		spadesuit: '\u2660',
    		spar: '\u2225',
    		sqcap: '\u2293',
    		sqcaps: '\u2293\uFE00',
    		sqcup: '\u2294',
    		sqcups: '\u2294\uFE00',
    		Sqrt: '\u221A',
    		sqsub: '\u228F',
    		sqsube: '\u2291',
    		sqsubset: '\u228F',
    		sqsubseteq: '\u2291',
    		sqsup: '\u2290',
    		sqsupe: '\u2292',
    		sqsupset: '\u2290',
    		sqsupseteq: '\u2292',
    		squ: '\u25A1',
    		Square: '\u25A1',
    		square: '\u25A1',
    		SquareIntersection: '\u2293',
    		SquareSubset: '\u228F',
    		SquareSubsetEqual: '\u2291',
    		SquareSuperset: '\u2290',
    		SquareSupersetEqual: '\u2292',
    		SquareUnion: '\u2294',
    		squarf: '\u25AA',
    		squf: '\u25AA',
    		srarr: '\u2192',
    		Sscr: '\uD835\uDCAE',
    		sscr: '\uD835\uDCC8',
    		ssetmn: '\u2216',
    		ssmile: '\u2323',
    		sstarf: '\u22C6',
    		Star: '\u22C6',
    		star: '\u2606',
    		starf: '\u2605',
    		straightepsilon: '\u03F5',
    		straightphi: '\u03D5',
    		strns: '\u00AF',
    		Sub: '\u22D0',
    		sub: '\u2282',
    		subdot: '\u2ABD',
    		subE: '\u2AC5',
    		sube: '\u2286',
    		subedot: '\u2AC3',
    		submult: '\u2AC1',
    		subnE: '\u2ACB',
    		subne: '\u228A',
    		subplus: '\u2ABF',
    		subrarr: '\u2979',
    		Subset: '\u22D0',
    		subset: '\u2282',
    		subseteq: '\u2286',
    		subseteqq: '\u2AC5',
    		SubsetEqual: '\u2286',
    		subsetneq: '\u228A',
    		subsetneqq: '\u2ACB',
    		subsim: '\u2AC7',
    		subsub: '\u2AD5',
    		subsup: '\u2AD3',
    		succ: '\u227B',
    		succapprox: '\u2AB8',
    		succcurlyeq: '\u227D',
    		Succeeds: '\u227B',
    		SucceedsEqual: '\u2AB0',
    		SucceedsSlantEqual: '\u227D',
    		SucceedsTilde: '\u227F',
    		succeq: '\u2AB0',
    		succnapprox: '\u2ABA',
    		succneqq: '\u2AB6',
    		succnsim: '\u22E9',
    		succsim: '\u227F',
    		SuchThat: '\u220B',
    		Sum: '\u2211',
    		sum: '\u2211',
    		sung: '\u266A',
    		Sup: '\u22D1',
    		sup: '\u2283',
    		sup1: '\u00B9',
    		sup2: '\u00B2',
    		sup3: '\u00B3',
    		supdot: '\u2ABE',
    		supdsub: '\u2AD8',
    		supE: '\u2AC6',
    		supe: '\u2287',
    		supedot: '\u2AC4',
    		Superset: '\u2283',
    		SupersetEqual: '\u2287',
    		suphsol: '\u27C9',
    		suphsub: '\u2AD7',
    		suplarr: '\u297B',
    		supmult: '\u2AC2',
    		supnE: '\u2ACC',
    		supne: '\u228B',
    		supplus: '\u2AC0',
    		Supset: '\u22D1',
    		supset: '\u2283',
    		supseteq: '\u2287',
    		supseteqq: '\u2AC6',
    		supsetneq: '\u228B',
    		supsetneqq: '\u2ACC',
    		supsim: '\u2AC8',
    		supsub: '\u2AD4',
    		supsup: '\u2AD6',
    		swarhk: '\u2926',
    		swArr: '\u21D9',
    		swarr: '\u2199',
    		swarrow: '\u2199',
    		swnwar: '\u292A',
    		szlig: '\u00DF',
    		Tab: '\u0009',
    		target: '\u2316',
    		Tau: '\u03A4',
    		tau: '\u03C4',
    		tbrk: '\u23B4',
    		Tcaron: '\u0164',
    		tcaron: '\u0165',
    		Tcedil: '\u0162',
    		tcedil: '\u0163',
    		Tcy: '\u0422',
    		tcy: '\u0442',
    		tdot: '\u20DB',
    		telrec: '\u2315',
    		Tfr: '\uD835\uDD17',
    		tfr: '\uD835\uDD31',
    		there4: '\u2234',
    		Therefore: '\u2234',
    		therefore: '\u2234',
    		Theta: '\u0398',
    		theta: '\u03B8',
    		thetasym: '\u03D1',
    		thetav: '\u03D1',
    		thickapprox: '\u2248',
    		thicksim: '\u223C',
    		ThickSpace: '\u205F\u200A',
    		thinsp: '\u2009',
    		ThinSpace: '\u2009',
    		thkap: '\u2248',
    		thksim: '\u223C',
    		THORN: '\u00DE',
    		thorn: '\u00FE',
    		Tilde: '\u223C',
    		tilde: '\u02DC',
    		TildeEqual: '\u2243',
    		TildeFullEqual: '\u2245',
    		TildeTilde: '\u2248',
    		times: '\u00D7',
    		timesb: '\u22A0',
    		timesbar: '\u2A31',
    		timesd: '\u2A30',
    		tint: '\u222D',
    		toea: '\u2928',
    		top: '\u22A4',
    		topbot: '\u2336',
    		topcir: '\u2AF1',
    		Topf: '\uD835\uDD4B',
    		topf: '\uD835\uDD65',
    		topfork: '\u2ADA',
    		tosa: '\u2929',
    		tprime: '\u2034',
    		TRADE: '\u2122',
    		trade: '\u2122',
    		triangle: '\u25B5',
    		triangledown: '\u25BF',
    		triangleleft: '\u25C3',
    		trianglelefteq: '\u22B4',
    		triangleq: '\u225C',
    		triangleright: '\u25B9',
    		trianglerighteq: '\u22B5',
    		tridot: '\u25EC',
    		trie: '\u225C',
    		triminus: '\u2A3A',
    		TripleDot: '\u20DB',
    		triplus: '\u2A39',
    		trisb: '\u29CD',
    		tritime: '\u2A3B',
    		trpezium: '\u23E2',
    		Tscr: '\uD835\uDCAF',
    		tscr: '\uD835\uDCC9',
    		TScy: '\u0426',
    		tscy: '\u0446',
    		TSHcy: '\u040B',
    		tshcy: '\u045B',
    		Tstrok: '\u0166',
    		tstrok: '\u0167',
    		twixt: '\u226C',
    		twoheadleftarrow: '\u219E',
    		twoheadrightarrow: '\u21A0',
    		Uacute: '\u00DA',
    		uacute: '\u00FA',
    		Uarr: '\u219F',
    		uArr: '\u21D1',
    		uarr: '\u2191',
    		Uarrocir: '\u2949',
    		Ubrcy: '\u040E',
    		ubrcy: '\u045E',
    		Ubreve: '\u016C',
    		ubreve: '\u016D',
    		Ucirc: '\u00DB',
    		ucirc: '\u00FB',
    		Ucy: '\u0423',
    		ucy: '\u0443',
    		udarr: '\u21C5',
    		Udblac: '\u0170',
    		udblac: '\u0171',
    		udhar: '\u296E',
    		ufisht: '\u297E',
    		Ufr: '\uD835\uDD18',
    		ufr: '\uD835\uDD32',
    		Ugrave: '\u00D9',
    		ugrave: '\u00F9',
    		uHar: '\u2963',
    		uharl: '\u21BF',
    		uharr: '\u21BE',
    		uhblk: '\u2580',
    		ulcorn: '\u231C',
    		ulcorner: '\u231C',
    		ulcrop: '\u230F',
    		ultri: '\u25F8',
    		Umacr: '\u016A',
    		umacr: '\u016B',
    		uml: '\u00A8',
    		UnderBar: '\u005F',
    		UnderBrace: '\u23DF',
    		UnderBracket: '\u23B5',
    		UnderParenthesis: '\u23DD',
    		Union: '\u22C3',
    		UnionPlus: '\u228E',
    		Uogon: '\u0172',
    		uogon: '\u0173',
    		Uopf: '\uD835\uDD4C',
    		uopf: '\uD835\uDD66',
    		UpArrow: '\u2191',
    		Uparrow: '\u21D1',
    		uparrow: '\u2191',
    		UpArrowBar: '\u2912',
    		UpArrowDownArrow: '\u21C5',
    		UpDownArrow: '\u2195',
    		Updownarrow: '\u21D5',
    		updownarrow: '\u2195',
    		UpEquilibrium: '\u296E',
    		upharpoonleft: '\u21BF',
    		upharpoonright: '\u21BE',
    		uplus: '\u228E',
    		UpperLeftArrow: '\u2196',
    		UpperRightArrow: '\u2197',
    		Upsi: '\u03D2',
    		upsi: '\u03C5',
    		upsih: '\u03D2',
    		Upsilon: '\u03A5',
    		upsilon: '\u03C5',
    		UpTee: '\u22A5',
    		UpTeeArrow: '\u21A5',
    		upuparrows: '\u21C8',
    		urcorn: '\u231D',
    		urcorner: '\u231D',
    		urcrop: '\u230E',
    		Uring: '\u016E',
    		uring: '\u016F',
    		urtri: '\u25F9',
    		Uscr: '\uD835\uDCB0',
    		uscr: '\uD835\uDCCA',
    		utdot: '\u22F0',
    		Utilde: '\u0168',
    		utilde: '\u0169',
    		utri: '\u25B5',
    		utrif: '\u25B4',
    		uuarr: '\u21C8',
    		Uuml: '\u00DC',
    		uuml: '\u00FC',
    		uwangle: '\u29A7',
    		vangrt: '\u299C',
    		varepsilon: '\u03F5',
    		varkappa: '\u03F0',
    		varnothing: '\u2205',
    		varphi: '\u03D5',
    		varpi: '\u03D6',
    		varpropto: '\u221D',
    		vArr: '\u21D5',
    		varr: '\u2195',
    		varrho: '\u03F1',
    		varsigma: '\u03C2',
    		varsubsetneq: '\u228A\uFE00',
    		varsubsetneqq: '\u2ACB\uFE00',
    		varsupsetneq: '\u228B\uFE00',
    		varsupsetneqq: '\u2ACC\uFE00',
    		vartheta: '\u03D1',
    		vartriangleleft: '\u22B2',
    		vartriangleright: '\u22B3',
    		Vbar: '\u2AEB',
    		vBar: '\u2AE8',
    		vBarv: '\u2AE9',
    		Vcy: '\u0412',
    		vcy: '\u0432',
    		VDash: '\u22AB',
    		Vdash: '\u22A9',
    		vDash: '\u22A8',
    		vdash: '\u22A2',
    		Vdashl: '\u2AE6',
    		Vee: '\u22C1',
    		vee: '\u2228',
    		veebar: '\u22BB',
    		veeeq: '\u225A',
    		vellip: '\u22EE',
    		Verbar: '\u2016',
    		verbar: '\u007C',
    		Vert: '\u2016',
    		vert: '\u007C',
    		VerticalBar: '\u2223',
    		VerticalLine: '\u007C',
    		VerticalSeparator: '\u2758',
    		VerticalTilde: '\u2240',
    		VeryThinSpace: '\u200A',
    		Vfr: '\uD835\uDD19',
    		vfr: '\uD835\uDD33',
    		vltri: '\u22B2',
    		vnsub: '\u2282\u20D2',
    		vnsup: '\u2283\u20D2',
    		Vopf: '\uD835\uDD4D',
    		vopf: '\uD835\uDD67',
    		vprop: '\u221D',
    		vrtri: '\u22B3',
    		Vscr: '\uD835\uDCB1',
    		vscr: '\uD835\uDCCB',
    		vsubnE: '\u2ACB\uFE00',
    		vsubne: '\u228A\uFE00',
    		vsupnE: '\u2ACC\uFE00',
    		vsupne: '\u228B\uFE00',
    		Vvdash: '\u22AA',
    		vzigzag: '\u299A',
    		Wcirc: '\u0174',
    		wcirc: '\u0175',
    		wedbar: '\u2A5F',
    		Wedge: '\u22C0',
    		wedge: '\u2227',
    		wedgeq: '\u2259',
    		weierp: '\u2118',
    		Wfr: '\uD835\uDD1A',
    		wfr: '\uD835\uDD34',
    		Wopf: '\uD835\uDD4E',
    		wopf: '\uD835\uDD68',
    		wp: '\u2118',
    		wr: '\u2240',
    		wreath: '\u2240',
    		Wscr: '\uD835\uDCB2',
    		wscr: '\uD835\uDCCC',
    		xcap: '\u22C2',
    		xcirc: '\u25EF',
    		xcup: '\u22C3',
    		xdtri: '\u25BD',
    		Xfr: '\uD835\uDD1B',
    		xfr: '\uD835\uDD35',
    		xhArr: '\u27FA',
    		xharr: '\u27F7',
    		Xi: '\u039E',
    		xi: '\u03BE',
    		xlArr: '\u27F8',
    		xlarr: '\u27F5',
    		xmap: '\u27FC',
    		xnis: '\u22FB',
    		xodot: '\u2A00',
    		Xopf: '\uD835\uDD4F',
    		xopf: '\uD835\uDD69',
    		xoplus: '\u2A01',
    		xotime: '\u2A02',
    		xrArr: '\u27F9',
    		xrarr: '\u27F6',
    		Xscr: '\uD835\uDCB3',
    		xscr: '\uD835\uDCCD',
    		xsqcup: '\u2A06',
    		xuplus: '\u2A04',
    		xutri: '\u25B3',
    		xvee: '\u22C1',
    		xwedge: '\u22C0',
    		Yacute: '\u00DD',
    		yacute: '\u00FD',
    		YAcy: '\u042F',
    		yacy: '\u044F',
    		Ycirc: '\u0176',
    		ycirc: '\u0177',
    		Ycy: '\u042B',
    		ycy: '\u044B',
    		yen: '\u00A5',
    		Yfr: '\uD835\uDD1C',
    		yfr: '\uD835\uDD36',
    		YIcy: '\u0407',
    		yicy: '\u0457',
    		Yopf: '\uD835\uDD50',
    		yopf: '\uD835\uDD6A',
    		Yscr: '\uD835\uDCB4',
    		yscr: '\uD835\uDCCE',
    		YUcy: '\u042E',
    		yucy: '\u044E',
    		Yuml: '\u0178',
    		yuml: '\u00FF',
    		Zacute: '\u0179',
    		zacute: '\u017A',
    		Zcaron: '\u017D',
    		zcaron: '\u017E',
    		Zcy: '\u0417',
    		zcy: '\u0437',
    		Zdot: '\u017B',
    		zdot: '\u017C',
    		zeetrf: '\u2128',
    		ZeroWidthSpace: '\u200B',
    		Zeta: '\u0396',
    		zeta: '\u03B6',
    		Zfr: '\u2128',
    		zfr: '\uD835\uDD37',
    		ZHcy: '\u0416',
    		zhcy: '\u0436',
    		zigrarr: '\u21DD',
    		Zopf: '\u2124',
    		zopf: '\uD835\uDD6B',
    		Zscr: '\uD835\uDCB5',
    		zscr: '\uD835\uDCCF',
    		zwj: '\u200D',
    		zwnj: '\u200C',
    	});

    	/**
    	 * @deprecated use `HTML_ENTITIES` instead
    	 * @see HTML_ENTITIES
    	 */
    	exports.entityMap = exports.HTML_ENTITIES; 
    } (entities$2));

    var entities$1 = /*@__PURE__*/getDefaultExportFromCjs(entities$2);

    var sax$1 = {};

    var NAMESPACE$1 = conventions$2.NAMESPACE;

    //[4]   	NameStartChar	   ::=   	":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
    //[4a]   	NameChar	   ::=   	NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
    //[5]   	Name	   ::=   	NameStartChar (NameChar)*
    var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;//\u10000-\uEFFFF
    var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
    var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
    //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
    //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')

    //S_TAG,	S_ATTR,	S_EQ,	S_ATTR_NOQUOT_VALUE
    //S_ATTR_SPACE,	S_ATTR_END,	S_TAG_SPACE, S_TAG_CLOSE
    var S_TAG = 0;//tag name offerring
    var S_ATTR = 1;//attr name offerring
    var S_ATTR_SPACE=2;//attr name end and space offer
    var S_EQ = 3;//=space?
    var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
    var S_ATTR_END = 5;//attr value end and no space(quot end)
    var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
    var S_TAG_CLOSE = 7;//closed el<el />

    /**
     * Creates an error that will not be caught by XMLReader aka the SAX parser.
     *
     * @param {string} message
     * @param {any?} locator Optional, can provide details about the location in the source
     * @constructor
     */
    function ParseError$1(message, locator) {
    	this.message = message;
    	this.locator = locator;
    	if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError$1);
    }
    ParseError$1.prototype = new Error();
    ParseError$1.prototype.name = ParseError$1.name;

    function XMLReader$1(){

    }

    XMLReader$1.prototype = {
    	parse:function(source,defaultNSMap,entityMap){
    		var domBuilder = this.domBuilder;
    		domBuilder.startDocument();
    		_copy(defaultNSMap ,defaultNSMap = {});
    		parse$2(source,defaultNSMap,entityMap,
    				domBuilder,this.errorHandler);
    		domBuilder.endDocument();
    	}
    };
    function parse$2(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
    	function fixedFromCharCode(code) {
    		// String.prototype.fromCharCode does not supports
    		// > 2 bytes unicode chars directly
    		if (code > 0xffff) {
    			code -= 0x10000;
    			var surrogate1 = 0xd800 + (code >> 10)
    				, surrogate2 = 0xdc00 + (code & 0x3ff);

    			return String.fromCharCode(surrogate1, surrogate2);
    		} else {
    			return String.fromCharCode(code);
    		}
    	}
    	function entityReplacer(a){
    		var k = a.slice(1,-1);
    		if (Object.hasOwnProperty.call(entityMap, k)) {
    			return entityMap[k];
    		}else if(k.charAt(0) === '#'){
    			return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
    		}else {
    			errorHandler.error('entity not found:'+a);
    			return a;
    		}
    	}
    	function appendText(end){//has some bugs
    		if(end>start){
    			var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
    			locator&&position(start);
    			domBuilder.characters(xt,0,end-start);
    			start = end;
    		}
    	}
    	function position(p,m){
    		while(p>=lineEnd && (m = linePattern.exec(source))){
    			lineStart = m.index;
    			lineEnd = lineStart + m[0].length;
    			locator.lineNumber++;
    			//console.log('line++:',locator,startPos,endPos)
    		}
    		locator.columnNumber = p-lineStart+1;
    	}
    	var lineStart = 0;
    	var lineEnd = 0;
    	var linePattern = /.*(?:\r\n?|\n)|.*$/g;
    	var locator = domBuilder.locator;

    	var parseStack = [{currentNSMap:defaultNSMapCopy}];
    	var closeMap = {};
    	var start = 0;
    	while(true){
    		try{
    			var tagStart = source.indexOf('<',start);
    			if(tagStart<0){
    				if(!source.substr(start).match(/^\s*$/)){
    					var doc = domBuilder.doc;
    	    			var text = doc.createTextNode(source.substr(start));
    	    			doc.appendChild(text);
    	    			domBuilder.currentElement = text;
    				}
    				return;
    			}
    			if(tagStart>start){
    				appendText(tagStart);
    			}
    			switch(source.charAt(tagStart+1)){
    			case '/':
    				var end = source.indexOf('>',tagStart+3);
    				var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, '');
    				var config = parseStack.pop();
    				if(end<0){

    	        		tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
    	        		errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
    	        		end = tagStart+1+tagName.length;
    	        	}else if(tagName.match(/\s</)){
    	        		tagName = tagName.replace(/[\s<].*/,'');
    	        		errorHandler.error("end tag name: "+tagName+' maybe not complete');
    	        		end = tagStart+1+tagName.length;
    				}
    				var localNSMap = config.localNSMap;
    				var endMatch = config.tagName == tagName;
    				var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase();
    		        if(endIgnoreCaseMach){
    		        	domBuilder.endElement(config.uri,config.localName,tagName);
    					if(localNSMap){
    						for (var prefix in localNSMap) {
    							if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
    								domBuilder.endPrefixMapping(prefix);
    							}
    						}
    					}
    					if(!endMatch){
    		            	errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case
    					}
    		        }else {
    		        	parseStack.push(config);
    		        }

    				end++;
    				break;
    				// end elment
    			case '?':// <?...?>
    				locator&&position(tagStart);
    				end = parseInstruction(source,tagStart,domBuilder);
    				break;
    			case '!':// <!doctype,<![CDATA,<!--
    				locator&&position(tagStart);
    				end = parseDCC(source,tagStart,domBuilder,errorHandler);
    				break;
    			default:
    				locator&&position(tagStart);
    				var el = new ElementAttributes();
    				var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
    				//elStartEnd
    				var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
    				var len = el.length;


    				if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
    					el.closed = true;
    					if(!entityMap.nbsp){
    						errorHandler.warning('unclosed xml attribute');
    					}
    				}
    				if(locator && len){
    					var locator2 = copyLocator(locator,{});
    					//try{//attribute position fixed
    					for(var i = 0;i<len;i++){
    						var a = el[i];
    						position(a.offset);
    						a.locator = copyLocator(locator,{});
    					}
    					domBuilder.locator = locator2;
    					if(appendElement$1(el,domBuilder,currentNSMap)){
    						parseStack.push(el);
    					}
    					domBuilder.locator = locator;
    				}else {
    					if(appendElement$1(el,domBuilder,currentNSMap)){
    						parseStack.push(el);
    					}
    				}

    				if (NAMESPACE$1.isHTML(el.uri) && !el.closed) {
    					end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
    				} else {
    					end++;
    				}
    			}
    		}catch(e){
    			if (e instanceof ParseError$1) {
    				throw e;
    			}
    			errorHandler.error('element parse error: '+e);
    			end = -1;
    		}
    		if(end>start){
    			start = end;
    		}else {
    			//TODO: 这里有可能sax回退，有位置错误风险
    			appendText(Math.max(tagStart,start)+1);
    		}
    	}
    }
    function copyLocator(f,t){
    	t.lineNumber = f.lineNumber;
    	t.columnNumber = f.columnNumber;
    	return t;
    }

    /**
     * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
     * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
     */
    function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){

    	/**
    	 * @param {string} qname
    	 * @param {string} value
    	 * @param {number} startIndex
    	 */
    	function addAttribute(qname, value, startIndex) {
    		if (el.attributeNames.hasOwnProperty(qname)) {
    			errorHandler.fatalError('Attribute ' + qname + ' redefined');
    		}
    		el.addValue(
    			qname,
    			// @see https://www.w3.org/TR/xml/#AVNormalize
    			// since the xmldom sax parser does not "interpret" DTD the following is not implemented:
    			// - recursive replacement of (DTD) entity references
    			// - trimming and collapsing multiple spaces into a single one for attributes that are not of type CDATA
    			value.replace(/[\t\n\r]/g, ' ').replace(/&#?\w+;/g, entityReplacer),
    			startIndex
    		);
    	}
    	var attrName;
    	var value;
    	var p = ++start;
    	var s = S_TAG;//status
    	while(true){
    		var c = source.charAt(p);
    		switch(c){
    		case '=':
    			if(s === S_ATTR){//attrName
    				attrName = source.slice(start,p);
    				s = S_EQ;
    			}else if(s === S_ATTR_SPACE){
    				s = S_EQ;
    			}else {
    				//fatalError: equal must after attrName or space after attrName
    				throw new Error('attribute equal must after attrName'); // No known test case
    			}
    			break;
    		case '\'':
    		case '"':
    			if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
    				){//equal
    				if(s === S_ATTR){
    					errorHandler.warning('attribute value must after "="');
    					attrName = source.slice(start,p);
    				}
    				start = p+1;
    				p = source.indexOf(c,start);
    				if(p>0){
    					value = source.slice(start, p);
    					addAttribute(attrName, value, start-1);
    					s = S_ATTR_END;
    				}else {
    					//fatalError: no end quot match
    					throw new Error('attribute value no end \''+c+'\' match');
    				}
    			}else if(s == S_ATTR_NOQUOT_VALUE){
    				value = source.slice(start, p);
    				addAttribute(attrName, value, start);
    				errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
    				start = p+1;
    				s = S_ATTR_END;
    			}else {
    				//fatalError: no equal before
    				throw new Error('attribute value must after "="'); // No known test case
    			}
    			break;
    		case '/':
    			switch(s){
    			case S_TAG:
    				el.setTagName(source.slice(start,p));
    			case S_ATTR_END:
    			case S_TAG_SPACE:
    			case S_TAG_CLOSE:
    				s =S_TAG_CLOSE;
    				el.closed = true;
    			case S_ATTR_NOQUOT_VALUE:
    			case S_ATTR:
    				break;
    				case S_ATTR_SPACE:
    					el.closed = true;
    				break;
    			//case S_EQ:
    			default:
    				throw new Error("attribute invalid close char('/')") // No known test case
    			}
    			break;
    		case ''://end document
    			errorHandler.error('unexpected end of input');
    			if(s == S_TAG){
    				el.setTagName(source.slice(start,p));
    			}
    			return p;
    		case '>':
    			switch(s){
    			case S_TAG:
    				el.setTagName(source.slice(start,p));
    			case S_ATTR_END:
    			case S_TAG_SPACE:
    			case S_TAG_CLOSE:
    				break;//normal
    			case S_ATTR_NOQUOT_VALUE://Compatible state
    			case S_ATTR:
    				value = source.slice(start,p);
    				if(value.slice(-1) === '/'){
    					el.closed  = true;
    					value = value.slice(0,-1);
    				}
    			case S_ATTR_SPACE:
    				if(s === S_ATTR_SPACE){
    					value = attrName;
    				}
    				if(s == S_ATTR_NOQUOT_VALUE){
    					errorHandler.warning('attribute "'+value+'" missed quot(")!');
    					addAttribute(attrName, value, start);
    				}else {
    					if(!NAMESPACE$1.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){
    						errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
    					}
    					addAttribute(value, value, start);
    				}
    				break;
    			case S_EQ:
    				throw new Error('attribute value missed!!');
    			}
    //			console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
    			return p;
    		/*xml space '\x20' | #x9 | #xD | #xA; */
    		case '\u0080':
    			c = ' ';
    		default:
    			if(c<= ' '){//space
    				switch(s){
    				case S_TAG:
    					el.setTagName(source.slice(start,p));//tagName
    					s = S_TAG_SPACE;
    					break;
    				case S_ATTR:
    					attrName = source.slice(start,p);
    					s = S_ATTR_SPACE;
    					break;
    				case S_ATTR_NOQUOT_VALUE:
    					var value = source.slice(start, p);
    					errorHandler.warning('attribute "'+value+'" missed quot(")!!');
    					addAttribute(attrName, value, start);
    				case S_ATTR_END:
    					s = S_TAG_SPACE;
    					break;
    				//case S_TAG_SPACE:
    				//case S_EQ:
    				//case S_ATTR_SPACE:
    				//	void();break;
    				//case S_TAG_CLOSE:
    					//ignore warning
    				}
    			}else {//not space
    //S_TAG,	S_ATTR,	S_EQ,	S_ATTR_NOQUOT_VALUE
    //S_ATTR_SPACE,	S_ATTR_END,	S_TAG_SPACE, S_TAG_CLOSE
    				switch(s){
    				//case S_TAG:void();break;
    				//case S_ATTR:void();break;
    				//case S_ATTR_NOQUOT_VALUE:void();break;
    				case S_ATTR_SPACE:
    					var tagName =  el.tagName;
    					if (!NAMESPACE$1.isHTML(currentNSMap['']) || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
    						errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!');
    					}
    					addAttribute(attrName, attrName, start);
    					start = p;
    					s = S_ATTR;
    					break;
    				case S_ATTR_END:
    					errorHandler.warning('attribute space is required"'+attrName+'"!!');
    				case S_TAG_SPACE:
    					s = S_ATTR;
    					start = p;
    					break;
    				case S_EQ:
    					s = S_ATTR_NOQUOT_VALUE;
    					start = p;
    					break;
    				case S_TAG_CLOSE:
    					throw new Error("elements closed character '/' and '>' must be connected to");
    				}
    			}
    		}//end outer switch
    		//console.log('p++',p)
    		p++;
    	}
    }
    /**
     * @return true if has new namespace define
     */
    function appendElement$1(el,domBuilder,currentNSMap){
    	var tagName = el.tagName;
    	var localNSMap = null;
    	//var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
    	var i = el.length;
    	while(i--){
    		var a = el[i];
    		var qName = a.qName;
    		var value = a.value;
    		var nsp = qName.indexOf(':');
    		if(nsp>0){
    			var prefix = a.prefix = qName.slice(0,nsp);
    			var localName = qName.slice(nsp+1);
    			var nsPrefix = prefix === 'xmlns' && localName;
    		}else {
    			localName = qName;
    			prefix = null;
    			nsPrefix = qName === 'xmlns' && '';
    		}
    		//can not set prefix,because prefix !== ''
    		a.localName = localName ;
    		//prefix == null for no ns prefix attribute
    		if(nsPrefix !== false){//hack!!
    			if(localNSMap == null){
    				localNSMap = {};
    				//console.log(currentNSMap,0)
    				_copy(currentNSMap,currentNSMap={});
    				//console.log(currentNSMap,1)
    			}
    			currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
    			a.uri = NAMESPACE$1.XMLNS;
    			domBuilder.startPrefixMapping(nsPrefix, value);
    		}
    	}
    	var i = el.length;
    	while(i--){
    		a = el[i];
    		var prefix = a.prefix;
    		if(prefix){//no prefix attribute has no namespace
    			if(prefix === 'xml'){
    				a.uri = NAMESPACE$1.XML;
    			}if(prefix !== 'xmlns'){
    				a.uri = currentNSMap[prefix || ''];

    				//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
    			}
    		}
    	}
    	var nsp = tagName.indexOf(':');
    	if(nsp>0){
    		prefix = el.prefix = tagName.slice(0,nsp);
    		localName = el.localName = tagName.slice(nsp+1);
    	}else {
    		prefix = null;//important!!
    		localName = el.localName = tagName;
    	}
    	//no prefix element has default namespace
    	var ns = el.uri = currentNSMap[prefix || ''];
    	domBuilder.startElement(ns,localName,tagName,el);
    	//endPrefixMapping and startPrefixMapping have not any help for dom builder
    	//localNSMap = null
    	if(el.closed){
    		domBuilder.endElement(ns,localName,tagName);
    		if(localNSMap){
    			for (prefix in localNSMap) {
    				if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
    					domBuilder.endPrefixMapping(prefix);
    				}
    			}
    		}
    	}else {
    		el.currentNSMap = currentNSMap;
    		el.localNSMap = localNSMap;
    		//parseStack.push(el);
    		return true;
    	}
    }
    function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
    	if(/^(?:script|textarea)$/i.test(tagName)){
    		var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
    		var text = source.substring(elStartEnd+1,elEndStart);
    		if(/[&<]/.test(text)){
    			if(/^script$/i.test(tagName)){
    				//if(!/\]\]>/.test(text)){
    					//lexHandler.startCDATA();
    					domBuilder.characters(text,0,text.length);
    					//lexHandler.endCDATA();
    					return elEndStart;
    				//}
    			}//}else{//text area
    				text = text.replace(/&#?\w+;/g,entityReplacer);
    				domBuilder.characters(text,0,text.length);
    				return elEndStart;
    			//}

    		}
    	}
    	return elStartEnd+1;
    }
    function fixSelfClosed(source,elStartEnd,tagName,closeMap){
    	//if(tagName in closeMap){
    	var pos = closeMap[tagName];
    	if(pos == null){
    		//console.log(tagName)
    		pos =  source.lastIndexOf('</'+tagName+'>');
    		if(pos<elStartEnd){//忘记闭合
    			pos = source.lastIndexOf('</'+tagName);
    		}
    		closeMap[tagName] =pos;
    	}
    	return pos<elStartEnd;
    	//}
    }

    function _copy (source, target) {
    	for (var n in source) {
    		if (Object.prototype.hasOwnProperty.call(source, n)) {
    			target[n] = source[n];
    		}
    	}
    }

    function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
    	var next= source.charAt(start+2);
    	switch(next){
    	case '-':
    		if(source.charAt(start + 3) === '-'){
    			var end = source.indexOf('-->',start+4);
    			//append comment source.substring(4,end)//<!--
    			if(end>start){
    				domBuilder.comment(source,start+4,end-start-4);
    				return end+3;
    			}else {
    				errorHandler.error("Unclosed comment");
    				return -1;
    			}
    		}else {
    			//error
    			return -1;
    		}
    	default:
    		if(source.substr(start+3,6) == 'CDATA['){
    			var end = source.indexOf(']]>',start+9);
    			domBuilder.startCDATA();
    			domBuilder.characters(source,start+9,end-start-9);
    			domBuilder.endCDATA();
    			return end+3;
    		}
    		//<!DOCTYPE
    		//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
    		var matchs = split(source,start);
    		var len = matchs.length;
    		if(len>1 && /!doctype/i.test(matchs[0][0])){
    			var name = matchs[1][0];
    			var pubid = false;
    			var sysid = false;
    			if(len>3){
    				if(/^public$/i.test(matchs[2][0])){
    					pubid = matchs[3][0];
    					sysid = len>4 && matchs[4][0];
    				}else if(/^system$/i.test(matchs[2][0])){
    					sysid = matchs[3][0];
    				}
    			}
    			var lastMatch = matchs[len-1];
    			domBuilder.startDTD(name, pubid, sysid);
    			domBuilder.endDTD();

    			return lastMatch.index+lastMatch[0].length
    		}
    	}
    	return -1;
    }



    function parseInstruction(source,start,domBuilder){
    	var end = source.indexOf('?>',start);
    	if(end){
    		var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
    		if(match){
    			var len = match[0].length;
    			domBuilder.processingInstruction(match[1], match[2]) ;
    			return end+2;
    		}else {//error
    			return -1;
    		}
    	}
    	return -1;
    }

    function ElementAttributes(){
    	this.attributeNames = {};
    }
    ElementAttributes.prototype = {
    	setTagName:function(tagName){
    		if(!tagNamePattern.test(tagName)){
    			throw new Error('invalid tagName:'+tagName)
    		}
    		this.tagName = tagName;
    	},
    	addValue:function(qName, value, offset) {
    		if(!tagNamePattern.test(qName)){
    			throw new Error('invalid attribute:'+qName)
    		}
    		this.attributeNames[qName] = this.length;
    		this[this.length++] = {qName:qName,value:value,offset:offset};
    	},
    	length:0,
    	getLocalName:function(i){return this[i].localName},
    	getLocator:function(i){return this[i].locator},
    	getQName:function(i){return this[i].qName},
    	getURI:function(i){return this[i].uri},
    	getValue:function(i){return this[i].value}
    //	,getIndex:function(uri, localName)){
    //		if(localName){
    //
    //		}else{
    //			var qName = uri
    //		}
    //	},
    //	getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
    //	getType:function(uri,localName){}
    //	getType:function(i){},
    };



    function split(source,start){
    	var match;
    	var buf = [];
    	var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
    	reg.lastIndex = start;
    	reg.exec(source);//skip <
    	while(match = reg.exec(source)){
    		buf.push(match);
    		if(match[1])return buf;
    	}
    }

    var XMLReader_1 = sax$1.XMLReader = XMLReader$1;
    var ParseError_1 = sax$1.ParseError = ParseError$1;

    var conventions = conventions$2;
    var dom$1 = dom$2;
    var entities = entities$2;
    var sax = sax$1;

    var DOMImplementation$1 = dom$1.DOMImplementation;

    var NAMESPACE = conventions.NAMESPACE;

    var ParseError = sax.ParseError;
    var XMLReader = sax.XMLReader;

    /**
     * Normalizes line ending according to https://www.w3.org/TR/xml11/#sec-line-ends:
     *
     * > XML parsed entities are often stored in computer files which,
     * > for editing convenience, are organized into lines.
     * > These lines are typically separated by some combination
     * > of the characters CARRIAGE RETURN (#xD) and LINE FEED (#xA).
     * >
     * > To simplify the tasks of applications, the XML processor must behave
     * > as if it normalized all line breaks in external parsed entities (including the document entity)
     * > on input, before parsing, by translating all of the following to a single #xA character:
     * >
     * > 1. the two-character sequence #xD #xA
     * > 2. the two-character sequence #xD #x85
     * > 3. the single character #x85
     * > 4. the single character #x2028
     * > 5. any #xD character that is not immediately followed by #xA or #x85.
     *
     * @param {string} input
     * @returns {string}
     */
    function normalizeLineEndings(input) {
    	return input
    		.replace(/\r[\n\u0085]/g, '\n')
    		.replace(/[\r\u0085\u2028]/g, '\n')
    }

    /**
     * @typedef Locator
     * @property {number} [columnNumber]
     * @property {number} [lineNumber]
     */

    /**
     * @typedef DOMParserOptions
     * @property {DOMHandler} [domBuilder]
     * @property {Function} [errorHandler]
     * @property {(string) => string} [normalizeLineEndings] used to replace line endings before parsing
     * 						defaults to `normalizeLineEndings`
     * @property {Locator} [locator]
     * @property {Record<string, string>} [xmlns]
     *
     * @see normalizeLineEndings
     */

    /**
     * The DOMParser interface provides the ability to parse XML or HTML source code
     * from a string into a DOM `Document`.
     *
     * _xmldom is different from the spec in that it allows an `options` parameter,
     * to override the default behavior._
     *
     * @param {DOMParserOptions} [options]
     * @constructor
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
     * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsing-and-serialization
     */
    function DOMParser$2(options){
    	this.options = options ||{locator:{}};
    }

    DOMParser$2.prototype.parseFromString = function(source,mimeType){
    	var options = this.options;
    	var sax =  new XMLReader();
    	var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
    	var errorHandler = options.errorHandler;
    	var locator = options.locator;
    	var defaultNSMap = options.xmlns||{};
    	var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;
      	var entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES;
    	if(locator){
    		domBuilder.setDocumentLocator(locator);
    	}

    	sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
    	sax.domBuilder = options.domBuilder || domBuilder;
    	if(isHTML){
    		defaultNSMap[''] = NAMESPACE.HTML;
    	}
    	defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
    	var normalize = options.normalizeLineEndings || normalizeLineEndings;
    	if (source && typeof source === 'string') {
    		sax.parse(
    			normalize(source),
    			defaultNSMap,
    			entityMap
    		);
    	} else {
    		sax.errorHandler.error('invalid doc source');
    	}
    	return domBuilder.doc;
    };
    function buildErrorHandler(errorImpl,domBuilder,locator){
    	if(!errorImpl){
    		if(domBuilder instanceof DOMHandler){
    			return domBuilder;
    		}
    		errorImpl = domBuilder ;
    	}
    	var errorHandler = {};
    	var isCallback = errorImpl instanceof Function;
    	locator = locator||{};
    	function build(key){
    		var fn = errorImpl[key];
    		if(!fn && isCallback){
    			fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
    		}
    		errorHandler[key] = fn && function(msg){
    			fn('[xmldom '+key+']\t'+msg+_locator(locator));
    		}||function(){};
    	}
    	build('warning');
    	build('error');
    	build('fatalError');
    	return errorHandler;
    }

    //console.log('#\n\n\n\n\n\n\n####')
    /**
     * +ContentHandler+ErrorHandler
     * +LexicalHandler+EntityResolver2
     * -DeclHandler-DTDHandler
     *
     * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
     * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
     * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
     */
    function DOMHandler() {
        this.cdata = false;
    }
    function position(locator,node){
    	node.lineNumber = locator.lineNumber;
    	node.columnNumber = locator.columnNumber;
    }
    /**
     * @see org.xml.sax.ContentHandler#startDocument
     * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
     */
    DOMHandler.prototype = {
    	startDocument : function() {
        	this.doc = new DOMImplementation$1().createDocument(null, null, null);
        	if (this.locator) {
            	this.doc.documentURI = this.locator.systemId;
        	}
    	},
    	startElement:function(namespaceURI, localName, qName, attrs) {
    		var doc = this.doc;
    	    var el = doc.createElementNS(namespaceURI, qName||localName);
    	    var len = attrs.length;
    	    appendElement(this, el);
    	    this.currentElement = el;

    		this.locator && position(this.locator,el);
    	    for (var i = 0 ; i < len; i++) {
    	        var namespaceURI = attrs.getURI(i);
    	        var value = attrs.getValue(i);
    	        var qName = attrs.getQName(i);
    			var attr = doc.createAttributeNS(namespaceURI, qName);
    			this.locator &&position(attrs.getLocator(i),attr);
    			attr.value = attr.nodeValue = value;
    			el.setAttributeNode(attr);
    	    }
    	},
    	endElement:function(namespaceURI, localName, qName) {
    		var current = this.currentElement;
    		var tagName = current.tagName;
    		this.currentElement = current.parentNode;
    	},
    	startPrefixMapping:function(prefix, uri) {
    	},
    	endPrefixMapping:function(prefix) {
    	},
    	processingInstruction:function(target, data) {
    	    var ins = this.doc.createProcessingInstruction(target, data);
    	    this.locator && position(this.locator,ins);
    	    appendElement(this, ins);
    	},
    	ignorableWhitespace:function(ch, start, length) {
    	},
    	characters:function(chars, start, length) {
    		chars = _toString.apply(this,arguments);
    		//console.log(chars)
    		if(chars){
    			if (this.cdata) {
    				var charNode = this.doc.createCDATASection(chars);
    			} else {
    				var charNode = this.doc.createTextNode(chars);
    			}
    			if(this.currentElement){
    				this.currentElement.appendChild(charNode);
    			}else if(/^\s*$/.test(chars)){
    				this.doc.appendChild(charNode);
    				//process xml
    			}
    			this.locator && position(this.locator,charNode);
    		}
    	},
    	skippedEntity:function(name) {
    	},
    	endDocument:function() {
    		this.doc.normalize();
    	},
    	setDocumentLocator:function (locator) {
    	    if(this.locator = locator){// && !('lineNumber' in locator)){
    	    	locator.lineNumber = 0;
    	    }
    	},
    	//LexicalHandler
    	comment:function(chars, start, length) {
    		chars = _toString.apply(this,arguments);
    	    var comm = this.doc.createComment(chars);
    	    this.locator && position(this.locator,comm);
    	    appendElement(this, comm);
    	},

    	startCDATA:function() {
    	    //used in characters() methods
    	    this.cdata = true;
    	},
    	endCDATA:function() {
    	    this.cdata = false;
    	},

    	startDTD:function(name, publicId, systemId) {
    		var impl = this.doc.implementation;
    	    if (impl && impl.createDocumentType) {
    	        var dt = impl.createDocumentType(name, publicId, systemId);
    	        this.locator && position(this.locator,dt);
    	        appendElement(this, dt);
    					this.doc.doctype = dt;
    	    }
    	},
    	/**
    	 * @see org.xml.sax.ErrorHandler
    	 * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
    	 */
    	warning:function(error) {
    		console.warn('[xmldom warning]\t'+error,_locator(this.locator));
    	},
    	error:function(error) {
    		console.error('[xmldom error]\t'+error,_locator(this.locator));
    	},
    	fatalError:function(error) {
    		throw new ParseError(error, this.locator);
    	}
    };
    function _locator(l){
    	if(l){
    		return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
    	}
    }
    function _toString(chars,start,length){
    	if(typeof chars == 'string'){
    		return chars.substr(start,length)
    	}else {//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
    		if(chars.length >= start+length || start){
    			return new java.lang.String(chars,start,length)+'';
    		}
    		return chars;
    	}
    }

    /*
     * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
     * used method of org.xml.sax.ext.LexicalHandler:
     *  #comment(chars, start, length)
     *  #startCDATA()
     *  #endCDATA()
     *  #startDTD(name, publicId, systemId)
     *
     *
     * IGNORED method of org.xml.sax.ext.LexicalHandler:
     *  #endDTD()
     *  #startEntity(name)
     *  #endEntity(name)
     *
     *
     * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
     * IGNORED method of org.xml.sax.ext.DeclHandler
     * 	#attributeDecl(eName, aName, type, mode, value)
     *  #elementDecl(name, model)
     *  #externalEntityDecl(name, publicId, systemId)
     *  #internalEntityDecl(name, value)
     * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
     * IGNORED method of org.xml.sax.EntityResolver2
     *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
     *  #resolveEntity(publicId, systemId)
     *  #getExternalSubset(name, baseURI)
     * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
     * IGNORED method of org.xml.sax.DTDHandler
     *  #notationDecl(name, publicId, systemId) {};
     *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
     */
    "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
    	DOMHandler.prototype[key] = function(){return null};
    });

    /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
    function appendElement (hander,node) {
        if (!hander.currentElement) {
            hander.doc.appendChild(node);
        } else {
            hander.currentElement.appendChild(node);
        }
    }//appendChild and setAttributeNS are preformance key

    var __DOMHandler = domParser.__DOMHandler = DOMHandler;
    var normalizeLineEndings_1 = domParser.normalizeLineEndings = normalizeLineEndings;
    var DOMParser_1 = domParser.DOMParser = DOMParser$2;

    var dom = dom$2;
    var DOMImplementation = lib.DOMImplementation = dom.DOMImplementation;
    var XMLSerializer$1 = lib.XMLSerializer = dom.XMLSerializer;
    var DOMParser$1 = lib.DOMParser = domParser.DOMParser;

    "use strict";
    const WebWorkerAdapter = {
      createCanvas: (width, height) => new OffscreenCanvas(width != null ? width : 0, height != null ? height : 0),
      createImage: () => new Image(),
      getCanvasRenderingContext2D: () => OffscreenCanvasRenderingContext2D,
      getWebGLRenderingContext: () => WebGLRenderingContext,
      getNavigator: () => navigator,
      getBaseUrl: () => globalThis.location.href,
      getFontFaceSet: () => globalThis.fonts,
      fetch: (url, options) => fetch(url, options),
      parseXML: (xml) => {
        const parser = new DOMParser$1();
        return parser.parseFromString(xml, "text/xml");
      }
    };

    "use strict";
    var __defProp$1d = Object.defineProperty;
    var __defProps$u = Object.defineProperties;
    var __getOwnPropDescs$u = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$1f = Object.getOwnPropertySymbols;
    var __hasOwnProp$1f = Object.prototype.hasOwnProperty;
    var __propIsEnum$1f = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$1d = (obj, key, value) => key in obj ? __defProp$1d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$1d = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1f.call(b, prop))
          __defNormalProp$1d(a, prop, b[prop]);
      if (__getOwnPropSymbols$1f)
        for (var prop of __getOwnPropSymbols$1f(b)) {
          if (__propIsEnum$1f.call(b, prop))
            __defNormalProp$1d(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$u = (a, b) => __defProps$u(a, __getOwnPropDescs$u(b));
    var ExtensionType = /* @__PURE__ */ ((ExtensionType2) => {
      ExtensionType2["Application"] = "application";
      ExtensionType2["WebGLPipes"] = "webgl-pipes";
      ExtensionType2["WebGLPipesAdaptor"] = "webgl-pipes-adaptor";
      ExtensionType2["WebGLSystem"] = "webgl-system";
      ExtensionType2["WebGPUPipes"] = "webgpu-pipes";
      ExtensionType2["WebGPUPipesAdaptor"] = "webgpu-pipes-adaptor";
      ExtensionType2["WebGPUSystem"] = "webgpu-system";
      ExtensionType2["CanvasSystem"] = "canvas-system";
      ExtensionType2["CanvasPipesAdaptor"] = "canvas-pipes-adaptor";
      ExtensionType2["CanvasPipes"] = "canvas-pipes";
      ExtensionType2["Asset"] = "asset";
      ExtensionType2["LoadParser"] = "load-parser";
      ExtensionType2["ResolveParser"] = "resolve-parser";
      ExtensionType2["CacheParser"] = "cache-parser";
      ExtensionType2["DetectionParser"] = "detection-parser";
      ExtensionType2["MaskEffect"] = "mask-effect";
      ExtensionType2["BlendMode"] = "blend-mode";
      ExtensionType2["TextureSource"] = "texture-source";
      ExtensionType2["Environment"] = "environment";
      ExtensionType2["ShapeBuilder"] = "shape-builder";
      ExtensionType2["Batcher"] = "batcher";
      return ExtensionType2;
    })(ExtensionType || {});
    const normalizeExtension = (ext) => {
      if (typeof ext === "function" || typeof ext === "object" && ext.extension) {
        if (!ext.extension) {
          throw new Error("Extension class must have an extension object");
        }
        const metadata = typeof ext.extension !== "object" ? { type: ext.extension } : ext.extension;
        ext = __spreadProps$u(__spreadValues$1d({}, metadata), { ref: ext });
      }
      if (typeof ext === "object") {
        ext = __spreadValues$1d({}, ext);
      } else {
        throw new Error("Invalid extension type");
      }
      if (typeof ext.type === "string") {
        ext.type = [ext.type];
      }
      return ext;
    };
    const normalizeExtensionPriority = (ext, defaultPriority) => {
      var _a;
      return (_a = normalizeExtension(ext).priority) != null ? _a : defaultPriority;
    };
    const extensions = {
      /** @ignore */
      _addHandlers: {},
      /** @ignore */
      _removeHandlers: {},
      /** @ignore */
      _queue: {},
      /**
       * Remove extensions from PixiJS.
       * @param extensions - Extensions to be removed. Can be:
       * - Extension class with static `extension` property
       * - Extension format object with `type` and `ref`
       * - Multiple extensions as separate arguments
       * @returns {extensions} this for chaining
       * @example
       * ```ts
       * // Remove a single extension
       * extensions.remove(MyRendererPlugin);
       *
       * // Remove multiple extensions
       * extensions.remove(
       *     MyRendererPlugin,
       *     MySystemPlugin
       * );
       * ```
       * @see {@link ExtensionType} For available extension types
       * @see {@link ExtensionFormat} For extension format details
       */
      remove(...extensions2) {
        extensions2.map(normalizeExtension).forEach((ext) => {
          ext.type.forEach((type) => {
            var _a, _b;
            return (_b = (_a = this._removeHandlers)[type]) == null ? void 0 : _b.call(_a, ext);
          });
        });
        return this;
      },
      /**
       * Register new extensions with PixiJS. Extensions can be registered in multiple formats:
       * - As a class with a static `extension` property
       * - As an extension format object
       * - As multiple extensions passed as separate arguments
       * @param extensions - Extensions to add to PixiJS. Each can be:
       * - A class with static `extension` property
       * - An extension format object with `type` and `ref`
       * - Multiple extensions as separate arguments
       * @returns This extensions instance for chaining
       * @example
       * ```ts
       * // Register a simple extension
       * extensions.add(MyRendererPlugin);
       *
       * // Register multiple extensions
       * extensions.add(
       *     MyRendererPlugin,
       *     MySystemPlugin,
       * });
       * ```
       * @see {@link ExtensionType} For available extension types
       * @see {@link ExtensionFormat} For extension format details
       * @see {@link extensions.remove} For removing registered extensions
       */
      add(...extensions2) {
        extensions2.map(normalizeExtension).forEach((ext) => {
          ext.type.forEach((type) => {
            var _a, _b;
            const handlers = this._addHandlers;
            const queue = this._queue;
            if (!handlers[type]) {
              queue[type] = queue[type] || [];
              (_a = queue[type]) == null ? void 0 : _a.push(ext);
            } else {
              (_b = handlers[type]) == null ? void 0 : _b.call(handlers, ext);
            }
          });
        });
        return this;
      },
      /**
       * Internal method to handle extensions by name.
       * @param type - The extension type.
       * @param onAdd  - Function handler when extensions are added/registered {@link StrictExtensionFormat}.
       * @param onRemove  - Function handler when extensions are removed/unregistered {@link StrictExtensionFormat}.
       * @returns this for chaining.
       * @internal
       * @ignore
       */
      handle(type, onAdd, onRemove) {
        var _a;
        const addHandlers = this._addHandlers;
        const removeHandlers = this._removeHandlers;
        if (addHandlers[type] || removeHandlers[type]) {
          throw new Error(`Extension type ${type} already has a handler`);
        }
        addHandlers[type] = onAdd;
        removeHandlers[type] = onRemove;
        const queue = this._queue;
        if (queue[type]) {
          (_a = queue[type]) == null ? void 0 : _a.forEach((ext) => onAdd(ext));
          delete queue[type];
        }
        return this;
      },
      /**
       * Handle a type, but using a map by `name` property.
       * @param type - Type of extension to handle.
       * @param map - The object map of named extensions.
       * @returns this for chaining.
       * @ignore
       */
      handleByMap(type, map) {
        return this.handle(
          type,
          (extension) => {
            if (extension.name) {
              map[extension.name] = extension.ref;
            }
          },
          (extension) => {
            if (extension.name) {
              delete map[extension.name];
            }
          }
        );
      },
      /**
       * Handle a type, but using a list of extensions with a `name` property.
       * @param type - Type of extension to handle.
       * @param map - The array of named extensions.
       * @param defaultPriority - Fallback priority if none is defined.
       * @returns this for chaining.
       * @ignore
       */
      handleByNamedList(type, map, defaultPriority = -1) {
        return this.handle(
          type,
          (extension) => {
            const index = map.findIndex((item) => item.name === extension.name);
            if (index >= 0)
              return;
            map.push({ name: extension.name, value: extension.ref });
            map.sort((a, b) => normalizeExtensionPriority(b.value, defaultPriority) - normalizeExtensionPriority(a.value, defaultPriority));
          },
          (extension) => {
            const index = map.findIndex((item) => item.name === extension.name);
            if (index !== -1) {
              map.splice(index, 1);
            }
          }
        );
      },
      /**
       * Handle a type, but using a list of extensions.
       * @param type - Type of extension to handle.
       * @param list - The list of extensions.
       * @param defaultPriority - The default priority to use if none is specified.
       * @returns this for chaining.
       * @ignore
       */
      handleByList(type, list, defaultPriority = -1) {
        return this.handle(
          type,
          (extension) => {
            if (list.includes(extension.ref)) {
              return;
            }
            list.push(extension.ref);
            list.sort((a, b) => normalizeExtensionPriority(b, defaultPriority) - normalizeExtensionPriority(a, defaultPriority));
          },
          (extension) => {
            const index = list.indexOf(extension.ref);
            if (index !== -1) {
              list.splice(index, 1);
            }
          }
        );
      },
      /**
       * Mixin the source object(s) properties into the target class's prototype.
       * Copies all property descriptors from source objects to the target's prototype.
       * @param Target - The target class to mix properties into
       * @param sources - One or more source objects containing properties to mix in
       * @example
       * ```ts
       * // Create a mixin with shared properties
       * const moveable = {
       *     x: 0,
       *     y: 0,
       *     move(x: number, y: number) {
       *         this.x += x;
       *         this.y += y;
       *     }
       * };
       *
       * // Create a mixin with computed properties
       * const scalable = {
       *     scale: 1,
       *     get scaled() {
       *         return this.scale > 1;
       *     }
       * };
       *
       * // Apply mixins to a class
       * extensions.mixin(Sprite, moveable, scalable);
       *
       * // Use mixed-in properties
       * const sprite = new Sprite();
       * sprite.move(10, 20);
       * console.log(sprite.x, sprite.y); // 10, 20
       * ```
       * @remarks
       * - Copies all properties including getters/setters
       * - Does not modify source objects
       * - Preserves property descriptors
       * @see {@link Object.defineProperties} For details on property descriptors
       * @see {@link Object.getOwnPropertyDescriptors} For details on property copying
       */
      mixin(Target, ...sources) {
        for (const source of sources) {
          Object.defineProperties(Target.prototype, Object.getOwnPropertyDescriptors(source));
        }
      }
    };

    "use strict";
    class ResizePlugin {
      /**
       * Initialize the plugin with scope of application instance
       * @private
       * @param {object} [options] - See application options
       */
      static init(options) {
        Object.defineProperty(
          this,
          "resizeTo",
          {
            configurable: true,
            set(dom) {
              globalThis.removeEventListener("resize", this.queueResize);
              this._resizeTo = dom;
              if (dom) {
                globalThis.addEventListener("resize", this.queueResize);
                this.resize();
              }
            },
            get() {
              return this._resizeTo;
            }
          }
        );
        this.queueResize = () => {
          if (!this._resizeTo) {
            return;
          }
          this._cancelResize();
          this._resizeId = requestAnimationFrame(() => this.resize());
        };
        this._cancelResize = () => {
          if (this._resizeId) {
            cancelAnimationFrame(this._resizeId);
            this._resizeId = null;
          }
        };
        this.resize = () => {
          if (!this._resizeTo) {
            return;
          }
          this._cancelResize();
          let width;
          let height;
          if (this._resizeTo === globalThis.window) {
            width = globalThis.innerWidth;
            height = globalThis.innerHeight;
          } else {
            const { clientWidth, clientHeight } = this._resizeTo;
            width = clientWidth;
            height = clientHeight;
          }
          this.renderer.resize(width, height);
          this.render();
        };
        this._resizeId = null;
        this._resizeTo = null;
        this.resizeTo = options.resizeTo || null;
      }
      /**
       * Clean up the ticker, scoped to application
       * @private
       */
      static destroy() {
        globalThis.removeEventListener("resize", this.queueResize);
        this._cancelResize();
        this._cancelResize = null;
        this.queueResize = null;
        this.resizeTo = null;
        this.resize = null;
      }
    }
    /** @ignore */
    ResizePlugin.extension = ExtensionType.Application;

    "use strict";
    var UPDATE_PRIORITY = /* @__PURE__ */ ((UPDATE_PRIORITY2) => {
      UPDATE_PRIORITY2[UPDATE_PRIORITY2["INTERACTION"] = 50] = "INTERACTION";
      UPDATE_PRIORITY2[UPDATE_PRIORITY2["HIGH"] = 25] = "HIGH";
      UPDATE_PRIORITY2[UPDATE_PRIORITY2["NORMAL"] = 0] = "NORMAL";
      UPDATE_PRIORITY2[UPDATE_PRIORITY2["LOW"] = -25] = "LOW";
      UPDATE_PRIORITY2[UPDATE_PRIORITY2["UTILITY"] = -50] = "UTILITY";
      return UPDATE_PRIORITY2;
    })(UPDATE_PRIORITY || {});

    "use strict";
    class TickerListener {
      /**
       * Constructor
       * @private
       * @param fn - The listener function to be added for one update
       * @param context - The listener context
       * @param priority - The priority for emitting
       * @param once - If the handler should fire once
       */
      constructor(fn, context = null, priority = 0, once = false) {
        /** The next item in chain. */
        this.next = null;
        /** The previous item in chain. */
        this.previous = null;
        /** `true` if this listener has been destroyed already. */
        this._destroyed = false;
        this._fn = fn;
        this._context = context;
        this.priority = priority;
        this._once = once;
      }
      /**
       * Simple compare function to figure out if a function and context match.
       * @param fn - The listener function to be added for one update
       * @param context - The listener context
       * @returns `true` if the listener match the arguments
       */
      match(fn, context = null) {
        return this._fn === fn && this._context === context;
      }
      /**
       * Emit by calling the current function.
       * @param ticker - The ticker emitting.
       * @returns Next ticker
       */
      emit(ticker) {
        if (this._fn) {
          if (this._context) {
            this._fn.call(this._context, ticker);
          } else {
            this._fn(ticker);
          }
        }
        const redirect = this.next;
        if (this._once) {
          this.destroy(true);
        }
        if (this._destroyed) {
          this.next = null;
        }
        return redirect;
      }
      /**
       * Connect to the list.
       * @param previous - Input node, previous listener
       */
      connect(previous) {
        this.previous = previous;
        if (previous.next) {
          previous.next.previous = this;
        }
        this.next = previous.next;
        previous.next = this;
      }
      /**
       * Destroy and don't use after this.
       * @param hard - `true` to remove the `next` reference, this
       *        is considered a hard destroy. Soft destroy maintains the next reference.
       * @returns The listener to redirect while emitting or removing.
       */
      destroy(hard = false) {
        this._destroyed = true;
        this._fn = null;
        this._context = null;
        if (this.previous) {
          this.previous.next = this.next;
        }
        if (this.next) {
          this.next.previous = this.previous;
        }
        const redirect = this.next;
        this.next = hard ? null : redirect;
        this.previous = null;
        return redirect;
      }
    }

    "use strict";
    const _Ticker = class _Ticker {
      constructor() {
        /**
         * Whether or not this ticker should invoke the method {@link Ticker#start|start}
         * automatically when a listener is added.
         * @example
         * ```ts
         * // Default behavior (manual start)
         * const ticker = new Ticker();
         * ticker.autoStart = false;
         * ticker.add(() => {
         *     // Won't run until ticker.start() is called
         * });
         *
         * // Auto-start behavior
         * const autoTicker = new Ticker();
         * autoTicker.autoStart = true;
         * autoTicker.add(() => {
         *     // Runs immediately when added
         * });
         * ```
         * @default false
         * @see {@link Ticker#start} For manually starting the ticker
         * @see {@link Ticker#stop} For manually stopping the ticker
         */
        this.autoStart = false;
        /**
         * Scalar representing the delta time factor.
         * This is a dimensionless value representing the fraction of a frame at the target framerate.
         * At 60 FPS, this value is typically around 1.0.
         *
         * This is NOT in milliseconds - it's a scalar multiplier for frame-independent animations.
         * For actual milliseconds, use {@link Ticker#deltaMS}.
         * @example
         * ```ts
         * // Frame-independent animation using deltaTime scalar
         * ticker.add((ticker) => {
         *     // Rotate sprite by 0.1 radians per frame, scaled by deltaTime
         *     sprite.rotation += 0.1 * ticker.deltaTime;
         * });
         * ```
         */
        this.deltaTime = 1;
        /**
         * The last time update was invoked, in milliseconds since epoch.
         * Similar to performance.now() timestamp format.
         *
         * Used internally for calculating time deltas between frames.
         * @example
         * ```ts
         * ticker.add((ticker) => {
         *     const currentTime = performance.now();
         *     const timeSinceLastFrame = currentTime - ticker.lastTime;
         *     console.log(`Time since last frame: ${timeSinceLastFrame}ms`);
         * });
         * ```
         */
        this.lastTime = -1;
        /**
         * Factor of current {@link Ticker#deltaTime|deltaTime}.
         * Used to scale time for slow motion or fast-forward effects.
         * @example
         * ```ts
         * // Basic speed adjustment
         * ticker.speed = 0.5; // Half speed (slow motion)
         * ticker.speed = 2.0; // Double speed (fast forward)
         *
         * // Temporary speed changes
         * function slowMotion() {
         *     const normalSpeed = ticker.speed;
         *     ticker.speed = 0.2;
         *     setTimeout(() => {
         *         ticker.speed = normalSpeed;
         *     }, 1000);
         * }
         * ```
         */
        this.speed = 1;
        /**
         * Whether or not this ticker has been started.
         *
         * `true` if {@link Ticker#start|start} has been called.
         * `false` if {@link Ticker#stop|Stop} has been called.
         *
         * While `false`, this value may change to `true` in the
         * event of {@link Ticker#autoStart|autoStart} being `true`
         * and a listener is added.
         * @example
         * ```ts
         * // Check ticker state
         * const ticker = new Ticker();
         * console.log(ticker.started); // false
         *
         * // Start and verify
         * ticker.start();
         * console.log(ticker.started); // true
         * ```
         */
        this.started = false;
        /** Internal current frame request ID */
        this._requestId = null;
        /**
         * Internal value managed by minFPS property setter and getter.
         * This is the maximum allowed milliseconds between updates.
         */
        this._maxElapsedMS = 100;
        /**
         * Internal value managed by minFPS property setter and getter.
         * This is the minimum allowed milliseconds between updates.
         */
        this._minElapsedMS = 0;
        /** If enabled, deleting is disabled.*/
        this._protected = false;
        /** The last time keyframe was executed. Maintains a relatively fixed interval with the previous value. */
        this._lastFrame = -1;
        this._head = new TickerListener(null, null, Infinity);
        this.deltaMS = 1 / _Ticker.targetFPMS;
        this.elapsedMS = 1 / _Ticker.targetFPMS;
        this._tick = (time) => {
          this._requestId = null;
          if (this.started) {
            this.update(time);
            if (this.started && this._requestId === null && this._head.next) {
              this._requestId = requestAnimationFrame(this._tick);
            }
          }
        };
      }
      /**
       * Conditionally requests a new animation frame.
       * If a frame has not already been requested, and if the internal
       * emitter has listeners, a new frame is requested.
       */
      _requestIfNeeded() {
        if (this._requestId === null && this._head.next) {
          this.lastTime = performance.now();
          this._lastFrame = this.lastTime;
          this._requestId = requestAnimationFrame(this._tick);
        }
      }
      /** Conditionally cancels a pending animation frame. */
      _cancelIfNeeded() {
        if (this._requestId !== null) {
          cancelAnimationFrame(this._requestId);
          this._requestId = null;
        }
      }
      /**
       * Conditionally requests a new animation frame.
       * If the ticker has been started it checks if a frame has not already
       * been requested, and if the internal emitter has listeners. If these
       * conditions are met, a new frame is requested. If the ticker has not
       * been started, but autoStart is `true`, then the ticker starts now,
       * and continues with the previous conditions to request a new frame.
       */
      _startIfPossible() {
        if (this.started) {
          this._requestIfNeeded();
        } else if (this.autoStart) {
          this.start();
        }
      }
      /**
       * Register a handler for tick events.
       * @param fn - The listener function to add. Receives the Ticker instance as parameter
       * @param context - The context for the listener
       * @param priority - The priority of the listener
       * @example
       * ```ts
       * // Access time properties through the ticker parameter
       * ticker.add((ticker) => {
       *     // Use deltaTime (dimensionless scalar) for frame-independent animations
       *     sprite.rotation += 0.1 * ticker.deltaTime;
       *
       *     // Use deltaMS (milliseconds) for time-based calculations
       *     const progress = ticker.deltaMS / animationDuration;
       *
       *     // Use elapsedMS for raw timing measurements
       *     console.log(`Raw frame time: ${ticker.elapsedMS}ms`);
       * });
       * ```
       */
      add(fn, context, priority = UPDATE_PRIORITY.NORMAL) {
        return this._addListener(new TickerListener(fn, context, priority));
      }
      /**
       * Add a handler for the tick event which is only executed once on the next frame.
       * @example
       * ```ts
       * // Basic one-time update
       * ticker.addOnce(() => {
       *     console.log('Runs next frame only');
       * });
       *
       * // With specific context
       * const game = {
       *     init(ticker) {
       *         this.loadResources();
       *         console.log('Game initialized');
       *     }
       * };
       * ticker.addOnce(game.init, game);
       *
       * // With priority
       * ticker.addOnce(
       *     () => {
       *         // High priority one-time setup
       *         physics.init();
       *     },
       *     undefined,
       *     UPDATE_PRIORITY.HIGH
       * );
       * ```
       * @param fn - The listener function to be added for one update
       * @param context - The listener context
       * @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)
       * @returns This instance of a ticker
       * @see {@link Ticker#add} For continuous updates
       * @see {@link Ticker#remove} For removing handlers
       */
      addOnce(fn, context, priority = UPDATE_PRIORITY.NORMAL) {
        return this._addListener(new TickerListener(fn, context, priority, true));
      }
      /**
       * Internally adds the event handler so that it can be sorted by priority.
       * Priority allows certain handler (user, AnimatedSprite, Interaction) to be run
       * before the rendering.
       * @private
       * @param listener - Current listener being added.
       * @returns This instance of a ticker
       */
      _addListener(listener) {
        let current = this._head.next;
        let previous = this._head;
        if (!current) {
          listener.connect(previous);
        } else {
          while (current) {
            if (listener.priority > current.priority) {
              listener.connect(previous);
              break;
            }
            previous = current;
            current = current.next;
          }
          if (!listener.previous) {
            listener.connect(previous);
          }
        }
        this._startIfPossible();
        return this;
      }
      /**
       * Removes any handlers matching the function and context parameters.
       * If no handlers are left after removing, then it cancels the animation frame.
       * @example
       * ```ts
       * // Basic removal
       * const onTick = () => {
       *     sprite.rotation += 0.1;
       * };
       * ticker.add(onTick);
       * ticker.remove(onTick);
       *
       * // Remove with context
       * const game = {
       *     update(ticker) {
       *         this.physics.update(ticker.deltaTime);
       *     }
       * };
       * ticker.add(game.update, game);
       * ticker.remove(game.update, game);
       *
       * // Remove all matching handlers
       * // (if same function was added multiple times)
       * ticker.add(onTick);
       * ticker.add(onTick);
       * ticker.remove(onTick); // Removes all instances
       * ```
       * @param fn - The listener function to be removed
       * @param context - The listener context to be removed
       * @returns This instance of a ticker
       * @see {@link Ticker#add} For adding handlers
       * @see {@link Ticker#addOnce} For one-time handlers
       */
      remove(fn, context) {
        let listener = this._head.next;
        while (listener) {
          if (listener.match(fn, context)) {
            listener = listener.destroy();
          } else {
            listener = listener.next;
          }
        }
        if (!this._head.next) {
          this._cancelIfNeeded();
        }
        return this;
      }
      /**
       * The number of listeners on this ticker, calculated by walking through linked list.
       * @example
       * ```ts
       * // Check number of active listeners
       * const ticker = new Ticker();
       * console.log(ticker.count); // 0
       *
       * // Add some listeners
       * ticker.add(() => {});
       * ticker.add(() => {});
       * console.log(ticker.count); // 2
       *
       * // Check after cleanup
       * ticker.destroy();
       * console.log(ticker.count); // 0
       * ```
       * @readonly
       * @see {@link Ticker#add} For adding listeners
       * @see {@link Ticker#remove} For removing listeners
       */
      get count() {
        if (!this._head) {
          return 0;
        }
        let count = 0;
        let current = this._head;
        while (current = current.next) {
          count++;
        }
        return count;
      }
      /**
       * Starts the ticker. If the ticker has listeners a new animation frame is requested at this point.
       * @example
       * ```ts
       * // Basic manual start
       * const ticker = new Ticker();
       * ticker.add(() => {
       *     // Animation code here
       * });
       * ticker.start();
       * ```
       * @see {@link Ticker#stop} For stopping the ticker
       * @see {@link Ticker#autoStart} For automatic starting
       * @see {@link Ticker#started} For checking ticker state
       */
      start() {
        if (!this.started) {
          this.started = true;
          this._requestIfNeeded();
        }
      }
      /**
       * Stops the ticker. If the ticker has requested an animation frame it is canceled at this point.
       * @example
       * ```ts
       * // Basic stop
       * const ticker = new Ticker();
       * ticker.stop();
       * ```
       * @see {@link Ticker#start} For starting the ticker
       * @see {@link Ticker#started} For checking ticker state
       * @see {@link Ticker#destroy} For cleaning up the ticker
       */
      stop() {
        if (this.started) {
          this.started = false;
          this._cancelIfNeeded();
        }
      }
      /**
       * Destroy the ticker and don't use after this. Calling this method removes all references to internal events.
       * @example
       * ```ts
       * // Clean up with active listeners
       * const ticker = new Ticker();
       * ticker.add(() => {});
       * ticker.destroy(); // Removes all listeners
       * ```
       * @see {@link Ticker#stop} For stopping without destroying
       * @see {@link Ticker#remove} For removing specific listeners
       */
      destroy() {
        if (!this._protected) {
          this.stop();
          let listener = this._head.next;
          while (listener) {
            listener = listener.destroy(true);
          }
          this._head.destroy();
          this._head = null;
        }
      }
      /**
       * Triggers an update.
       *
       * An update entails setting the
       * current {@link Ticker#elapsedMS|elapsedMS},
       * the current {@link Ticker#deltaTime|deltaTime},
       * invoking all listeners with current deltaTime,
       * and then finally setting {@link Ticker#lastTime|lastTime}
       * with the value of currentTime that was provided.
       *
       * This method will be called automatically by animation
       * frame callbacks if the ticker instance has been started
       * and listeners are added.
       * @example
       * ```ts
       * // Basic manual update
       * const ticker = new Ticker();
       * ticker.update(performance.now());
       * ```
       * @param currentTime - The current time of execution (defaults to performance.now())
       * @see {@link Ticker#deltaTime} For frame delta value
       * @see {@link Ticker#elapsedMS} For raw elapsed time
       */
      update(currentTime = performance.now()) {
        let elapsedMS;
        if (currentTime > this.lastTime) {
          elapsedMS = this.elapsedMS = currentTime - this.lastTime;
          if (elapsedMS > this._maxElapsedMS) {
            elapsedMS = this._maxElapsedMS;
          }
          elapsedMS *= this.speed;
          if (this._minElapsedMS) {
            const delta = currentTime - this._lastFrame | 0;
            if (delta < this._minElapsedMS) {
              return;
            }
            this._lastFrame = currentTime - delta % this._minElapsedMS;
          }
          this.deltaMS = elapsedMS;
          this.deltaTime = this.deltaMS * _Ticker.targetFPMS;
          const head = this._head;
          let listener = head.next;
          while (listener) {
            listener = listener.emit(this);
          }
          if (!head.next) {
            this._cancelIfNeeded();
          }
        } else {
          this.deltaTime = this.deltaMS = this.elapsedMS = 0;
        }
        this.lastTime = currentTime;
      }
      /**
       * The frames per second at which this ticker is running.
       * The default is approximately 60 in most modern browsers.
       * > [!NOTE] This does not factor in the value of
       * > {@link Ticker#speed|speed}, which is specific
       * > to scaling {@link Ticker#deltaTime|deltaTime}.
       * @example
       * ```ts
       * // Basic FPS monitoring
       * ticker.add(() => {
       *     console.log(`Current FPS: ${Math.round(ticker.FPS)}`);
       * });
       * ```
       * @readonly
       */
      get FPS() {
        return 1e3 / this.elapsedMS;
      }
      /**
       * Manages the maximum amount of milliseconds allowed to
       * elapse between invoking {@link Ticker#update|update}.
       *
       * This value is used to cap {@link Ticker#deltaTime|deltaTime},
       * but does not effect the measured value of {@link Ticker#FPS|FPS}.
       *
       * When setting this property it is clamped to a value between
       * `0` and `Ticker.targetFPMS * 1000`.
       * @example
       * ```ts
       * // Set minimum acceptable frame rate
       * const ticker = new Ticker();
       * ticker.minFPS = 30; // Never go below 30 FPS
       *
       * // Use with maxFPS for frame rate clamping
       * ticker.minFPS = 30;
       * ticker.maxFPS = 60;
       *
       * // Monitor delta capping
       * ticker.add(() => {
       *     // Delta time will be capped based on minFPS
       *     console.log(`Delta time: ${ticker.deltaTime}`);
       * });
       * ```
       * @default 10
       */
      get minFPS() {
        return 1e3 / this._maxElapsedMS;
      }
      set minFPS(fps) {
        const minFPS = Math.min(this.maxFPS, fps);
        const minFPMS = Math.min(Math.max(0, minFPS) / 1e3, _Ticker.targetFPMS);
        this._maxElapsedMS = 1 / minFPMS;
      }
      /**
       * Manages the minimum amount of milliseconds required to
       * elapse between invoking {@link Ticker#update|update}.
       *
       * This will effect the measured value of {@link Ticker#FPS|FPS}.
       *
       * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.
       * Otherwise it will be at least `minFPS`
       * @example
       * ```ts
       * // Set minimum acceptable frame rate
       * const ticker = new Ticker();
       * ticker.maxFPS = 60; // Never go above 60 FPS
       *
       * // Use with maxFPS for frame rate clamping
       * ticker.minFPS = 30;
       * ticker.maxFPS = 60;
       *
       * // Monitor delta capping
       * ticker.add(() => {
       *     // Delta time will be capped based on maxFPS
       *     console.log(`Delta time: ${ticker.deltaTime}`);
       * });
       * ```
       * @default 0
       */
      get maxFPS() {
        if (this._minElapsedMS) {
          return Math.round(1e3 / this._minElapsedMS);
        }
        return 0;
      }
      set maxFPS(fps) {
        if (fps === 0) {
          this._minElapsedMS = 0;
        } else {
          const maxFPS = Math.max(this.minFPS, fps);
          this._minElapsedMS = 1 / (maxFPS / 1e3);
        }
      }
      /**
       * The shared ticker instance used by {@link AnimatedSprite} and by
       * {@link VideoSource} to update animation frames / video textures.
       *
       * It may also be used by {@link Application} if created with the `sharedTicker` option property set to true.
       *
       * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance.
       * Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker.
       * @example
       * import { Ticker } from 'pixi.js';
       *
       * const ticker = Ticker.shared;
       * // Set this to prevent starting this ticker when listeners are added.
       * // By default this is true only for the Ticker.shared instance.
       * ticker.autoStart = false;
       *
       * // FYI, call this to ensure the ticker is stopped. It should be stopped
       * // if you have not attempted to render anything yet.
       * ticker.stop();
       *
       * // Call this when you are ready for a running shared ticker.
       * ticker.start();
       * @example
       * import { autoDetectRenderer, Container } from 'pixi.js';
       *
       * // You may use the shared ticker to render...
       * const renderer = autoDetectRenderer();
       * const stage = new Container();
       * document.body.appendChild(renderer.view);
       * ticker.add((time) => renderer.render(stage));
       *
       * // Or you can just update it manually.
       * ticker.autoStart = false;
       * ticker.stop();
       * const animate = (time) => {
       *     ticker.update(time);
       *     renderer.render(stage);
       *     requestAnimationFrame(animate);
       * };
       * animate(performance.now());
       * @type {Ticker}
       * @readonly
       */
      static get shared() {
        if (!_Ticker._shared) {
          const shared = _Ticker._shared = new _Ticker();
          shared.autoStart = true;
          shared._protected = true;
        }
        return _Ticker._shared;
      }
      /**
       * The system ticker instance used by {@link PrepareBase} for core timing
       * functionality that shouldn't usually need to be paused, unlike the `shared`
       * ticker which drives visual animations and rendering which may want to be paused.
       *
       * The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance.
       * @type {Ticker}
       * @readonly
       * @advanced
       */
      static get system() {
        if (!_Ticker._system) {
          const system = _Ticker._system = new _Ticker();
          system.autoStart = true;
          system._protected = true;
        }
        return _Ticker._system;
      }
    };
    /**
     * Target frame rate in frames per millisecond.
     * Used for converting deltaTime to a scalar time delta.
     * @example
     * ```ts
     * // Default is 0.06 (60 FPS)
     * console.log(Ticker.targetFPMS); // 0.06
     *
     * // Calculate target frame duration
     * const frameDuration = 1 / Ticker.targetFPMS; // ≈ 16.67ms
     *
     * // Use in custom timing calculations
     * const deltaTime = elapsedMS * Ticker.targetFPMS;
     * ```
     * @remarks
     * - Default is 0.06 (equivalent to 60 FPS)
     * - Used in deltaTime calculations
     * - Affects all ticker instances
     * @default 0.06
     * @see {@link Ticker#deltaTime} For time scaling
     * @see {@link Ticker#FPS} For actual frame rate
     */
    _Ticker.targetFPMS = 0.06;
    let Ticker = _Ticker;

    "use strict";
    class TickerPlugin {
      /**
       * Initialize the plugin with scope of application instance
       * @private
       * @param {object} [options] - See application options
       */
      static init(options) {
        options = Object.assign({
          autoStart: true,
          sharedTicker: false
        }, options);
        Object.defineProperty(
          this,
          "ticker",
          {
            configurable: true,
            set(ticker) {
              if (this._ticker) {
                this._ticker.remove(this.render, this);
              }
              this._ticker = ticker;
              if (ticker) {
                ticker.add(this.render, this, UPDATE_PRIORITY.LOW);
              }
            },
            get() {
              return this._ticker;
            }
          }
        );
        this.stop = () => {
          this._ticker.stop();
        };
        this.start = () => {
          this._ticker.start();
        };
        this._ticker = null;
        this.ticker = options.sharedTicker ? Ticker.shared : new Ticker();
        if (options.autoStart) {
          this.start();
        }
      }
      /**
       * Clean up the ticker, scoped to application.
       * @private
       */
      static destroy() {
        if (this._ticker) {
          const oldTicker = this._ticker;
          this.ticker = null;
          oldTicker.destroy();
        }
      }
    }
    /** @ignore */
    TickerPlugin.extension = ExtensionType.Application;

    "use strict";
    extensions.add(ResizePlugin);
    extensions.add(TickerPlugin);

    "use strict";
    var LoaderParserPriority = /* @__PURE__ */ ((LoaderParserPriority2) => {
      LoaderParserPriority2[LoaderParserPriority2["Low"] = 0] = "Low";
      LoaderParserPriority2[LoaderParserPriority2["Normal"] = 1] = "Normal";
      LoaderParserPriority2[LoaderParserPriority2["High"] = 2] = "High";
      return LoaderParserPriority2;
    })(LoaderParserPriority || {});

    "use strict";
    let warnCount = 0;
    const maxWarnings = 500;
    function warn(...args) {
      if (warnCount === maxWarnings)
        return;
      warnCount++;
      if (warnCount === maxWarnings) {
        console.warn("PixiJS Warning: too many warnings, no more warnings will be reported to the console by PixiJS.");
      } else {
        console.warn("PixiJS Warning: ", ...args);
      }
    }

    "use strict";
    function assertPath(path2) {
      if (typeof path2 !== "string") {
        throw new TypeError(`Path must be a string. Received ${JSON.stringify(path2)}`);
      }
    }
    function removeUrlParams(url) {
      const re = url.split("?")[0];
      return re.split("#")[0];
    }
    function escapeRegExp(string) {
      return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    }
    function replaceAll(str, find, replace) {
      return str.replace(new RegExp(escapeRegExp(find), "g"), replace);
    }
    function normalizeStringPosix(path2, allowAboveRoot) {
      let res = "";
      let lastSegmentLength = 0;
      let lastSlash = -1;
      let dots = 0;
      let code = -1;
      for (let i = 0; i <= path2.length; ++i) {
        if (i < path2.length) {
          code = path2.charCodeAt(i);
        } else if (code === 47) {
          break;
        } else {
          code = 47;
        }
        if (code === 47) {
          if (lastSlash === i - 1 || dots === 1) {
          } else if (lastSlash !== i - 1 && dots === 2) {
            if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
              if (res.length > 2) {
                const lastSlashIndex = res.lastIndexOf("/");
                if (lastSlashIndex !== res.length - 1) {
                  if (lastSlashIndex === -1) {
                    res = "";
                    lastSegmentLength = 0;
                  } else {
                    res = res.slice(0, lastSlashIndex);
                    lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
                  }
                  lastSlash = i;
                  dots = 0;
                  continue;
                }
              } else if (res.length === 2 || res.length === 1) {
                res = "";
                lastSegmentLength = 0;
                lastSlash = i;
                dots = 0;
                continue;
              }
            }
            if (allowAboveRoot) {
              if (res.length > 0) {
                res += "/..";
              } else {
                res = "..";
              }
              lastSegmentLength = 2;
            }
          } else {
            if (res.length > 0) {
              res += `/${path2.slice(lastSlash + 1, i)}`;
            } else {
              res = path2.slice(lastSlash + 1, i);
            }
            lastSegmentLength = i - lastSlash - 1;
          }
          lastSlash = i;
          dots = 0;
        } else if (code === 46 && dots !== -1) {
          ++dots;
        } else {
          dots = -1;
        }
      }
      return res;
    }
    const path = {
      /**
       * Converts a path to posix format.
       * @param path - The path to convert to posix
       * @example
       * ```ts
       * // Convert a Windows path to POSIX format
       * path.toPosix('C:\\Users\\User\\Documents\\file.txt');
       * // -> 'C:/Users/User/Documents/file.txt'
       * ```
       */
      toPosix(path2) {
        return replaceAll(path2, "\\", "/");
      },
      /**
       * Checks if the path is a URL e.g. http://, https://
       * @param path - The path to check
       * @example
       * ```ts
       * // Check if a path is a URL
       * path.isUrl('http://www.example.com');
       * // -> true
       * path.isUrl('C:/Users/User/Documents/file.txt');
       * // -> false
       * ```
       */
      isUrl(path2) {
        return /^https?:/.test(this.toPosix(path2));
      },
      /**
       * Checks if the path is a data URL
       * @param path - The path to check
       * @example
       * ```ts
       * // Check if a path is a data URL
       * path.isDataUrl('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...');
       * // -> true
       * ```
       */
      isDataUrl(path2) {
        return /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i.test(path2);
      },
      /**
       * Checks if the path is a blob URL
       * @param path - The path to check
       * @example
       * ```ts
       * // Check if a path is a blob URL
       * path.isBlobUrl('blob:http://www.example.com/12345678-1234-1234-1234-123456789012');
       * // -> true
       * ```
       */
      isBlobUrl(path2) {
        return path2.startsWith("blob:");
      },
      /**
       * Checks if the path has a protocol e.g. http://, https://, file:///, data:, blob:, C:/
       * This will return true for windows file paths
       * @param path - The path to check
       * @example
       * ```ts
       * // Check if a path has a protocol
       * path.hasProtocol('http://www.example.com');
       * // -> true
       * path.hasProtocol('C:/Users/User/Documents/file.txt');
       * // -> true
       * ```
       */
      hasProtocol(path2) {
        return /^[^/:]+:/.test(this.toPosix(path2));
      },
      /**
       * Returns the protocol of the path e.g. http://, https://, file:///, data:, blob:, C:/
       * @param path - The path to get the protocol from
       * @example
       * ```ts
       * // Get the protocol from a URL
       * path.getProtocol('http://www.example.com/path/to/resource');
       * // -> 'http://'
       * // Get the protocol from a file path
       * path.getProtocol('C:/Users/User/Documents/file.txt');
       * // -> 'C:/'
       * ```
       */
      getProtocol(path2) {
        assertPath(path2);
        path2 = this.toPosix(path2);
        const matchFile = /^file:\/\/\//.exec(path2);
        if (matchFile) {
          return matchFile[0];
        }
        const matchProtocol = /^[^/:]+:\/{0,2}/.exec(path2);
        if (matchProtocol) {
          return matchProtocol[0];
        }
        return "";
      },
      /**
       * Converts URL to an absolute path.
       * When loading from a Web Worker, we must use absolute paths.
       * If the URL is already absolute we return it as is
       * If it's not, we convert it
       * @param url - The URL to test
       * @param customBaseUrl - The base URL to use
       * @param customRootUrl - The root URL to use
       * @example
       * ```ts
       * // Convert a relative URL to an absolute path
       * path.toAbsolute('images/texture.png', 'http://example.com/assets/');
       * // -> 'http://example.com/assets/images/texture.png'
       * ```
       */
      toAbsolute(url, customBaseUrl, customRootUrl) {
        assertPath(url);
        if (this.isDataUrl(url) || this.isBlobUrl(url))
          return url;
        const baseUrl = removeUrlParams(this.toPosix(customBaseUrl != null ? customBaseUrl : DOMAdapter.get().getBaseUrl()));
        const rootUrl = removeUrlParams(this.toPosix(customRootUrl != null ? customRootUrl : this.rootname(baseUrl)));
        url = this.toPosix(url);
        if (url.startsWith("/")) {
          return path.join(rootUrl, url.slice(1));
        }
        const absolutePath = this.isAbsolute(url) ? url : this.join(baseUrl, url);
        return absolutePath;
      },
      /**
       * Normalizes the given path, resolving '..' and '.' segments
       * @param path - The path to normalize
       * @example
       * ```ts
       * // Normalize a path with relative segments
       * path.normalize('http://www.example.com/foo/bar/../baz');
       * // -> 'http://www.example.com/foo/baz'
       * // Normalize a file path with relative segments
       * path.normalize('C:\\Users\\User\\Documents\\..\\file.txt');
       * // -> 'C:/Users/User/file.txt'
       * ```
       */
      normalize(path2) {
        assertPath(path2);
        if (path2.length === 0)
          return ".";
        if (this.isDataUrl(path2) || this.isBlobUrl(path2))
          return path2;
        path2 = this.toPosix(path2);
        let protocol = "";
        const isAbsolute = path2.startsWith("/");
        if (this.hasProtocol(path2)) {
          protocol = this.rootname(path2);
          path2 = path2.slice(protocol.length);
        }
        const trailingSeparator = path2.endsWith("/");
        path2 = normalizeStringPosix(path2, false);
        if (path2.length > 0 && trailingSeparator)
          path2 += "/";
        if (isAbsolute)
          return `/${path2}`;
        return protocol + path2;
      },
      /**
       * Determines if path is an absolute path.
       * Absolute paths can be urls, data urls, or paths on disk
       * @param path - The path to test
       * @example
       * ```ts
       * // Check if a path is absolute
       * path.isAbsolute('http://www.example.com/foo/bar');
       * // -> true
       * path.isAbsolute('C:/Users/User/Documents/file.txt');
       * // -> true
       * ```
       */
      isAbsolute(path2) {
        assertPath(path2);
        path2 = this.toPosix(path2);
        if (this.hasProtocol(path2))
          return true;
        return path2.startsWith("/");
      },
      /**
       * Joins all given path segments together using the platform-specific separator as a delimiter,
       * then normalizes the resulting path
       * @param segments - The segments of the path to join
       * @example
       * ```ts
       * // Join multiple path segments
       * path.join('assets', 'images', 'sprite.png');
       * // -> 'assets/images/sprite.png'
       * // Join with relative segments
       * path.join('assets', 'images', '../textures', 'sprite.png');
       * // -> 'assets/textures/sprite.png'
       * ```
       */
      join(...segments) {
        var _a;
        if (segments.length === 0) {
          return ".";
        }
        let joined;
        for (let i = 0; i < segments.length; ++i) {
          const arg = segments[i];
          assertPath(arg);
          if (arg.length > 0) {
            if (joined === void 0)
              joined = arg;
            else {
              const prevArg = (_a = segments[i - 1]) != null ? _a : "";
              if (this.joinExtensions.includes(this.extname(prevArg).toLowerCase())) {
                joined += `/../${arg}`;
              } else {
                joined += `/${arg}`;
              }
            }
          }
        }
        if (joined === void 0) {
          return ".";
        }
        return this.normalize(joined);
      },
      /**
       * Returns the directory name of a path
       * @param path - The path to parse
       * @example
       * ```ts
       * // Get the directory name of a path
       * path.dirname('http://www.example.com/foo/bar/baz.png');
       * // -> 'http://www.example.com/foo/bar'
       * // Get the directory name of a file path
       * path.dirname('C:/Users/User/Documents/file.txt');
       * // -> 'C:/Users/User/Documents'
       * ```
       */
      dirname(path2) {
        assertPath(path2);
        if (path2.length === 0)
          return ".";
        path2 = this.toPosix(path2);
        let code = path2.charCodeAt(0);
        const hasRoot = code === 47;
        let end = -1;
        let matchedSlash = true;
        const proto = this.getProtocol(path2);
        const origpath = path2;
        path2 = path2.slice(proto.length);
        for (let i = path2.length - 1; i >= 1; --i) {
          code = path2.charCodeAt(i);
          if (code === 47) {
            if (!matchedSlash) {
              end = i;
              break;
            }
          } else {
            matchedSlash = false;
          }
        }
        if (end === -1)
          return hasRoot ? "/" : this.isUrl(origpath) ? proto + path2 : proto;
        if (hasRoot && end === 1)
          return "//";
        return proto + path2.slice(0, end);
      },
      /**
       * Returns the root of the path e.g. /, C:/, file:///, http://domain.com/
       * @param path - The path to parse
       * @example
       * ```ts
       * // Get the root of a URL
       * path.rootname('http://www.example.com/foo/bar/baz.png');
       * // -> 'http://www.example.com/'
       * // Get the root of a file path
       * path.rootname('C:/Users/User/Documents/file.txt');
       * // -> 'C:/'
       * ```
       */
      rootname(path2) {
        assertPath(path2);
        path2 = this.toPosix(path2);
        let root = "";
        if (path2.startsWith("/"))
          root = "/";
        else {
          root = this.getProtocol(path2);
        }
        if (this.isUrl(path2)) {
          const index = path2.indexOf("/", root.length);
          if (index !== -1) {
            root = path2.slice(0, index);
          } else
            root = path2;
          if (!root.endsWith("/"))
            root += "/";
        }
        return root;
      },
      /**
       * Returns the last portion of a path
       * @param path - The path to test
       * @param ext - Optional extension to remove
       * @example
       * ```ts
       * // Get the basename of a URL
       * path.basename('http://www.example.com/foo/bar/baz.png');
       * // -> 'baz.png'
       * // Get the basename of a file path
       * path.basename('C:/Users/User/Documents/file.txt');
       * // -> 'file.txt'
       * ```
       */
      basename(path2, ext) {
        assertPath(path2);
        if (ext)
          assertPath(ext);
        path2 = removeUrlParams(this.toPosix(path2));
        let start = 0;
        let end = -1;
        let matchedSlash = true;
        let i;
        if (ext !== void 0 && ext.length > 0 && ext.length <= path2.length) {
          if (ext.length === path2.length && ext === path2)
            return "";
          let extIdx = ext.length - 1;
          let firstNonSlashEnd = -1;
          for (i = path2.length - 1; i >= 0; --i) {
            const code = path2.charCodeAt(i);
            if (code === 47) {
              if (!matchedSlash) {
                start = i + 1;
                break;
              }
            } else {
              if (firstNonSlashEnd === -1) {
                matchedSlash = false;
                firstNonSlashEnd = i + 1;
              }
              if (extIdx >= 0) {
                if (code === ext.charCodeAt(extIdx)) {
                  if (--extIdx === -1) {
                    end = i;
                  }
                } else {
                  extIdx = -1;
                  end = firstNonSlashEnd;
                }
              }
            }
          }
          if (start === end)
            end = firstNonSlashEnd;
          else if (end === -1)
            end = path2.length;
          return path2.slice(start, end);
        }
        for (i = path2.length - 1; i >= 0; --i) {
          if (path2.charCodeAt(i) === 47) {
            if (!matchedSlash) {
              start = i + 1;
              break;
            }
          } else if (end === -1) {
            matchedSlash = false;
            end = i + 1;
          }
        }
        if (end === -1)
          return "";
        return path2.slice(start, end);
      },
      /**
       * Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last
       * portion of the path. If there is no . in the last portion of the path, or if there are no . characters other than
       * the first character of the basename of path, an empty string is returned.
       * @param path - The path to parse
       * @example
       * ```ts
       * // Get the extension of a URL
       * path.extname('http://www.example.com/foo/bar/baz.png');
       * // -> '.png'
       * // Get the extension of a file path
       * path.extname('C:/Users/User/Documents/file.txt');
       * // -> '.txt'
       * ```
       */
      extname(path2) {
        assertPath(path2);
        path2 = removeUrlParams(this.toPosix(path2));
        let startDot = -1;
        let startPart = 0;
        let end = -1;
        let matchedSlash = true;
        let preDotState = 0;
        for (let i = path2.length - 1; i >= 0; --i) {
          const code = path2.charCodeAt(i);
          if (code === 47) {
            if (!matchedSlash) {
              startPart = i + 1;
              break;
            }
            continue;
          }
          if (end === -1) {
            matchedSlash = false;
            end = i + 1;
          }
          if (code === 46) {
            if (startDot === -1)
              startDot = i;
            else if (preDotState !== 1)
              preDotState = 1;
          } else if (startDot !== -1) {
            preDotState = -1;
          }
        }
        if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
          return "";
        }
        return path2.slice(startDot, end);
      },
      /**
       * Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties.
       * @param path - The path to parse
       * @example
       * ```ts
       * // Parse a URL
       * const parsed = path.parse('http://www.example.com/foo/bar/baz.png');
       * // -> {
       * //   root: 'http://www.example.com/',
       * //   dir: 'http://www.example.com/foo/bar',
       * //   base: 'baz.png',
       * //   ext: '.png',
       * //   name: 'baz'
       * // }
       * // Parse a file path
       * const parsedFile = path.parse('C:/Users/User/Documents/file.txt');
       * // -> {
       * //   root: 'C:/',
       * //   dir: 'C:/Users/User/Documents',
       * //   base: 'file.txt',
       * //   ext: '.txt',
       * //   name: 'file'
       * // }
       * ```
       */
      parse(path2) {
        assertPath(path2);
        const ret = { root: "", dir: "", base: "", ext: "", name: "" };
        if (path2.length === 0)
          return ret;
        path2 = removeUrlParams(this.toPosix(path2));
        let code = path2.charCodeAt(0);
        const isAbsolute = this.isAbsolute(path2);
        let start;
        const protocol = "";
        ret.root = this.rootname(path2);
        if (isAbsolute || this.hasProtocol(path2)) {
          start = 1;
        } else {
          start = 0;
        }
        let startDot = -1;
        let startPart = 0;
        let end = -1;
        let matchedSlash = true;
        let i = path2.length - 1;
        let preDotState = 0;
        for (; i >= start; --i) {
          code = path2.charCodeAt(i);
          if (code === 47) {
            if (!matchedSlash) {
              startPart = i + 1;
              break;
            }
            continue;
          }
          if (end === -1) {
            matchedSlash = false;
            end = i + 1;
          }
          if (code === 46) {
            if (startDot === -1)
              startDot = i;
            else if (preDotState !== 1)
              preDotState = 1;
          } else if (startDot !== -1) {
            preDotState = -1;
          }
        }
        if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
          if (end !== -1) {
            if (startPart === 0 && isAbsolute)
              ret.base = ret.name = path2.slice(1, end);
            else
              ret.base = ret.name = path2.slice(startPart, end);
          }
        } else {
          if (startPart === 0 && isAbsolute) {
            ret.name = path2.slice(1, startDot);
            ret.base = path2.slice(1, end);
          } else {
            ret.name = path2.slice(startPart, startDot);
            ret.base = path2.slice(startPart, end);
          }
          ret.ext = path2.slice(startDot, end);
        }
        ret.dir = this.dirname(path2);
        if (protocol)
          ret.dir = protocol + ret.dir;
        return ret;
      },
      sep: "/",
      delimiter: ":",
      joinExtensions: [".html"]
    };

    "use strict";
    const convertToList = (input, transform, forceTransform = false) => {
      if (!Array.isArray(input)) {
        input = [input];
      }
      if (!transform) {
        return input;
      }
      return input.map((item) => {
        if (typeof item === "string" || forceTransform) {
          return transform(item);
        }
        return item;
      });
    };

    "use strict";
    function processX(base, ids, depth, result, tags) {
      const id = ids[depth];
      for (let i = 0; i < id.length; i++) {
        const value = id[i];
        if (depth < ids.length - 1) {
          processX(base.replace(result[depth], value), ids, depth + 1, result, tags);
        } else {
          tags.push(base.replace(result[depth], value));
        }
      }
    }
    function createStringVariations(string) {
      const regex = /\{(.*?)\}/g;
      const result = string.match(regex);
      const tags = [];
      if (result) {
        const ids = [];
        result.forEach((vars) => {
          const split = vars.substring(1, vars.length - 1).split(",");
          ids.push(split);
        });
        processX(string, ids, 0, result, tags);
      } else {
        tags.push(string);
      }
      return tags;
    }

    "use strict";
    const isSingleItem = (item) => !Array.isArray(item);

    "use strict";
    var __defProp$1c = Object.defineProperty;
    var __defProps$t = Object.defineProperties;
    var __getOwnPropDescs$t = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$1e = Object.getOwnPropertySymbols;
    var __hasOwnProp$1e = Object.prototype.hasOwnProperty;
    var __propIsEnum$1e = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$1c = (obj, key, value) => key in obj ? __defProp$1c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$1c = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1e.call(b, prop))
          __defNormalProp$1c(a, prop, b[prop]);
      if (__getOwnPropSymbols$1e)
        for (var prop of __getOwnPropSymbols$1e(b)) {
          if (__propIsEnum$1e.call(b, prop))
            __defNormalProp$1c(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$t = (a, b) => __defProps$t(a, __getOwnPropDescs$t(b));
    class Resolver {
      constructor() {
        this._defaultBundleIdentifierOptions = {
          connector: "-",
          createBundleAssetId: (bundleId, assetId) => `${bundleId}${this._bundleIdConnector}${assetId}`,
          extractAssetIdFromBundle: (bundleId, assetBundleId) => assetBundleId.replace(`${bundleId}${this._bundleIdConnector}`, "")
        };
        /** The character that is used to connect the bundleId and the assetId when generating a bundle asset id key */
        this._bundleIdConnector = this._defaultBundleIdentifierOptions.connector;
        /**
         * A function that generates a bundle asset id key from a bundleId and an assetId
         * @param bundleId - the bundleId
         * @param assetId  - the assetId
         * @returns the bundle asset id key
         */
        this._createBundleAssetId = this._defaultBundleIdentifierOptions.createBundleAssetId;
        /**
         * A function that generates an assetId from a bundle asset id key. This is the reverse of generateBundleAssetId
         * @param bundleId - the bundleId
         * @param assetBundleId - the bundle asset id key
         * @returns the assetId
         */
        this._extractAssetIdFromBundle = this._defaultBundleIdentifierOptions.extractAssetIdFromBundle;
        this._assetMap = {};
        this._preferredOrder = [];
        this._parsers = [];
        this._resolverHash = {};
        this._bundles = {};
      }
      /**
       * Override how the resolver deals with generating bundle ids.
       * must be called before any bundles are added
       * @param bundleIdentifier - the bundle identifier options
       */
      setBundleIdentifier(bundleIdentifier) {
        var _a, _b, _c;
        this._bundleIdConnector = (_a = bundleIdentifier.connector) != null ? _a : this._bundleIdConnector;
        this._createBundleAssetId = (_b = bundleIdentifier.createBundleAssetId) != null ? _b : this._createBundleAssetId;
        this._extractAssetIdFromBundle = (_c = bundleIdentifier.extractAssetIdFromBundle) != null ? _c : this._extractAssetIdFromBundle;
        if (this._extractAssetIdFromBundle("foo", this._createBundleAssetId("foo", "bar")) !== "bar") {
          throw new Error("[Resolver] GenerateBundleAssetId are not working correctly");
        }
      }
      /**
       * Let the resolver know which assets you prefer to use when resolving assets.
       * Multiple prefer user defined rules can be added.
       * @example
       * resolver.prefer({
       *     // first look for something with the correct format, and then then correct resolution
       *     priority: ['format', 'resolution'],
       *     params:{
       *         format:'webp', // prefer webp images
       *         resolution: 2, // prefer a resolution of 2
       *     }
       * })
       * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']);
       * resolver.resolveUrl('foo') // => 'bar@2x.webp'
       * @param preferOrders - the prefer options
       */
      prefer(...preferOrders) {
        preferOrders.forEach((prefer) => {
          this._preferredOrder.push(prefer);
          if (!prefer.priority) {
            prefer.priority = Object.keys(prefer.params);
          }
        });
        this._resolverHash = {};
      }
      /**
       * Set the base path to prepend to all urls when resolving
       * @example
       * resolver.basePath = 'https://home.com/';
       * resolver.add('foo', 'bar.ong');
       * resolver.resolveUrl('foo', 'bar.png'); // => 'https://home.com/bar.png'
       * @param basePath - the base path to use
       */
      set basePath(basePath) {
        this._basePath = basePath;
      }
      get basePath() {
        return this._basePath;
      }
      /**
       * Set the root path for root-relative URLs. By default the `basePath`'s root is used. If no `basePath` is set, then the
       * default value for browsers is `window.location.origin`
       * @example
       * // Application hosted on https://home.com/some-path/index.html
       * resolver.basePath = 'https://home.com/some-path/';
       * resolver.rootPath = 'https://home.com/';
       * resolver.add('foo', '/bar.png');
       * resolver.resolveUrl('foo', '/bar.png'); // => 'https://home.com/bar.png'
       * @param rootPath - the root path to use
       */
      set rootPath(rootPath) {
        this._rootPath = rootPath;
      }
      get rootPath() {
        return this._rootPath;
      }
      /**
       * All the active URL parsers that help the parser to extract information and create
       * an asset object-based on parsing the URL itself.
       *
       * Can be added using the extensions API
       * @example
       * resolver.add('foo', [
       *     {
       *         resolution: 2,
       *         format: 'png',
       *         src: 'image@2x.png',
       *     },
       *     {
       *         resolution:1,
       *         format:'png',
       *         src: 'image.png',
       *     },
       * ]);
       *
       * // With a url parser the information such as resolution and file format could extracted from the url itself:
       * extensions.add({
       *     extension: ExtensionType.ResolveParser,
       *     test: loadTextures.test, // test if url ends in an image
       *     parse: (value: string) =>
       *     ({
       *         resolution: parseFloat(Resolver.RETINA_PREFIX.exec(value)?.[1] ?? '1'),
       *         format: value.split('.').pop(),
       *         src: value,
       *     }),
       * });
       *
       * // Now resolution and format can be extracted from the url
       * resolver.add('foo', [
       *     'image@2x.png',
       *     'image.png',
       * ]);
       */
      get parsers() {
        return this._parsers;
      }
      /** Used for testing, this resets the resolver to its initial state */
      reset() {
        this.setBundleIdentifier(this._defaultBundleIdentifierOptions);
        this._assetMap = {};
        this._preferredOrder = [];
        this._resolverHash = {};
        this._rootPath = null;
        this._basePath = null;
        this._manifest = null;
        this._bundles = {};
        this._defaultSearchParams = null;
      }
      /**
       * Sets the default URL search parameters for the URL resolver. The urls can be specified as a string or an object.
       * @param searchParams - the default url parameters to append when resolving urls
       */
      setDefaultSearchParams(searchParams) {
        if (typeof searchParams === "string") {
          this._defaultSearchParams = searchParams;
        } else {
          const queryValues = searchParams;
          this._defaultSearchParams = Object.keys(queryValues).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryValues[key])}`).join("&");
        }
      }
      /**
       * Returns the aliases for a given asset
       * @param asset - the asset to get the aliases for
       */
      getAlias(asset) {
        const { alias, src } = asset;
        const aliasesToUse = convertToList(
          alias || src,
          (value) => {
            if (typeof value === "string")
              return value;
            if (Array.isArray(value))
              return value.map((v) => {
                var _a;
                return (_a = v == null ? void 0 : v.src) != null ? _a : v;
              });
            if (value == null ? void 0 : value.src)
              return value.src;
            return value;
          },
          true
        );
        return aliasesToUse;
      }
      /**
       * Add a manifest to the asset resolver. This is a nice way to add all the asset information in one go.
       * generally a manifest would be built using a tool.
       * @param manifest - the manifest to add to the resolver
       */
      addManifest(manifest) {
        if (this._manifest) {
          warn("[Resolver] Manifest already exists, this will be overwritten");
        }
        this._manifest = manifest;
        manifest.bundles.forEach((bundle) => {
          this.addBundle(bundle.name, bundle.assets);
        });
      }
      /**
       * This adds a bundle of assets in one go so that you can resolve them as a group.
       * For example you could add a bundle for each screen in you pixi app
       * @example
       * resolver.addBundle('animals', [
       *  { alias: 'bunny', src: 'bunny.png' },
       *  { alias: 'chicken', src: 'chicken.png' },
       *  { alias: 'thumper', src: 'thumper.png' },
       * ]);
       * // or
       * resolver.addBundle('animals', {
       *     bunny: 'bunny.png',
       *     chicken: 'chicken.png',
       *     thumper: 'thumper.png',
       * });
       *
       * const resolvedAssets = await resolver.resolveBundle('animals');
       * @param bundleId - The id of the bundle to add
       * @param assets - A record of the asset or assets that will be chosen from when loading via the specified key
       */
      addBundle(bundleId, assets) {
        const assetNames = [];
        let convertedAssets = assets;
        if (!Array.isArray(assets)) {
          convertedAssets = Object.entries(assets).map(([alias, src]) => {
            if (typeof src === "string" || Array.isArray(src)) {
              return { alias, src };
            }
            return __spreadValues$1c({ alias }, src);
          });
        }
        convertedAssets.forEach((asset) => {
          const srcs = asset.src;
          const aliases = asset.alias;
          let ids;
          if (typeof aliases === "string") {
            const bundleAssetId = this._createBundleAssetId(bundleId, aliases);
            assetNames.push(bundleAssetId);
            ids = [aliases, bundleAssetId];
          } else {
            const bundleIds = aliases.map((name) => this._createBundleAssetId(bundleId, name));
            assetNames.push(...bundleIds);
            ids = [...aliases, ...bundleIds];
          }
          this.add(__spreadValues$1c(__spreadValues$1c({}, asset), {
            alias: ids,
            src: srcs
          }));
        });
        this._bundles[bundleId] = assetNames;
      }
      /**
       * Tells the resolver what keys are associated with witch asset.
       * The most important thing the resolver does
       * @example
       * // Single key, single asset:
       * resolver.add({alias: 'foo', src: 'bar.png');
       * resolver.resolveUrl('foo') // => 'bar.png'
       *
       * // Multiple keys, single asset:
       * resolver.add({alias: ['foo', 'boo'], src: 'bar.png'});
       * resolver.resolveUrl('foo') // => 'bar.png'
       * resolver.resolveUrl('boo') // => 'bar.png'
       *
       * // Multiple keys, multiple assets:
       * resolver.add({alias: ['foo', 'boo'], src: ['bar.png', 'bar.webp']});
       * resolver.resolveUrl('foo') // => 'bar.png'
       *
       * // Add custom data attached to the resolver
       * Resolver.add({
       *     alias: 'bunnyBooBooSmooth',
       *     src: 'bunny{png,webp}',
       *     data: { scaleMode:SCALE_MODES.NEAREST }, // Base texture options
       * });
       *
       * resolver.resolve('bunnyBooBooSmooth') // => { src: 'bunny.png', data: { scaleMode: SCALE_MODES.NEAREST } }
       * @param aliases - the UnresolvedAsset or array of UnresolvedAssets to add to the resolver
       */
      add(aliases) {
        const assets = [];
        if (Array.isArray(aliases)) {
          assets.push(...aliases);
        } else {
          assets.push(aliases);
        }
        let keyCheck;
        keyCheck = (key) => {
          if (this.hasKey(key)) {
            warn(`[Resolver] already has key: ${key} overwriting`);
          }
        };
        const assetArray = convertToList(assets);
        assetArray.forEach((asset) => {
          const { src } = asset;
          let {
            data,
            format,
            loadParser: userDefinedLoadParser,
            parser: userDefinedParser
          } = asset;
          const srcsToUse = convertToList(src).map((src2) => {
            if (typeof src2 === "string") {
              return createStringVariations(src2);
            }
            return Array.isArray(src2) ? src2 : [src2];
          });
          const aliasesToUse = this.getAlias(asset);
          Array.isArray(aliasesToUse) ? aliasesToUse.forEach(keyCheck) : keyCheck(aliasesToUse);
          const resolvedAssets = [];
          const parseUrl = (url) => {
            const parser = this._parsers.find((p) => p.test(url));
            return __spreadProps$t(__spreadValues$1c({}, parser == null ? void 0 : parser.parse(url)), {
              src: url
            });
          };
          srcsToUse.forEach((srcs) => {
            srcs.forEach((src2) => {
              var _a, _b, _c, _d;
              let formattedAsset = {};
              if (typeof src2 !== "object") {
                formattedAsset = parseUrl(src2);
              } else {
                data = (_a = src2.data) != null ? _a : data;
                format = (_b = src2.format) != null ? _b : format;
                if (src2.loadParser || src2.parser) {
                  userDefinedLoadParser = (_c = src2.loadParser) != null ? _c : userDefinedLoadParser;
                  userDefinedParser = (_d = src2.parser) != null ? _d : userDefinedParser;
                }
                formattedAsset = __spreadValues$1c(__spreadValues$1c({}, parseUrl(src2.src)), src2);
              }
              if (!aliasesToUse) {
                throw new Error(`[Resolver] alias is undefined for this asset: ${formattedAsset.src}`);
              }
              formattedAsset = this._buildResolvedAsset(formattedAsset, {
                aliases: aliasesToUse,
                data,
                format,
                loadParser: userDefinedLoadParser,
                parser: userDefinedParser,
                progressSize: asset.progressSize
              });
              resolvedAssets.push(formattedAsset);
            });
          });
          aliasesToUse.forEach((alias) => {
            this._assetMap[alias] = resolvedAssets;
          });
        });
      }
      // TODO: this needs an overload like load did in Assets
      /**
       * If the resolver has had a manifest set via setManifest, this will return the assets urls for
       * a given bundleId or bundleIds.
       * @example
       * // Manifest Example
       * const manifest = {
       *     bundles: [
       *         {
       *             name: 'load-screen',
       *             assets: [
       *                 {
       *                     alias: 'background',
       *                     src: 'sunset.png',
       *                 },
       *                 {
       *                     alias: 'bar',
       *                     src: 'load-bar.{png,webp}',
       *                 },
       *             ],
       *         },
       *         {
       *             name: 'game-screen',
       *             assets: [
       *                 {
       *                     alias: 'character',
       *                     src: 'robot.png',
       *                 },
       *                 {
       *                     alias: 'enemy',
       *                     src: 'bad-guy.png',
       *                 },
       *             ],
       *         },
       *     ]
       * };
       *
       * resolver.setManifest(manifest);
       * const resolved = resolver.resolveBundle('load-screen');
       * @param bundleIds - The bundle ids to resolve
       * @returns All the bundles assets or a hash of assets for each bundle specified
       */
      resolveBundle(bundleIds) {
        const singleAsset = isSingleItem(bundleIds);
        bundleIds = convertToList(bundleIds);
        const out = {};
        bundleIds.forEach((bundleId) => {
          const assetNames = this._bundles[bundleId];
          if (assetNames) {
            const results = this.resolve(assetNames);
            const assets = {};
            for (const key in results) {
              const asset = results[key];
              assets[this._extractAssetIdFromBundle(bundleId, key)] = asset;
            }
            out[bundleId] = assets;
          }
        });
        return singleAsset ? out[bundleIds[0]] : out;
      }
      /**
       * Does exactly what resolve does, but returns just the URL rather than the whole asset object
       * @param key - The key or keys to resolve
       * @returns - The URLs associated with the key(s)
       */
      resolveUrl(key) {
        const result = this.resolve(key);
        if (typeof key !== "string") {
          const out = {};
          for (const i in result) {
            out[i] = result[i].src;
          }
          return out;
        }
        return result.src;
      }
      resolve(keys) {
        const singleAsset = isSingleItem(keys);
        keys = convertToList(keys);
        const result = {};
        keys.forEach((key) => {
          if (!this._resolverHash[key]) {
            if (this._assetMap[key]) {
              let assets = this._assetMap[key];
              const preferredOrder = this._getPreferredOrder(assets);
              preferredOrder == null ? void 0 : preferredOrder.priority.forEach((priorityKey) => {
                preferredOrder.params[priorityKey].forEach((value) => {
                  const filteredAssets = assets.filter((asset) => {
                    if (asset[priorityKey]) {
                      return asset[priorityKey] === value;
                    }
                    return false;
                  });
                  if (filteredAssets.length) {
                    assets = filteredAssets;
                  }
                });
              });
              this._resolverHash[key] = assets[0];
            } else {
              this._resolverHash[key] = this._buildResolvedAsset({
                alias: [key],
                src: key
              }, {});
            }
          }
          result[key] = this._resolverHash[key];
        });
        return singleAsset ? result[keys[0]] : result;
      }
      /**
       * Checks if an asset with a given key exists in the resolver
       * @param key - The key of the asset
       */
      hasKey(key) {
        return !!this._assetMap[key];
      }
      /**
       * Checks if a bundle with the given key exists in the resolver
       * @param key - The key of the bundle
       */
      hasBundle(key) {
        return !!this._bundles[key];
      }
      /**
       * Internal function for figuring out what prefer criteria an asset should use.
       * @param assets
       */
      _getPreferredOrder(assets) {
        for (let i = 0; i < assets.length; i++) {
          const asset = assets[i];
          const preferred = this._preferredOrder.find((preference) => preference.params.format.includes(asset.format));
          if (preferred) {
            return preferred;
          }
        }
        return this._preferredOrder[0];
      }
      /**
       * Appends the default url parameters to the url
       * @param url - The url to append the default parameters to
       * @returns - The url with the default parameters appended
       */
      _appendDefaultSearchParams(url) {
        if (!this._defaultSearchParams)
          return url;
        const paramConnector = /\?/.test(url) ? "&" : "?";
        return `${url}${paramConnector}${this._defaultSearchParams}`;
      }
      _buildResolvedAsset(formattedAsset, data) {
        var _a, _b;
        const { aliases, data: assetData, loadParser, parser, format, progressSize } = data;
        if (this._basePath || this._rootPath) {
          formattedAsset.src = path.toAbsolute(formattedAsset.src, this._basePath, this._rootPath);
        }
        formattedAsset.alias = (_a = aliases != null ? aliases : formattedAsset.alias) != null ? _a : [formattedAsset.src];
        formattedAsset.src = this._appendDefaultSearchParams(formattedAsset.src);
        formattedAsset.data = __spreadValues$1c(__spreadValues$1c({}, assetData || {}), formattedAsset.data);
        formattedAsset.loadParser = loadParser != null ? loadParser : formattedAsset.loadParser;
        formattedAsset.parser = parser != null ? parser : formattedAsset.parser;
        formattedAsset.format = (_b = format != null ? format : formattedAsset.format) != null ? _b : getUrlExtension(formattedAsset.src);
        if (progressSize !== void 0) {
          formattedAsset.progressSize = progressSize;
        }
        return formattedAsset;
      }
    }
    /**
     * The prefix that denotes a URL is for a retina asset.
     * @default /@([0-9\.]+)x/
     * @example `@2x`
     */
    Resolver.RETINA_PREFIX = /@([0-9\.]+)x/;
    function getUrlExtension(url) {
      return url.split(".").pop().split("?").shift().split("#").shift();
    }

    "use strict";
    const copySearchParams = (targetUrl, sourceUrl) => {
      const searchParams = sourceUrl.split("?")[1];
      if (searchParams) {
        targetUrl += `?${searchParams}`;
      }
      return targetUrl;
    };

    var eventemitter3$1 = {exports: {}};

    var eventemitter3 = eventemitter3$1.exports;

    (function (module) {
    	'use strict';

    	var has = Object.prototype.hasOwnProperty
    	  , prefix = '~';

    	/**
    	 * Constructor to create a storage for our `EE` objects.
    	 * An `Events` instance is a plain object whose properties are event names.
    	 *
    	 * @constructor
    	 * @private
    	 */
    	function Events() {}

    	//
    	// We try to not inherit from `Object.prototype`. In some engines creating an
    	// instance in this way is faster than calling `Object.create(null)` directly.
    	// If `Object.create(null)` is not supported we prefix the event names with a
    	// character to make sure that the built-in object properties are not
    	// overridden or used as an attack vector.
    	//
    	if (Object.create) {
    	  Events.prototype = Object.create(null);

    	  //
    	  // This hack is needed because the `__proto__` property is still inherited in
    	  // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
    	  //
    	  if (!new Events().__proto__) prefix = false;
    	}

    	/**
    	 * Representation of a single event listener.
    	 *
    	 * @param {Function} fn The listener function.
    	 * @param {*} context The context to invoke the listener with.
    	 * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
    	 * @constructor
    	 * @private
    	 */
    	function EE(fn, context, once) {
    	  this.fn = fn;
    	  this.context = context;
    	  this.once = once || false;
    	}

    	/**
    	 * Add a listener for a given event.
    	 *
    	 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
    	 * @param {(String|Symbol)} event The event name.
    	 * @param {Function} fn The listener function.
    	 * @param {*} context The context to invoke the listener with.
    	 * @param {Boolean} once Specify if the listener is a one-time listener.
    	 * @returns {EventEmitter}
    	 * @private
    	 */
    	function addListener(emitter, event, fn, context, once) {
    	  if (typeof fn !== 'function') {
    	    throw new TypeError('The listener must be a function');
    	  }

    	  var listener = new EE(fn, context || emitter, once)
    	    , evt = prefix ? prefix + event : event;

    	  if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
    	  else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
    	  else emitter._events[evt] = [emitter._events[evt], listener];

    	  return emitter;
    	}

    	/**
    	 * Clear event by name.
    	 *
    	 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
    	 * @param {(String|Symbol)} evt The Event name.
    	 * @private
    	 */
    	function clearEvent(emitter, evt) {
    	  if (--emitter._eventsCount === 0) emitter._events = new Events();
    	  else delete emitter._events[evt];
    	}

    	/**
    	 * Minimal `EventEmitter` interface that is molded against the Node.js
    	 * `EventEmitter` interface.
    	 *
    	 * @constructor
    	 * @public
    	 */
    	function EventEmitter() {
    	  this._events = new Events();
    	  this._eventsCount = 0;
    	}

    	/**
    	 * Return an array listing the events for which the emitter has registered
    	 * listeners.
    	 *
    	 * @returns {Array}
    	 * @public
    	 */
    	EventEmitter.prototype.eventNames = function eventNames() {
    	  var names = []
    	    , events
    	    , name;

    	  if (this._eventsCount === 0) return names;

    	  for (name in (events = this._events)) {
    	    if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
    	  }

    	  if (Object.getOwnPropertySymbols) {
    	    return names.concat(Object.getOwnPropertySymbols(events));
    	  }

    	  return names;
    	};

    	/**
    	 * Return the listeners registered for a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @returns {Array} The registered listeners.
    	 * @public
    	 */
    	EventEmitter.prototype.listeners = function listeners(event) {
    	  var evt = prefix ? prefix + event : event
    	    , handlers = this._events[evt];

    	  if (!handlers) return [];
    	  if (handlers.fn) return [handlers.fn];

    	  for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
    	    ee[i] = handlers[i].fn;
    	  }

    	  return ee;
    	};

    	/**
    	 * Return the number of listeners listening to a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @returns {Number} The number of listeners.
    	 * @public
    	 */
    	EventEmitter.prototype.listenerCount = function listenerCount(event) {
    	  var evt = prefix ? prefix + event : event
    	    , listeners = this._events[evt];

    	  if (!listeners) return 0;
    	  if (listeners.fn) return 1;
    	  return listeners.length;
    	};

    	/**
    	 * Calls each of the listeners registered for a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @returns {Boolean} `true` if the event had listeners, else `false`.
    	 * @public
    	 */
    	EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
    	  var evt = prefix ? prefix + event : event;

    	  if (!this._events[evt]) return false;

    	  var listeners = this._events[evt]
    	    , len = arguments.length
    	    , args
    	    , i;

    	  if (listeners.fn) {
    	    if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);

    	    switch (len) {
    	      case 1: return listeners.fn.call(listeners.context), true;
    	      case 2: return listeners.fn.call(listeners.context, a1), true;
    	      case 3: return listeners.fn.call(listeners.context, a1, a2), true;
    	      case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
    	      case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
    	      case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
    	    }

    	    for (i = 1, args = new Array(len -1); i < len; i++) {
    	      args[i - 1] = arguments[i];
    	    }

    	    listeners.fn.apply(listeners.context, args);
    	  } else {
    	    var length = listeners.length
    	      , j;

    	    for (i = 0; i < length; i++) {
    	      if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);

    	      switch (len) {
    	        case 1: listeners[i].fn.call(listeners[i].context); break;
    	        case 2: listeners[i].fn.call(listeners[i].context, a1); break;
    	        case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
    	        case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
    	        default:
    	          if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
    	            args[j - 1] = arguments[j];
    	          }

    	          listeners[i].fn.apply(listeners[i].context, args);
    	      }
    	    }
    	  }

    	  return true;
    	};

    	/**
    	 * Add a listener for a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @param {Function} fn The listener function.
    	 * @param {*} [context=this] The context to invoke the listener with.
    	 * @returns {EventEmitter} `this`.
    	 * @public
    	 */
    	EventEmitter.prototype.on = function on(event, fn, context) {
    	  return addListener(this, event, fn, context, false);
    	};

    	/**
    	 * Add a one-time listener for a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @param {Function} fn The listener function.
    	 * @param {*} [context=this] The context to invoke the listener with.
    	 * @returns {EventEmitter} `this`.
    	 * @public
    	 */
    	EventEmitter.prototype.once = function once(event, fn, context) {
    	  return addListener(this, event, fn, context, true);
    	};

    	/**
    	 * Remove the listeners of a given event.
    	 *
    	 * @param {(String|Symbol)} event The event name.
    	 * @param {Function} fn Only remove the listeners that match this function.
    	 * @param {*} context Only remove the listeners that have this context.
    	 * @param {Boolean} once Only remove one-time listeners.
    	 * @returns {EventEmitter} `this`.
    	 * @public
    	 */
    	EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
    	  var evt = prefix ? prefix + event : event;

    	  if (!this._events[evt]) return this;
    	  if (!fn) {
    	    clearEvent(this, evt);
    	    return this;
    	  }

    	  var listeners = this._events[evt];

    	  if (listeners.fn) {
    	    if (
    	      listeners.fn === fn &&
    	      (!once || listeners.once) &&
    	      (!context || listeners.context === context)
    	    ) {
    	      clearEvent(this, evt);
    	    }
    	  } else {
    	    for (var i = 0, events = [], length = listeners.length; i < length; i++) {
    	      if (
    	        listeners[i].fn !== fn ||
    	        (once && !listeners[i].once) ||
    	        (context && listeners[i].context !== context)
    	      ) {
    	        events.push(listeners[i]);
    	      }
    	    }

    	    //
    	    // Reset the array, or remove it completely if we have no more listeners.
    	    //
    	    if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
    	    else clearEvent(this, evt);
    	  }

    	  return this;
    	};

    	/**
    	 * Remove all listeners, or those of the specified event.
    	 *
    	 * @param {(String|Symbol)} [event] The event name.
    	 * @returns {EventEmitter} `this`.
    	 * @public
    	 */
    	EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
    	  var evt;

    	  if (event) {
    	    evt = prefix ? prefix + event : event;
    	    if (this._events[evt]) clearEvent(this, evt);
    	  } else {
    	    this._events = new Events();
    	    this._eventsCount = 0;
    	  }

    	  return this;
    	};

    	//
    	// Alias methods names because people roll like that.
    	//
    	EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
    	EventEmitter.prototype.addListener = EventEmitter.prototype.on;

    	//
    	// Expose the prefix.
    	//
    	EventEmitter.prefixed = prefix;

    	//
    	// Allow `EventEmitter` to be imported as module namespace.
    	//
    	EventEmitter.EventEmitter = EventEmitter;

    	//
    	// Expose the module.
    	//
    	if ('undefined' !== 'object') {
    	  module.exports = EventEmitter;
    	} 
    } (eventemitter3$1));

    var eventemitter3Exports = eventemitter3$1.exports;
    var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);

    "use strict";
    const PI_2 = Math.PI * 2;
    const RAD_TO_DEG = 180 / Math.PI;
    const DEG_TO_RAD = Math.PI / 180;

    "use strict";
    class Point {
      /**
       * Creates a new `Point`
       * @param {number} [x=0] - position of the point on the x axis
       * @param {number} [y=0] - position of the point on the y axis
       */
      constructor(x = 0, y = 0) {
        /**
         * Position of the point on the x axis
         * @example
         * ```ts
         * // Set x position
         * const point = new Point();
         * point.x = 100;
         *
         * // Use in calculations
         * const width = rightPoint.x - leftPoint.x;
         * ```
         */
        this.x = 0;
        /**
         * Position of the point on the y axis
         * @example
         * ```ts
         * // Set y position
         * const point = new Point();
         * point.y = 200;
         *
         * // Use in calculations
         * const height = bottomPoint.y - topPoint.y;
         * ```
         */
        this.y = 0;
        this.x = x;
        this.y = y;
      }
      /**
       * Creates a clone of this point, which is a new instance with the same `x` and `y` values.
       * @example
       * ```ts
       * // Basic point cloning
       * const original = new Point(100, 200);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.set(300, 400);
       *
       * // Verify independence
       * console.log(original); // Point(100, 200)
       * console.log(modified); // Point(300, 400)
       * ```
       * @remarks
       * - Creates new Point instance
       * - Deep copies x and y values
       * - Independent from original
       * - Useful for preserving values
       * @returns A clone of this point
       * @see {@link Point.copyFrom} For copying into existing point
       * @see {@link Point.copyTo} For copying to existing point
       */
      clone() {
        return new Point(this.x, this.y);
      }
      /**
       * Copies x and y from the given point into this point.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Point(100, 200);
       * const target = new Point();
       * target.copyFrom(source);
       *
       * // Copy and chain operations
       * const point = new Point()
       *     .copyFrom(source)
       *     .set(x + 50, y + 50);
       *
       * // Copy from any PointData
       * const data = { x: 10, y: 20 };
       * point.copyFrom(data);
       * ```
       * @param p - The point to copy from
       * @returns The point instance itself
       * @see {@link Point.copyTo} For copying to another point
       * @see {@link Point.clone} For creating new point copy
       */
      copyFrom(p) {
        this.set(p.x, p.y);
        return this;
      }
      /**
       * Copies this point's x and y into the given point.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Point(100, 200);
       * const target = new Point();
       * source.copyTo(target);
       * ```
       * @param p - The point to copy to. Can be any type that is or extends `PointLike`
       * @returns The point (`p`) with values updated
       * @see {@link Point.copyFrom} For copying from another point
       * @see {@link Point.clone} For creating new point copy
       */
      copyTo(p) {
        p.set(this.x, this.y);
        return p;
      }
      /**
       * Checks if another point is equal to this point.
       *
       * Compares x and y values using strict equality.
       * @example
       * ```ts
       * // Basic equality check
       * const p1 = new Point(100, 200);
       * const p2 = new Point(100, 200);
       * console.log(p1.equals(p2)); // true
       *
       * // Compare with PointData
       * const data = { x: 100, y: 200 };
       * console.log(p1.equals(data)); // true
       *
       * // Check different points
       * const p3 = new Point(200, 300);
       * console.log(p1.equals(p3)); // false
       * ```
       * @param p - The point to check
       * @returns `true` if both `x` and `y` are equal
       * @see {@link Point.copyFrom} For making points equal
       * @see {@link PointData} For point data interface
       */
      equals(p) {
        return p.x === this.x && p.y === this.y;
      }
      /**
       * Sets the point to a new x and y position.
       *
       * If y is omitted, both x and y will be set to x.
       * @example
       * ```ts
       * // Basic position setting
       * const point = new Point();
       * point.set(100, 200);
       *
       * // Set both x and y to same value
       * point.set(50); // x=50, y=50
       *
       * // Chain with other operations
       * point
       *     .set(10, 20)
       *     .copyTo(otherPoint);
       * ```
       * @param x - Position on the x axis
       * @param y - Position on the y axis, defaults to x
       * @returns The point instance itself
       * @see {@link Point.copyFrom} For copying from another point
       * @see {@link Point.equals} For comparing positions
       */
      set(x = 0, y = x) {
        this.x = x;
        this.y = y;
        return this;
      }
      toString() {
        return `[pixi.js/math:Point x=${this.x} y=${this.y}]`;
      }
      /**
       * A static Point object with `x` and `y` values of `0`.
       *
       * This shared instance is reset to zero values when accessed.
       *
       * > [!IMPORTANT] This point is shared and temporary. Do not store references to it.
       * @example
       * ```ts
       * // Use for temporary calculations
       * const tempPoint = Point.shared;
       * tempPoint.set(100, 200);
       * matrix.apply(tempPoint);
       *
       * // Will be reset to (0,0) on next access
       * const fresh = Point.shared; // x=0, y=0
       * ```
       * @readonly
       * @returns A fresh zeroed point for temporary use
       * @see {@link Point.constructor} For creating new points
       * @see {@link PointData} For basic point interface
       */
      static get shared() {
        tempPoint.x = 0;
        tempPoint.y = 0;
        return tempPoint;
      }
    }
    const tempPoint = new Point();

    "use strict";
    class Matrix {
      /**
       * @param a - x scale
       * @param b - y skew
       * @param c - x skew
       * @param d - y scale
       * @param tx - x translation
       * @param ty - y translation
       */
      constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
        /**
         * Array representation of the matrix.
         * Only populated when `toArray()` is called.
         * @default null
         * @see {@link Matrix.toArray} For filling this array
         */
        this.array = null;
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.tx = tx;
        this.ty = ty;
      }
      /**
       * Creates a Matrix object based on the given array.
       * Populates matrix components from a flat array in column-major order.
       *
       * > [!NOTE] Array mapping order:
       * > ```
       * > array[0] = a  (x scale)
       * > array[1] = b  (y skew)
       * > array[2] = tx (x translation)
       * > array[3] = c  (x skew)
       * > array[4] = d  (y scale)
       * > array[5] = ty (y translation)
       * > ```
       * @example
       * ```ts
       * // Create matrix from array
       * const matrix = new Matrix();
       * matrix.fromArray([
       *     2, 0,  100,  // a, b, tx
       *     0, 2,  100   // c, d, ty
       * ]);
       *
       * // Create matrix from typed array
       * const float32Array = new Float32Array([
       *     1, 0, 0,     // Scale x1, no skew
       *     0, 1, 0      // No skew, scale x1
       * ]);
       * matrix.fromArray(float32Array);
       * ```
       * @param array - The array to populate the matrix from
       * @see {@link Matrix.toArray} For converting matrix to array
       * @see {@link Matrix.set} For setting values directly
       */
      fromArray(array) {
        this.a = array[0];
        this.b = array[1];
        this.c = array[3];
        this.d = array[4];
        this.tx = array[2];
        this.ty = array[5];
      }
      /**
       * Sets the matrix properties directly.
       * All matrix components can be set in one call.
       * @example
       * ```ts
       * // Set to identity matrix
       * matrix.set(1, 0, 0, 1, 0, 0);
       *
       * // Set to scale matrix
       * matrix.set(2, 0, 0, 2, 0, 0); // Scale 2x
       *
       * // Set to translation matrix
       * matrix.set(1, 0, 0, 1, 100, 50); // Move 100,50
       * ```
       * @param a - Scale on x axis
       * @param b - Shear on y axis
       * @param c - Shear on x axis
       * @param d - Scale on y axis
       * @param tx - Translation on x axis
       * @param ty - Translation on y axis
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.identity} For resetting to identity
       * @see {@link Matrix.fromArray} For setting from array
       */
      set(a, b, c, d, tx, ty) {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.tx = tx;
        this.ty = ty;
        return this;
      }
      /**
       * Creates an array from the current Matrix object.
       *
       * > [!NOTE] The array format is:
       * > ```
       * > Non-transposed:
       * > [a, c, tx,
       * > b, d, ty,
       * > 0, 0, 1]
       * >
       * > Transposed:
       * > [a, b, 0,
       * > c, d, 0,
       * > tx,ty,1]
       * > ```
       * @example
       * ```ts
       * // Basic array conversion
       * const matrix = new Matrix(2, 0, 0, 2, 100, 100);
       * const array = matrix.toArray();
       *
       * // Using existing array
       * const float32Array = new Float32Array(9);
       * matrix.toArray(false, float32Array);
       *
       * // Get transposed array
       * const transposed = matrix.toArray(true);
       * ```
       * @param transpose - Whether to transpose the matrix
       * @param out - Optional Float32Array to store the result
       * @returns The array containing the matrix values
       * @see {@link Matrix.fromArray} For creating matrix from array
       * @see {@link Matrix.array} For cached array storage
       */
      toArray(transpose, out) {
        if (!this.array) {
          this.array = new Float32Array(9);
        }
        const array = out || this.array;
        if (transpose) {
          array[0] = this.a;
          array[1] = this.b;
          array[2] = 0;
          array[3] = this.c;
          array[4] = this.d;
          array[5] = 0;
          array[6] = this.tx;
          array[7] = this.ty;
          array[8] = 1;
        } else {
          array[0] = this.a;
          array[1] = this.c;
          array[2] = this.tx;
          array[3] = this.b;
          array[4] = this.d;
          array[5] = this.ty;
          array[6] = 0;
          array[7] = 0;
          array[8] = 1;
        }
        return array;
      }
      /**
       * Get a new position with the current transformation applied.
       *
       * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering)
       * @example
       * ```ts
       * // Basic point transformation
       * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
       * const point = new Point(10, 20);
       * const transformed = matrix.apply(point);
       *
       * // Reuse existing point
       * const output = new Point();
       * matrix.apply(point, output);
       * ```
       * @param pos - The origin point to transform
       * @param newPos - Optional point to store the result
       * @returns The transformed point
       * @see {@link Matrix.applyInverse} For inverse transformation
       * @see {@link Point} For point operations
       */
      apply(pos, newPos) {
        newPos = newPos || new Point();
        const x = pos.x;
        const y = pos.y;
        newPos.x = this.a * x + this.c * y + this.tx;
        newPos.y = this.b * x + this.d * y + this.ty;
        return newPos;
      }
      /**
       * Get a new position with the inverse of the current transformation applied.
       *
       * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input)
       * @example
       * ```ts
       * // Basic inverse transformation
       * const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
       * const worldPoint = new Point(150, 100);
       * const localPoint = matrix.applyInverse(worldPoint);
       *
       * // Reuse existing point
       * const output = new Point();
       * matrix.applyInverse(worldPoint, output);
       *
       * // Convert mouse position to local space
       * const mousePoint = new Point(mouseX, mouseY);
       * const localMouse = matrix.applyInverse(mousePoint);
       * ```
       * @param pos - The origin point to inverse-transform
       * @param newPos - Optional point to store the result
       * @returns The inverse-transformed point
       * @see {@link Matrix.apply} For forward transformation
       * @see {@link Matrix.invert} For getting inverse matrix
       */
      applyInverse(pos, newPos) {
        newPos = newPos || new Point();
        const a = this.a;
        const b = this.b;
        const c = this.c;
        const d = this.d;
        const tx = this.tx;
        const ty = this.ty;
        const id = 1 / (a * d + c * -b);
        const x = pos.x;
        const y = pos.y;
        newPos.x = d * id * x + -c * id * y + (ty * c - tx * d) * id;
        newPos.y = a * id * y + -b * id * x + (-ty * a + tx * b) * id;
        return newPos;
      }
      /**
       * Translates the matrix on the x and y axes.
       * Adds to the position values while preserving scale, rotation and skew.
       * @example
       * ```ts
       * // Basic translation
       * const matrix = new Matrix();
       * matrix.translate(100, 50); // Move right 100, down 50
       *
       * // Chain with other transformations
       * matrix
       *     .scale(2, 2)
       *     .translate(100, 0)
       *     .rotate(Math.PI / 4);
       * ```
       * @param x - How much to translate on the x axis
       * @param y - How much to translate on the y axis
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.set} For setting position directly
       * @see {@link Matrix.setTransform} For complete transform setup
       */
      translate(x, y) {
        this.tx += x;
        this.ty += y;
        return this;
      }
      /**
       * Applies a scale transformation to the matrix.
       * Multiplies the scale values with existing matrix components.
       * @example
       * ```ts
       * // Basic scaling
       * const matrix = new Matrix();
       * matrix.scale(2, 3); // Scale 2x horizontally, 3x vertically
       *
       * // Chain with other transformations
       * matrix
       *     .translate(100, 100)
       *     .scale(2, 2)     // Scales after translation
       *     .rotate(Math.PI / 4);
       * ```
       * @param x - The amount to scale horizontally
       * @param y - The amount to scale vertically
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.setTransform} For setting scale directly
       * @see {@link Matrix.append} For combining transformations
       */
      scale(x, y) {
        this.a *= x;
        this.d *= y;
        this.c *= x;
        this.b *= y;
        this.tx *= x;
        this.ty *= y;
        return this;
      }
      /**
       * Applies a rotation transformation to the matrix.
       *
       * Rotates around the origin (0,0) by the given angle in radians.
       * @example
       * ```ts
       * // Basic rotation
       * const matrix = new Matrix();
       * matrix.rotate(Math.PI / 4); // Rotate 45 degrees
       *
       * // Chain with other transformations
       * matrix
       *     .translate(100, 100) // Move to rotation center
       *     .rotate(Math.PI)     // Rotate 180 degrees
       *     .scale(2, 2);        // Scale after rotation
       *
       * // Common angles
       * matrix.rotate(Math.PI / 2);  // 90 degrees
       * matrix.rotate(Math.PI);      // 180 degrees
       * matrix.rotate(Math.PI * 2);  // 360 degrees
       * ```
       * @remarks
       * - Rotates around origin point (0,0)
       * - Affects position if translation was set
       * - Uses counter-clockwise rotation
       * - Order of operations matters when chaining
       * @param angle - The angle in radians
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.setTransform} For setting rotation directly
       * @see {@link Matrix.append} For combining transformations
       */
      rotate(angle) {
        const cos = Math.cos(angle);
        const sin = Math.sin(angle);
        const a1 = this.a;
        const c1 = this.c;
        const tx1 = this.tx;
        this.a = a1 * cos - this.b * sin;
        this.b = a1 * sin + this.b * cos;
        this.c = c1 * cos - this.d * sin;
        this.d = c1 * sin + this.d * cos;
        this.tx = tx1 * cos - this.ty * sin;
        this.ty = tx1 * sin + this.ty * cos;
        return this;
      }
      /**
       * Appends the given Matrix to this Matrix.
       * Combines two matrices by multiplying them together: this = this * matrix
       * @example
       * ```ts
       * // Basic matrix combination
       * const matrix = new Matrix();
       * const other = new Matrix().translate(100, 0).rotate(Math.PI / 4);
       * matrix.append(other);
       * ```
       * @remarks
       * - Order matters: A.append(B) !== B.append(A)
       * - Modifies current matrix
       * - Preserves transformation order
       * - Commonly used for combining transforms
       * @param matrix - The matrix to append
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.prepend} For prepending transformations
       * @see {@link Matrix.appendFrom} For appending two external matrices
       */
      append(matrix) {
        const a1 = this.a;
        const b1 = this.b;
        const c1 = this.c;
        const d1 = this.d;
        this.a = matrix.a * a1 + matrix.b * c1;
        this.b = matrix.a * b1 + matrix.b * d1;
        this.c = matrix.c * a1 + matrix.d * c1;
        this.d = matrix.c * b1 + matrix.d * d1;
        this.tx = matrix.tx * a1 + matrix.ty * c1 + this.tx;
        this.ty = matrix.tx * b1 + matrix.ty * d1 + this.ty;
        return this;
      }
      /**
       * Appends two matrices and sets the result to this matrix.
       * Performs matrix multiplication: this = A * B
       * @example
       * ```ts
       * // Basic matrix multiplication
       * const result = new Matrix();
       * const matrixA = new Matrix().scale(2, 2);
       * const matrixB = new Matrix().rotate(Math.PI / 4);
       * result.appendFrom(matrixA, matrixB);
       * ```
       * @remarks
       * - Order matters: A * B !== B * A
       * - Creates a new transformation from two others
       * - More efficient than append() for multiple operations
       * - Does not modify input matrices
       * @param a - The first matrix to multiply
       * @param b - The second matrix to multiply
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.append} For single matrix combination
       * @see {@link Matrix.prepend} For reverse order multiplication
       */
      appendFrom(a, b) {
        const a1 = a.a;
        const b1 = a.b;
        const c1 = a.c;
        const d1 = a.d;
        const tx = a.tx;
        const ty = a.ty;
        const a2 = b.a;
        const b2 = b.b;
        const c2 = b.c;
        const d2 = b.d;
        this.a = a1 * a2 + b1 * c2;
        this.b = a1 * b2 + b1 * d2;
        this.c = c1 * a2 + d1 * c2;
        this.d = c1 * b2 + d1 * d2;
        this.tx = tx * a2 + ty * c2 + b.tx;
        this.ty = tx * b2 + ty * d2 + b.ty;
        return this;
      }
      /**
       * Sets the matrix based on all the available properties.
       * Combines position, scale, rotation, skew and pivot in a single operation.
       * @example
       * ```ts
       * // Basic transform setup
       * const matrix = new Matrix();
       * matrix.setTransform(
       *     100, 100,    // position
       *     0, 0,        // pivot
       *     2, 2,        // scale
       *     Math.PI / 4, // rotation (45 degrees)
       *     0, 0         // skew
       * );
       * ```
       * @remarks
       * - Updates all matrix components at once
       * - More efficient than separate transform calls
       * - Uses radians for rotation and skew
       * - Pivot affects rotation center
       * @param x - Position on the x axis
       * @param y - Position on the y axis
       * @param pivotX - Pivot on the x axis
       * @param pivotY - Pivot on the y axis
       * @param scaleX - Scale on the x axis
       * @param scaleY - Scale on the y axis
       * @param rotation - Rotation in radians
       * @param skewX - Skew on the x axis
       * @param skewY - Skew on the y axis
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.decompose} For extracting transform properties
       * @see {@link TransformableObject} For transform data structure
       */
      setTransform(x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY) {
        this.a = Math.cos(rotation + skewY) * scaleX;
        this.b = Math.sin(rotation + skewY) * scaleX;
        this.c = -Math.sin(rotation - skewX) * scaleY;
        this.d = Math.cos(rotation - skewX) * scaleY;
        this.tx = x - (pivotX * this.a + pivotY * this.c);
        this.ty = y - (pivotX * this.b + pivotY * this.d);
        return this;
      }
      /**
       * Prepends the given Matrix to this Matrix.
       * Combines two matrices by multiplying them together: this = matrix * this
       * @example
       * ```ts
       * // Basic matrix prepend
       * const matrix = new Matrix().scale(2, 2);
       * const other = new Matrix().translate(100, 0);
       * matrix.prepend(other); // Translation happens before scaling
       * ```
       * @remarks
       * - Order matters: A.prepend(B) !== B.prepend(A)
       * - Modifies current matrix
       * - Reverses transformation order compared to append()
       * @param matrix - The matrix to prepend
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.append} For appending transformations
       * @see {@link Matrix.appendFrom} For combining external matrices
       */
      prepend(matrix) {
        const tx1 = this.tx;
        if (matrix.a !== 1 || matrix.b !== 0 || matrix.c !== 0 || matrix.d !== 1) {
          const a1 = this.a;
          const c1 = this.c;
          this.a = a1 * matrix.a + this.b * matrix.c;
          this.b = a1 * matrix.b + this.b * matrix.d;
          this.c = c1 * matrix.a + this.d * matrix.c;
          this.d = c1 * matrix.b + this.d * matrix.d;
        }
        this.tx = tx1 * matrix.a + this.ty * matrix.c + matrix.tx;
        this.ty = tx1 * matrix.b + this.ty * matrix.d + matrix.ty;
        return this;
      }
      /**
       * Decomposes the matrix into its individual transform components.
       * Extracts position, scale, rotation and skew values from the matrix.
       * @example
       * ```ts
       * // Basic decomposition
       * const matrix = new Matrix()
       *     .translate(100, 100)
       *     .rotate(Math.PI / 4)
       *     .scale(2, 2);
       *
       * const transform = {
       *     position: new Point(),
       *     scale: new Point(),
       *     pivot: new Point(),
       *     skew: new Point(),
       *     rotation: 0
       * };
       *
       * matrix.decompose(transform);
       * console.log(transform.position); // Point(100, 100)
       * console.log(transform.rotation); // ~0.785 (PI/4)
       * console.log(transform.scale); // Point(2, 2)
       * ```
       * @remarks
       * - Handles combined transformations
       * - Accounts for pivot points
       * - Chooses between rotation/skew based on transform type
       * - Uses radians for rotation and skew
       * @param transform - The transform object to store the decomposed values
       * @returns The transform with the newly applied properties
       * @see {@link Matrix.setTransform} For composing from components
       * @see {@link TransformableObject} For transform structure
       */
      decompose(transform) {
        const a = this.a;
        const b = this.b;
        const c = this.c;
        const d = this.d;
        const pivot = transform.pivot;
        const skewX = -Math.atan2(-c, d);
        const skewY = Math.atan2(b, a);
        const delta = Math.abs(skewX + skewY);
        if (delta < 1e-5 || Math.abs(PI_2 - delta) < 1e-5) {
          transform.rotation = skewY;
          transform.skew.x = transform.skew.y = 0;
        } else {
          transform.rotation = 0;
          transform.skew.x = skewX;
          transform.skew.y = skewY;
        }
        transform.scale.x = Math.sqrt(a * a + b * b);
        transform.scale.y = Math.sqrt(c * c + d * d);
        transform.position.x = this.tx + (pivot.x * a + pivot.y * c);
        transform.position.y = this.ty + (pivot.x * b + pivot.y * d);
        return transform;
      }
      /**
       * Inverts this matrix.
       * Creates the matrix that when multiplied with this matrix results in an identity matrix.
       * @example
       * ```ts
       * // Basic matrix inversion
       * const matrix = new Matrix()
       *     .translate(100, 50)
       *     .scale(2, 2);
       *
       * matrix.invert(); // Now transforms in opposite direction
       *
       * // Verify inversion
       * const point = new Point(50, 50);
       * const transformed = matrix.apply(point);
       * const original = matrix.invert().apply(transformed);
       * // original ≈ point
       * ```
       * @remarks
       * - Modifies the current matrix
       * - Useful for reversing transformations
       * - Cannot invert matrices with zero determinant
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.identity} For resetting to identity
       * @see {@link Matrix.applyInverse} For inverse transformations
       */
      invert() {
        const a1 = this.a;
        const b1 = this.b;
        const c1 = this.c;
        const d1 = this.d;
        const tx1 = this.tx;
        const n = a1 * d1 - b1 * c1;
        this.a = d1 / n;
        this.b = -b1 / n;
        this.c = -c1 / n;
        this.d = a1 / n;
        this.tx = (c1 * this.ty - d1 * tx1) / n;
        this.ty = -(a1 * this.ty - b1 * tx1) / n;
        return this;
      }
      /**
       * Checks if this matrix is an identity matrix.
       *
       * An identity matrix has no transformations applied (default state).
       * @example
       * ```ts
       * // Check if matrix is identity
       * const matrix = new Matrix();
       * console.log(matrix.isIdentity()); // true
       *
       * // Check after transformations
       * matrix.translate(100, 0);
       * console.log(matrix.isIdentity()); // false
       *
       * // Reset and verify
       * matrix.identity();
       * console.log(matrix.isIdentity()); // true
       * ```
       * @remarks
       * - Verifies a = 1, d = 1 (no scale)
       * - Verifies b = 0, c = 0 (no skew)
       * - Verifies tx = 0, ty = 0 (no translation)
       * @returns True if matrix has no transformations
       * @see {@link Matrix.identity} For resetting to identity
       * @see {@link Matrix.IDENTITY} For constant identity matrix
       */
      isIdentity() {
        return this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.tx === 0 && this.ty === 0;
      }
      /**
       * Resets this Matrix to an identity (default) matrix.
       * Sets all components to their default values: scale=1, no skew, no translation.
       * @example
       * ```ts
       * // Reset transformed matrix
       * const matrix = new Matrix()
       *     .scale(2, 2)
       *     .rotate(Math.PI / 4);
       * matrix.identity(); // Back to default state
       *
       * // Chain after reset
       * matrix
       *     .identity()
       *     .translate(100, 100)
       *     .scale(2, 2);
       *
       * // Compare with identity constant
       * const isDefault = matrix.equals(Matrix.IDENTITY);
       * ```
       * @remarks
       * - Sets a=1, d=1 (default scale)
       * - Sets b=0, c=0 (no skew)
       * - Sets tx=0, ty=0 (no translation)
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.IDENTITY} For constant identity matrix
       * @see {@link Matrix.isIdentity} For checking identity state
       */
      identity() {
        this.a = 1;
        this.b = 0;
        this.c = 0;
        this.d = 1;
        this.tx = 0;
        this.ty = 0;
        return this;
      }
      /**
       * Creates a new Matrix object with the same values as this one.
       * @returns A copy of this matrix. Good for chaining method calls.
       */
      clone() {
        const matrix = new Matrix();
        matrix.a = this.a;
        matrix.b = this.b;
        matrix.c = this.c;
        matrix.d = this.d;
        matrix.tx = this.tx;
        matrix.ty = this.ty;
        return matrix;
      }
      /**
       * Creates a new Matrix object with the same values as this one.
       * @param matrix
       * @example
       * ```ts
       * // Basic matrix cloning
       * const matrix = new Matrix()
       *     .translate(100, 100)
       *     .rotate(Math.PI / 4);
       * const copy = matrix.clone();
       *
       * // Clone and modify
       * const modified = matrix.clone()
       *     .scale(2, 2);
       *
       * // Compare matrices
       * console.log(matrix.equals(copy));     // true
       * console.log(matrix.equals(modified)); // false
       * ```
       * @returns A copy of this matrix. Good for chaining method calls.
       * @see {@link Matrix.copyTo} For copying to existing matrix
       * @see {@link Matrix.copyFrom} For copying from another matrix
       */
      copyTo(matrix) {
        matrix.a = this.a;
        matrix.b = this.b;
        matrix.c = this.c;
        matrix.d = this.d;
        matrix.tx = this.tx;
        matrix.ty = this.ty;
        return matrix;
      }
      /**
       * Changes the values of the matrix to be the same as the ones in given matrix.
       * @example
       * ```ts
       * // Basic matrix copying
       * const source = new Matrix()
       *     .translate(100, 100)
       *     .rotate(Math.PI / 4);
       * const target = new Matrix();
       * target.copyFrom(source);
       * ```
       * @param matrix - The matrix to copy from
       * @returns This matrix. Good for chaining method calls.
       * @see {@link Matrix.clone} For creating new matrix copy
       * @see {@link Matrix.copyTo} For copying to another matrix
       */
      copyFrom(matrix) {
        this.a = matrix.a;
        this.b = matrix.b;
        this.c = matrix.c;
        this.d = matrix.d;
        this.tx = matrix.tx;
        this.ty = matrix.ty;
        return this;
      }
      /**
       * Checks if this matrix equals another matrix.
       * Compares all components for exact equality.
       * @example
       * ```ts
       * // Basic equality check
       * const m1 = new Matrix();
       * const m2 = new Matrix();
       * console.log(m1.equals(m2)); // true
       *
       * // Compare transformed matrices
       * const transform = new Matrix()
       *     .translate(100, 100)
       * const clone = new Matrix()
       *     .scale(2, 2);
       * console.log(transform.equals(clone)); // false
       * ```
       * @param matrix - The matrix to compare to
       * @returns True if matrices are identical
       * @see {@link Matrix.copyFrom} For copying matrix values
       * @see {@link Matrix.isIdentity} For identity comparison
       */
      equals(matrix) {
        return matrix.a === this.a && matrix.b === this.b && matrix.c === this.c && matrix.d === this.d && matrix.tx === this.tx && matrix.ty === this.ty;
      }
      toString() {
        return `[pixi.js:Matrix a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
      }
      /**
       * A default (identity) matrix with no transformations applied.
       *
       * > [!IMPORTANT] This is a shared read-only object. Create a new Matrix if you need to modify it.
       * @example
       * ```ts
       * // Get identity matrix reference
       * const identity = Matrix.IDENTITY;
       * console.log(identity.isIdentity()); // true
       *
       * // Compare with identity
       * const matrix = new Matrix();
       * console.log(matrix.equals(Matrix.IDENTITY)); // true
       *
       * // Create new matrix instead of modifying IDENTITY
       * const transform = new Matrix()
       *     .copyFrom(Matrix.IDENTITY)
       *     .translate(100, 100);
       * ```
       * @readonly
       * @returns A read-only identity matrix
       * @see {@link Matrix.shared} For temporary calculations
       * @see {@link Matrix.identity} For resetting matrices
       */
      static get IDENTITY() {
        return identityMatrix$1.identity();
      }
      /**
       * A static Matrix that can be used to avoid creating new objects.
       * Will always ensure the matrix is reset to identity when requested.
       *
       * > [!IMPORTANT] This matrix is shared and temporary. Do not store references to it.
       * @example
       * ```ts
       * // Use for temporary calculations
       * const tempMatrix = Matrix.shared;
       * tempMatrix.translate(100, 100).rotate(Math.PI / 4);
       * const point = tempMatrix.apply({ x: 10, y: 20 });
       *
       * // Will be reset to identity on next access
       * const fresh = Matrix.shared; // Back to identity
       * ```
       * @remarks
       * - Always returns identity matrix
       * - Safe to modify temporarily
       * - Not safe to store references
       * - Useful for one-off calculations
       * @readonly
       * @returns A fresh identity matrix for temporary use
       * @see {@link Matrix.IDENTITY} For immutable identity matrix
       * @see {@link Matrix.identity} For resetting matrices
       */
      static get shared() {
        return tempMatrix$6.identity();
      }
    }
    const tempMatrix$6 = new Matrix();
    const identityMatrix$1 = new Matrix();

    "use strict";
    const ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1];
    const uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1];
    const vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1];
    const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1];
    const rotationCayley = [];
    const rotationMatrices = [];
    const signum = Math.sign;
    function init() {
      for (let i = 0; i < 16; i++) {
        const row = [];
        rotationCayley.push(row);
        for (let j = 0; j < 16; j++) {
          const _ux = signum(ux[i] * ux[j] + vx[i] * uy[j]);
          const _uy = signum(uy[i] * ux[j] + vy[i] * uy[j]);
          const _vx = signum(ux[i] * vx[j] + vx[i] * vy[j]);
          const _vy = signum(uy[i] * vx[j] + vy[i] * vy[j]);
          for (let k = 0; k < 16; k++) {
            if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy) {
              row.push(k);
              break;
            }
          }
        }
      }
      for (let i = 0; i < 16; i++) {
        const mat = new Matrix();
        mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0);
        rotationMatrices.push(mat);
      }
    }
    init();
    const groupD8 = {
      /**
       * | Rotation | Direction |
       * |----------|-----------|
       * | 0°       | East      |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      E: 0,
      /**
       * | Rotation | Direction |
       * |----------|-----------|
       * | 45°↻     | Southeast |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      SE: 1,
      /**
       * | Rotation | Direction |
       * |----------|-----------|
       * | 90°↻     | South     |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      S: 2,
      /**
       * | Rotation | Direction |
       * |----------|-----------|
       * | 135°↻    | Southwest |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      SW: 3,
      /**
       * | Rotation | Direction |
       * |----------|-----------|
       * | 180°     | West      |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      W: 4,
      /**
       * | Rotation    | Direction    |
       * |-------------|--------------|
       * | -135°/225°↻ | Northwest    |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      NW: 5,
      /**
       * | Rotation    | Direction    |
       * |-------------|--------------|
       * | -90°/270°↻  | North        |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      N: 6,
      /**
       * | Rotation    | Direction    |
       * |-------------|--------------|
       * | -45°/315°↻  | Northeast    |
       * @group groupD8
       * @type {GD8Symmetry}
       */
      NE: 7,
      /**
       * Reflection about Y-axis.
       * @group groupD8
       * @type {GD8Symmetry}
       */
      MIRROR_VERTICAL: 8,
      /**
       * Reflection about the main diagonal.
       * @group groupD8
       * @type {GD8Symmetry}
       */
      MAIN_DIAGONAL: 10,
      /**
       * Reflection about X-axis.
       * @group groupD8
       * @type {GD8Symmetry}
       */
      MIRROR_HORIZONTAL: 12,
      /**
       * Reflection about reverse diagonal.
       * @group groupD8
       * @type {GD8Symmetry}
       */
      REVERSE_DIAGONAL: 14,
      /**
       * @group groupD8
       * @param {GD8Symmetry} ind - sprite rotation angle.
       * @returns {GD8Symmetry} The X-component of the U-axis
       *    after rotating the axes.
       */
      uX: (ind) => ux[ind],
      /**
       * @group groupD8
       * @param {GD8Symmetry} ind - sprite rotation angle.
       * @returns {GD8Symmetry} The Y-component of the U-axis
       *    after rotating the axes.
       */
      uY: (ind) => uy[ind],
      /**
       * @group groupD8
       * @param {GD8Symmetry} ind - sprite rotation angle.
       * @returns {GD8Symmetry} The X-component of the V-axis
       *    after rotating the axes.
       */
      vX: (ind) => vx[ind],
      /**
       * @group groupD8
       * @param {GD8Symmetry} ind - sprite rotation angle.
       * @returns {GD8Symmetry} The Y-component of the V-axis
       *    after rotating the axes.
       */
      vY: (ind) => vy[ind],
      /**
       * @group groupD8
       * @param {GD8Symmetry} rotation - symmetry whose opposite
       *   is needed. Only rotations have opposite symmetries while
       *   reflections don't.
       * @returns {GD8Symmetry} The opposite symmetry of `rotation`
       */
      inv: (rotation) => {
        if (rotation & 8) {
          return rotation & 15;
        }
        return -rotation & 7;
      },
      /**
       * Composes the two D8 operations.
       *
       * Taking `^` as reflection:
       *
       * |       | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 |
       * |-------|-----|-----|-----|-----|------|-------|-------|-------|
       * | E=0   | E   | S   | W   | N   | E^   | S^    | W^    | N^    |
       * | S=2   | S   | W   | N   | E   | S^   | W^    | N^    | E^    |
       * | W=4   | W   | N   | E   | S   | W^   | N^    | E^    | S^    |
       * | N=6   | N   | E   | S   | W   | N^   | E^    | S^    | W^    |
       * | E^=8  | E^  | N^  | W^  | S^  | E    | N     | W     | S     |
       * | S^=10 | S^  | E^  | N^  | W^  | S    | E     | N     | W     |
       * | W^=12 | W^  | S^  | E^  | N^  | W    | S     | E     | N     |
       * | N^=14 | N^  | W^  | S^  | E^  | N    | W     | S     | E     |
       *
       * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table}
       * @group groupD8
       * @param {GD8Symmetry} rotationSecond - Second operation, which
       *   is the row in the above cayley table.
       * @param {GD8Symmetry} rotationFirst - First operation, which
       *   is the column in the above cayley table.
       * @returns {GD8Symmetry} Composed operation
       */
      add: (rotationSecond, rotationFirst) => rotationCayley[rotationSecond][rotationFirst],
      /**
       * Reverse of `add`.
       * @group groupD8
       * @param {GD8Symmetry} rotationSecond - Second operation
       * @param {GD8Symmetry} rotationFirst - First operation
       * @returns {GD8Symmetry} Result
       */
      sub: (rotationSecond, rotationFirst) => rotationCayley[rotationSecond][groupD8.inv(rotationFirst)],
      /**
       * Adds 180 degrees to rotation, which is a commutative
       * operation.
       * @group groupD8
       * @param {number} rotation - The number to rotate.
       * @returns {number} Rotated number
       */
      rotate180: (rotation) => rotation ^ 4,
      /**
       * Checks if the rotation angle is vertical, i.e. south
       * or north. It doesn't work for reflections.
       * @group groupD8
       * @param {GD8Symmetry} rotation - The number to check.
       * @returns {boolean} Whether or not the direction is vertical
       */
      isVertical: (rotation) => (rotation & 3) === 2,
      // rotation % 4 === 2
      /**
       * Approximates the vector `V(dx,dy)` into one of the
       * eight directions provided by `groupD8`.
       * @group groupD8
       * @param {number} dx - X-component of the vector
       * @param {number} dy - Y-component of the vector
       * @returns {GD8Symmetry} Approximation of the vector into
       *  one of the eight symmetries.
       */
      byDirection: (dx, dy) => {
        if (Math.abs(dx) * 2 <= Math.abs(dy)) {
          if (dy >= 0) {
            return groupD8.S;
          }
          return groupD8.N;
        } else if (Math.abs(dy) * 2 <= Math.abs(dx)) {
          if (dx > 0) {
            return groupD8.E;
          }
          return groupD8.W;
        } else if (dy > 0) {
          if (dx > 0) {
            return groupD8.SE;
          }
          return groupD8.SW;
        } else if (dx > 0) {
          return groupD8.NE;
        }
        return groupD8.NW;
      },
      /**
       * Helps sprite to compensate texture packer rotation.
       * @group groupD8
       * @param {Matrix} matrix - sprite world matrix
       * @param {GD8Symmetry} rotation - The rotation factor to use.
       * @param {number} tx - sprite anchoring
       * @param {number} ty - sprite anchoring
       */
      matrixAppendRotationInv: (matrix, rotation, tx = 0, ty = 0) => {
        const mat = rotationMatrices[groupD8.inv(rotation)];
        mat.tx = tx;
        mat.ty = ty;
        matrix.append(mat);
      },
      /**
       * Transforms rectangle coordinates based on texture packer rotation.
       * Used when texture atlas pages are rotated and coordinates need to be adjusted.
       * @group groupD8
       * @param {RectangleLike} rect - Rectangle with original coordinates to transform
       * @param {RectangleLike} sourceFrame - Source texture frame (includes offset and dimensions)
       * @param {GD8Symmetry} rotation - The groupD8 rotation value
       * @param {Rectangle} out - Rectangle to store the result
       * @returns {Rectangle} Transformed coordinates (includes source frame offset)
       */
      transformRectCoords: (rect, sourceFrame, rotation, out) => {
        const { x, y, width, height } = rect;
        const { x: frameX, y: frameY, width: frameWidth, height: frameHeight } = sourceFrame;
        if (rotation === groupD8.E) {
          out.set(x + frameX, y + frameY, width, height);
          return out;
        } else if (rotation === groupD8.S) {
          return out.set(
            frameWidth - y - height + frameX,
            x + frameY,
            height,
            width
          );
        } else if (rotation === groupD8.W) {
          return out.set(
            frameWidth - x - width + frameX,
            frameHeight - y - height + frameY,
            width,
            height
          );
        } else if (rotation === groupD8.N) {
          return out.set(
            y + frameX,
            frameHeight - x - width + frameY,
            height,
            width
          );
        }
        return out.set(x + frameX, y + frameY, width, height);
      }
    };

    "use strict";
    const tempPoints = [new Point(), new Point(), new Point(), new Point()];
    class Rectangle {
      /**
       * @param x - The X coordinate of the upper-left corner of the rectangle
       * @param y - The Y coordinate of the upper-left corner of the rectangle
       * @param width - The overall width of the rectangle
       * @param height - The overall height of the rectangle
       */
      constructor(x = 0, y = 0, width = 0, height = 0) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks
         * @example
         * ```ts
         * // Check shape type
         * const shape = new Rectangle(0, 0, 100, 100);
         * console.log(shape.type); // 'rectangle'
         *
         * // Use in type guards
         * if (shape.type === 'rectangle') {
         *     console.log(shape.width, shape.height);
         * }
         * ```
         * @readonly
         * @default 'rectangle'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         */
        this.type = "rectangle";
        this.x = Number(x);
        this.y = Number(y);
        this.width = Number(width);
        this.height = Number(height);
      }
      /**
       * Returns the left edge (x-coordinate) of the rectangle.
       * @example
       * ```ts
       * // Get left edge position
       * const rect = new Rectangle(100, 100, 200, 150);
       * console.log(rect.left); // 100
       *
       * // Use in alignment calculations
       * sprite.x = rect.left + padding;
       *
       * // Compare positions
       * if (point.x > rect.left) {
       *     console.log('Point is right of rectangle');
       * }
       * ```
       * @readonly
       * @returns The x-coordinate of the left edge
       * @see {@link Rectangle.right} For right edge position
       * @see {@link Rectangle.x} For direct x-coordinate access
       */
      get left() {
        return this.x;
      }
      /**
       * Returns the right edge (x + width) of the rectangle.
       * @example
       * ```ts
       * // Get right edge position
       * const rect = new Rectangle(100, 100, 200, 150);
       * console.log(rect.right); // 300
       *
       * // Align to right edge
       * sprite.x = rect.right - sprite.width;
       *
       * // Check boundaries
       * if (point.x < rect.right) {
       *     console.log('Point is inside right bound');
       * }
       * ```
       * @readonly
       * @returns The x-coordinate of the right edge
       * @see {@link Rectangle.left} For left edge position
       * @see {@link Rectangle.width} For width value
       */
      get right() {
        return this.x + this.width;
      }
      /**
       * Returns the top edge (y-coordinate) of the rectangle.
       * @example
       * ```ts
       * // Get top edge position
       * const rect = new Rectangle(100, 100, 200, 150);
       * console.log(rect.top); // 100
       *
       * // Position above rectangle
       * sprite.y = rect.top - sprite.height;
       *
       * // Check vertical position
       * if (point.y > rect.top) {
       *     console.log('Point is below top edge');
       * }
       * ```
       * @readonly
       * @returns The y-coordinate of the top edge
       * @see {@link Rectangle.bottom} For bottom edge position
       * @see {@link Rectangle.y} For direct y-coordinate access
       */
      get top() {
        return this.y;
      }
      /**
       * Returns the bottom edge (y + height) of the rectangle.
       * @example
       * ```ts
       * // Get bottom edge position
       * const rect = new Rectangle(100, 100, 200, 150);
       * console.log(rect.bottom); // 250
       *
       * // Stack below rectangle
       * sprite.y = rect.bottom + margin;
       *
       * // Check vertical bounds
       * if (point.y < rect.bottom) {
       *     console.log('Point is above bottom edge');
       * }
       * ```
       * @readonly
       * @returns The y-coordinate of the bottom edge
       * @see {@link Rectangle.top} For top edge position
       * @see {@link Rectangle.height} For height value
       */
      get bottom() {
        return this.y + this.height;
      }
      /**
       * Determines whether the Rectangle is empty (has no area).
       * @example
       * ```ts
       * // Check zero dimensions
       * const rect = new Rectangle(100, 100, 0, 50);
       * console.log(rect.isEmpty()); // true
       * ```
       * @returns True if the rectangle has no area
       * @see {@link Rectangle.width} For width value
       * @see {@link Rectangle.height} For height value
       */
      isEmpty() {
        return this.left === this.right || this.top === this.bottom;
      }
      /**
       * A constant empty rectangle. This is a new object every time the property is accessed.
       * @example
       * ```ts
       * // Get fresh empty rectangle
       * const empty = Rectangle.EMPTY;
       * console.log(empty.isEmpty()); // true
       * ```
       * @returns A new empty rectangle instance
       * @see {@link Rectangle.isEmpty} For empty state testing
       */
      static get EMPTY() {
        return new Rectangle(0, 0, 0, 0);
      }
      /**
       * Creates a clone of this Rectangle
       * @example
       * ```ts
       * // Basic cloning
       * const original = new Rectangle(100, 100, 200, 150);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.width *= 2;
       * modified.height += 50;
       *
       * // Verify independence
       * console.log(original.width);  // 200
       * console.log(modified.width);  // 400
       * ```
       * @returns A copy of the rectangle
       * @see {@link Rectangle.copyFrom} For copying into existing rectangle
       * @see {@link Rectangle.copyTo} For copying to another rectangle
       */
      clone() {
        return new Rectangle(this.x, this.y, this.width, this.height);
      }
      /**
       * Converts a Bounds object to a Rectangle object.
       * @example
       * ```ts
       * // Convert bounds to rectangle
       * const bounds = container.getBounds();
       * const rect = new Rectangle().copyFromBounds(bounds);
       * ```
       * @param bounds - The bounds to copy and convert to a rectangle
       * @returns Returns itself
       * @see {@link Bounds} For bounds object structure
       * @see {@link Rectangle.getBounds} For getting rectangle bounds
       */
      copyFromBounds(bounds) {
        this.x = bounds.minX;
        this.y = bounds.minY;
        this.width = bounds.maxX - bounds.minX;
        this.height = bounds.maxY - bounds.minY;
        return this;
      }
      /**
       * Copies another rectangle to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Rectangle(100, 100, 200, 150);
       * const target = new Rectangle();
       * target.copyFrom(source);
       *
       * // Chain with other operations
       * const rect = new Rectangle()
       *     .copyFrom(source)
       *     .pad(10);
       * ```
       * @param rectangle - The rectangle to copy from
       * @returns Returns itself
       * @see {@link Rectangle.copyTo} For copying to another rectangle
       * @see {@link Rectangle.clone} For creating new rectangle copy
       */
      copyFrom(rectangle) {
        this.x = rectangle.x;
        this.y = rectangle.y;
        this.width = rectangle.width;
        this.height = rectangle.height;
        return this;
      }
      /**
       * Copies this rectangle to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Rectangle(100, 100, 200, 150);
       * const target = new Rectangle();
       * source.copyTo(target);
       *
       * // Chain with other operations
       * const result = source
       *     .copyTo(new Rectangle())
       *     .getBounds();
       * ```
       * @param rectangle - The rectangle to copy to
       * @returns Returns given parameter
       * @see {@link Rectangle.copyFrom} For copying from another rectangle
       * @see {@link Rectangle.clone} For creating new rectangle copy
       */
      copyTo(rectangle) {
        rectangle.copyFrom(this);
        return rectangle;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this Rectangle
       * @example
       * ```ts
       * // Basic containment check
       * const rect = new Rectangle(100, 100, 200, 150);
       * const isInside = rect.contains(150, 125); // true
       * // Check edge cases
       * console.log(rect.contains(100, 100)); // true (on edge)
       * console.log(rect.contains(300, 250)); // false (outside)
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coordinates are within this Rectangle
       * @see {@link Rectangle.containsRect} For rectangle containment
       * @see {@link Rectangle.strokeContains} For checking stroke intersection
       */
      contains(x, y) {
        if (this.width <= 0 || this.height <= 0) {
          return false;
        }
        if (x >= this.x && x < this.x + this.width) {
          if (y >= this.y && y < this.y + this.height) {
            return true;
          }
        }
        return false;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const rect = new Rectangle(100, 100, 200, 150);
       * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = rect.strokeContains(150, 100, 4, 1);   // Inside
       * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
       * const outerStroke = rect.strokeContains(150, 100, 4, 0);   // Outside
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @param strokeWidth - The width of the line to check
       * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
       * @returns Whether the x/y coordinates are within this rectangle's stroke
       * @see {@link Rectangle.contains} For checking fill containment
       * @see {@link Rectangle.getBounds} For getting stroke bounds
       */
      strokeContains(x, y, strokeWidth, alignment = 0.5) {
        const { width, height } = this;
        if (width <= 0 || height <= 0)
          return false;
        const _x = this.x;
        const _y = this.y;
        const strokeWidthOuter = strokeWidth * (1 - alignment);
        const strokeWidthInner = strokeWidth - strokeWidthOuter;
        const outerLeft = _x - strokeWidthOuter;
        const outerRight = _x + width + strokeWidthOuter;
        const outerTop = _y - strokeWidthOuter;
        const outerBottom = _y + height + strokeWidthOuter;
        const innerLeft = _x + strokeWidthInner;
        const innerRight = _x + width - strokeWidthInner;
        const innerTop = _y + strokeWidthInner;
        const innerBottom = _y + height - strokeWidthInner;
        return x >= outerLeft && x <= outerRight && y >= outerTop && y <= outerBottom && !(x > innerLeft && x < innerRight && y > innerTop && y < innerBottom);
      }
      /**
       * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
       * Returns true only if the area of the intersection is >0, this means that Rectangles
       * sharing a side are not overlapping. Another side effect is that an arealess rectangle
       * (width or height equal to zero) can't intersect any other rectangle.
       * @param {Rectangle} other - The Rectangle to intersect with `this`.
       * @param {Matrix} transform - The transformation matrix of `other`.
       * @returns {boolean} A value of `true` if the transformed `other` Rectangle intersects with `this`; otherwise `false`.
       */
      /**
       * Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
       *
       * Returns true only if the area of the intersection is greater than 0.
       * This means that rectangles sharing only a side are not considered intersecting.
       * @example
       * ```ts
       * // Basic intersection check
       * const rect1 = new Rectangle(0, 0, 100, 100);
       * const rect2 = new Rectangle(50, 50, 100, 100);
       * console.log(rect1.intersects(rect2)); // true
       *
       * // With transformation matrix
       * const matrix = new Matrix();
       * matrix.rotate(Math.PI / 4); // 45 degrees
       * console.log(rect1.intersects(rect2, matrix)); // Checks with rotation
       *
       * // Edge cases
       * const zeroWidth = new Rectangle(0, 0, 0, 100);
       * console.log(rect1.intersects(zeroWidth)); // false (no area)
       * ```
       * @remarks
       * - Returns true only if intersection area is > 0
       * - Rectangles sharing only a side are not intersecting
       * - Zero-area rectangles cannot intersect anything
       * - Supports optional transformation matrix
       * @param other - The Rectangle to intersect with `this`
       * @param transform - Optional transformation matrix of `other`
       * @returns True if the transformed `other` Rectangle intersects with `this`
       * @see {@link Rectangle.containsRect} For containment testing
       * @see {@link Rectangle.contains} For point testing
       */
      intersects(other, transform) {
        if (!transform) {
          const x02 = this.x < other.x ? other.x : this.x;
          const x12 = this.right > other.right ? other.right : this.right;
          if (x12 <= x02) {
            return false;
          }
          const y02 = this.y < other.y ? other.y : this.y;
          const y12 = this.bottom > other.bottom ? other.bottom : this.bottom;
          return y12 > y02;
        }
        const x0 = this.left;
        const x1 = this.right;
        const y0 = this.top;
        const y1 = this.bottom;
        if (x1 <= x0 || y1 <= y0) {
          return false;
        }
        const lt = tempPoints[0].set(other.left, other.top);
        const lb = tempPoints[1].set(other.left, other.bottom);
        const rt = tempPoints[2].set(other.right, other.top);
        const rb = tempPoints[3].set(other.right, other.bottom);
        if (rt.x <= lt.x || lb.y <= lt.y) {
          return false;
        }
        const s = Math.sign(transform.a * transform.d - transform.b * transform.c);
        if (s === 0) {
          return false;
        }
        transform.apply(lt, lt);
        transform.apply(lb, lb);
        transform.apply(rt, rt);
        transform.apply(rb, rb);
        if (Math.max(lt.x, lb.x, rt.x, rb.x) <= x0 || Math.min(lt.x, lb.x, rt.x, rb.x) >= x1 || Math.max(lt.y, lb.y, rt.y, rb.y) <= y0 || Math.min(lt.y, lb.y, rt.y, rb.y) >= y1) {
          return false;
        }
        const nx = s * (lb.y - lt.y);
        const ny = s * (lt.x - lb.x);
        const n00 = nx * x0 + ny * y0;
        const n10 = nx * x1 + ny * y0;
        const n01 = nx * x0 + ny * y1;
        const n11 = nx * x1 + ny * y1;
        if (Math.max(n00, n10, n01, n11) <= nx * lt.x + ny * lt.y || Math.min(n00, n10, n01, n11) >= nx * rb.x + ny * rb.y) {
          return false;
        }
        const mx = s * (lt.y - rt.y);
        const my = s * (rt.x - lt.x);
        const m00 = mx * x0 + my * y0;
        const m10 = mx * x1 + my * y0;
        const m01 = mx * x0 + my * y1;
        const m11 = mx * x1 + my * y1;
        if (Math.max(m00, m10, m01, m11) <= mx * lt.x + my * lt.y || Math.min(m00, m10, m01, m11) >= mx * rb.x + my * rb.y) {
          return false;
        }
        return true;
      }
      /**
       * Pads the rectangle making it grow in all directions.
       *
       * If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
       * @example
       * ```ts
       * // Basic padding
       * const rect = new Rectangle(100, 100, 200, 150);
       * rect.pad(10); // Adds 10px padding on all sides
       *
       * // Different horizontal and vertical padding
       * const uiRect = new Rectangle(0, 0, 100, 50);
       * uiRect.pad(20, 10); // 20px horizontal, 10px vertical
       * ```
       * @remarks
       * - Adjusts x/y by subtracting padding
       * - Increases width/height by padding * 2
       * - Common in UI layout calculations
       * - Chainable with other methods
       * @param paddingX - The horizontal padding amount
       * @param paddingY - The vertical padding amount
       * @returns Returns itself
       * @see {@link Rectangle.enlarge} For growing to include another rectangle
       * @see {@link Rectangle.fit} For shrinking to fit within another rectangle
       */
      pad(paddingX = 0, paddingY = paddingX) {
        this.x -= paddingX;
        this.y -= paddingY;
        this.width += paddingX * 2;
        this.height += paddingY * 2;
        return this;
      }
      /**
       * Fits this rectangle around the passed one.
       * @example
       * ```ts
       * // Basic fitting
       * const container = new Rectangle(0, 0, 100, 100);
       * const content = new Rectangle(25, 25, 200, 200);
       * content.fit(container); // Clips to container bounds
       * ```
       * @param rectangle - The rectangle to fit around
       * @returns Returns itself
       * @see {@link Rectangle.enlarge} For growing to include another rectangle
       * @see {@link Rectangle.pad} For adding padding around the rectangle
       */
      fit(rectangle) {
        const x1 = Math.max(this.x, rectangle.x);
        const x2 = Math.min(this.x + this.width, rectangle.x + rectangle.width);
        const y1 = Math.max(this.y, rectangle.y);
        const y2 = Math.min(this.y + this.height, rectangle.y + rectangle.height);
        this.x = x1;
        this.width = Math.max(x2 - x1, 0);
        this.y = y1;
        this.height = Math.max(y2 - y1, 0);
        return this;
      }
      /**
       * Enlarges rectangle so that its corners lie on a grid defined by resolution.
       * @example
       * ```ts
       * // Basic grid alignment
       * const rect = new Rectangle(10.2, 10.6, 100.8, 100.4);
       * rect.ceil(); // Aligns to whole pixels
       *
       * // Custom resolution grid
       * const uiRect = new Rectangle(5.3, 5.7, 50.2, 50.8);
       * uiRect.ceil(0.5); // Aligns to half pixels
       *
       * // Use with precision value
       * const preciseRect = new Rectangle(20.001, 20.999, 100.001, 100.999);
       * preciseRect.ceil(1, 0.01); // Handles small decimal variations
       * ```
       * @param resolution - The grid size to align to (1 = whole pixels)
       * @param eps - Small number to prevent floating point errors
       * @returns Returns itself
       * @see {@link Rectangle.fit} For constraining to bounds
       * @see {@link Rectangle.enlarge} For growing dimensions
       */
      ceil(resolution = 1, eps = 1e-3) {
        const x2 = Math.ceil((this.x + this.width - eps) * resolution) / resolution;
        const y2 = Math.ceil((this.y + this.height - eps) * resolution) / resolution;
        this.x = Math.floor((this.x + eps) * resolution) / resolution;
        this.y = Math.floor((this.y + eps) * resolution) / resolution;
        this.width = x2 - this.x;
        this.height = y2 - this.y;
        return this;
      }
      /**
       * Scales the rectangle's dimensions and position by the specified factors.
       * @example
       * ```ts
       * const rect = new Rectangle(50, 50, 100, 100);
       *
       * // Scale uniformly
       * rect.scale(0.5, 0.5);
       * // rect is now: x=25, y=25, width=50, height=50
       *
       * // non-uniformly
       * rect.scale(0.5, 1);
       * // rect is now: x=25, y=50, width=50, height=100
       * ```
       * @param x - The factor by which to scale the horizontal properties (x, width).
       * @param y - The factor by which to scale the vertical properties (y, height).
       * @returns Returns itself
       */
      scale(x, y = x) {
        this.x *= x;
        this.y *= y;
        this.width *= x;
        this.height *= y;
        return this;
      }
      /**
       * Enlarges this rectangle to include the passed rectangle.
       * @example
       * ```ts
       * // Basic enlargement
       * const rect = new Rectangle(50, 50, 100, 100);
       * const other = new Rectangle(0, 0, 200, 75);
       * rect.enlarge(other);
       * // rect is now: x=0, y=0, width=200, height=150
       *
       * // Use for bounding box calculation
       * const bounds = new Rectangle();
       * objects.forEach((obj) => {
       *     bounds.enlarge(obj.getBounds());
       * });
       * ```
       * @param rectangle - The rectangle to include
       * @returns Returns itself
       * @see {@link Rectangle.fit} For shrinking to fit within another rectangle
       * @see {@link Rectangle.pad} For adding padding around the rectangle
       */
      enlarge(rectangle) {
        const x1 = Math.min(this.x, rectangle.x);
        const x2 = Math.max(this.x + this.width, rectangle.x + rectangle.width);
        const y1 = Math.min(this.y, rectangle.y);
        const y2 = Math.max(this.y + this.height, rectangle.y + rectangle.height);
        this.x = x1;
        this.width = x2 - x1;
        this.y = y1;
        this.height = y2 - y1;
        return this;
      }
      /**
       * Returns the framing rectangle of the rectangle as a Rectangle object
       * @example
       * ```ts
       * // Basic bounds retrieval
       * const rect = new Rectangle(100, 100, 200, 150);
       * const bounds = rect.getBounds();
       *
       * // Reuse existing rectangle
       * const out = new Rectangle();
       * rect.getBounds(out);
       * ```
       * @param out - Optional rectangle to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle.copyFrom} For direct copying
       * @see {@link Rectangle.clone} For creating new copy
       */
      getBounds(out) {
        out || (out = new Rectangle());
        out.copyFrom(this);
        return out;
      }
      /**
       * Determines whether another Rectangle is fully contained within this Rectangle.
       *
       * Rectangles that occupy the same space are considered to be containing each other.
       *
       * Rectangles without area (width or height equal to zero) can't contain anything,
       * not even other arealess rectangles.
       * @example
       * ```ts
       * // Check if one rectangle contains another
       * const container = new Rectangle(0, 0, 100, 100);
       * const inner = new Rectangle(25, 25, 50, 50);
       *
       * console.log(container.containsRect(inner)); // true
       *
       * // Check overlapping rectangles
       * const partial = new Rectangle(75, 75, 50, 50);
       * console.log(container.containsRect(partial)); // false
       *
       * // Zero-area rectangles
       * const empty = new Rectangle(0, 0, 0, 100);
       * console.log(container.containsRect(empty)); // false
       * ```
       * @param other - The Rectangle to check for containment
       * @returns True if other is fully contained within this Rectangle
       * @see {@link Rectangle.contains} For point containment
       * @see {@link Rectangle.intersects} For overlap testing
       */
      containsRect(other) {
        if (this.width <= 0 || this.height <= 0)
          return false;
        const x1 = other.x;
        const y1 = other.y;
        const x2 = other.x + other.width;
        const y2 = other.y + other.height;
        return x1 >= this.x && x1 < this.x + this.width && y1 >= this.y && y1 < this.y + this.height && x2 >= this.x && x2 < this.x + this.width && y2 >= this.y && y2 < this.y + this.height;
      }
      /**
       * Sets the position and dimensions of the rectangle.
       * @example
       * ```ts
       * // Basic usage
       * const rect = new Rectangle();
       * rect.set(100, 100, 200, 150);
       *
       * // Chain with other operations
       * const bounds = new Rectangle()
       *     .set(0, 0, 100, 100)
       *     .pad(10);
       * ```
       * @param x - The X coordinate of the upper-left corner of the rectangle
       * @param y - The Y coordinate of the upper-left corner of the rectangle
       * @param width - The overall width of the rectangle
       * @param height - The overall height of the rectangle
       * @returns Returns itself for method chaining
       * @see {@link Rectangle.copyFrom} For copying from another rectangle
       * @see {@link Rectangle.clone} For creating a new copy
       */
      set(x, y, width, height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        return this;
      }
      toString() {
        return `[pixi.js/math:Rectangle x=${this.x} y=${this.y} width=${this.width} height=${this.height}]`;
      }
    }

    "use strict";
    const uidCache = {
      default: -1
    };
    function uid$1(name = "default") {
      if (uidCache[name] === void 0) {
        uidCache[name] = -1;
      }
      return ++uidCache[name];
    }
    function resetUids() {
      for (const key in uidCache) {
        delete uidCache[key];
      }
    }

    "use strict";
    const warnings = /* @__PURE__ */ new Set();
    const v8_0_0 = "8.0.0";
    const v8_3_4 = "8.3.4";
    const deprecationState = {
      quiet: false,
      noColor: false
    };
    const deprecation = (version, message, ignoreDepth = 3) => {
      if (deprecationState.quiet || warnings.has(message))
        return;
      let stack = new Error().stack;
      const deprecationMessage = `${message}
Deprecated since v${version}`;
      const useGroup = typeof console.groupCollapsed === "function" && !deprecationState.noColor;
      if (typeof stack === "undefined") {
        console.warn("PixiJS Deprecation Warning: ", deprecationMessage);
      } else {
        stack = stack.split("\n").splice(ignoreDepth).join("\n");
        if (useGroup) {
          console.groupCollapsed(
            "%cPixiJS Deprecation Warning: %c%s",
            "color:#614108;background:#fffbe6",
            "font-weight:normal;color:#614108;background:#fffbe6",
            deprecationMessage
          );
          console.warn(stack);
          console.groupEnd();
        } else {
          console.warn("PixiJS Deprecation Warning: ", deprecationMessage);
          console.warn(stack);
        }
      }
      warnings.add(message);
    };
    Object.defineProperties(deprecation, {
      quiet: {
        get: () => deprecationState.quiet,
        set: (value) => {
          deprecationState.quiet = value;
        },
        enumerable: true,
        configurable: false
      },
      noColor: {
        get: () => deprecationState.noColor,
        set: (value) => {
          deprecationState.noColor = value;
        },
        enumerable: true,
        configurable: false
      }
    });

    "use strict";
    const NOOP = () => {
    };

    "use strict";
    function nextPow2(v) {
      v += v === 0 ? 1 : 0;
      --v;
      v |= v >>> 1;
      v |= v >>> 2;
      v |= v >>> 4;
      v |= v >>> 8;
      v |= v >>> 16;
      return v + 1;
    }
    function isPow2(v) {
      return !(v & v - 1) && !!v;
    }
    function log2(v) {
      let r = (v > 65535 ? 1 : 0) << 4;
      v >>>= r;
      let shift = (v > 255 ? 1 : 0) << 3;
      v >>>= shift;
      r |= shift;
      shift = (v > 15 ? 1 : 0) << 2;
      v >>>= shift;
      r |= shift;
      shift = (v > 3 ? 1 : 0) << 1;
      v >>>= shift;
      r |= shift;
      return r | v >> 1;
    }

    "use strict";
    function definedProps(obj) {
      const result = {};
      for (const key in obj) {
        if (obj[key] !== void 0) {
          result[key] = obj[key];
        }
      }
      return result;
    }

    "use strict";
    var __defProp$1b = Object.defineProperty;
    var __getOwnPropSymbols$1d = Object.getOwnPropertySymbols;
    var __hasOwnProp$1d = Object.prototype.hasOwnProperty;
    var __propIsEnum$1d = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$1b = (obj, key, value) => key in obj ? __defProp$1b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$1b = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1d.call(b, prop))
          __defNormalProp$1b(a, prop, b[prop]);
      if (__getOwnPropSymbols$1d)
        for (var prop of __getOwnPropSymbols$1d(b)) {
          if (__propIsEnum$1d.call(b, prop))
            __defNormalProp$1b(a, prop, b[prop]);
        }
      return a;
    };
    const idHash$1 = /* @__PURE__ */ Object.create(null);
    function createResourceIdFromString(value) {
      const id = idHash$1[value];
      if (id === void 0) {
        idHash$1[value] = uid$1("resource");
      }
      return id;
    }
    const _TextureStyle = class _TextureStyle extends EventEmitter {
      /**
       * @param options - options for the style
       */
      constructor(options = {}) {
        var _a, _b, _c, _d, _e, _f, _g;
        super();
        /** @internal */
        this._resourceType = "textureSampler";
        /** @internal */
        this._touched = 0;
        /**
         * Specifies the maximum anisotropy value clamp used by the sampler.
         * Note: Most implementations support {@link TextureStyle#maxAnisotropy} values in range
         * between 1 and 16, inclusive. The used value of {@link TextureStyle#maxAnisotropy} will
         * be clamped to the maximum value that the platform supports.
         * @internal
         */
        this._maxAnisotropy = 1;
        /**
         * Has the style been destroyed?
         * @readonly
         */
        this.destroyed = false;
        options = __spreadValues$1b(__spreadValues$1b({}, _TextureStyle.defaultOptions), options);
        this.addressMode = options.addressMode;
        this.addressModeU = (_a = options.addressModeU) != null ? _a : this.addressModeU;
        this.addressModeV = (_b = options.addressModeV) != null ? _b : this.addressModeV;
        this.addressModeW = (_c = options.addressModeW) != null ? _c : this.addressModeW;
        this.scaleMode = options.scaleMode;
        this.magFilter = (_d = options.magFilter) != null ? _d : this.magFilter;
        this.minFilter = (_e = options.minFilter) != null ? _e : this.minFilter;
        this.mipmapFilter = (_f = options.mipmapFilter) != null ? _f : this.mipmapFilter;
        this.lodMinClamp = options.lodMinClamp;
        this.lodMaxClamp = options.lodMaxClamp;
        this.compare = options.compare;
        this.maxAnisotropy = (_g = options.maxAnisotropy) != null ? _g : 1;
      }
      set addressMode(value) {
        this.addressModeU = value;
        this.addressModeV = value;
        this.addressModeW = value;
      }
      /** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */
      get addressMode() {
        return this.addressModeU;
      }
      set wrapMode(value) {
        deprecation(v8_0_0, "TextureStyle.wrapMode is now TextureStyle.addressMode");
        this.addressMode = value;
      }
      get wrapMode() {
        return this.addressMode;
      }
      set scaleMode(value) {
        this.magFilter = value;
        this.minFilter = value;
        this.mipmapFilter = value;
      }
      /** setting this will set magFilter,minFilter and mipmapFilter all at once!  */
      get scaleMode() {
        return this.magFilter;
      }
      /** Specifies the maximum anisotropy value clamp used by the sampler. */
      set maxAnisotropy(value) {
        this._maxAnisotropy = Math.min(value, 16);
        if (this._maxAnisotropy > 1) {
          this.scaleMode = "linear";
        }
      }
      get maxAnisotropy() {
        return this._maxAnisotropy;
      }
      // TODO - move this to WebGL?
      get _resourceId() {
        return this._sharedResourceId || this._generateResourceId();
      }
      update() {
        this._sharedResourceId = null;
        this.emit("change", this);
      }
      _generateResourceId() {
        const bigKey = `${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`;
        this._sharedResourceId = createResourceIdFromString(bigKey);
        return this._resourceId;
      }
      /** Destroys the style */
      destroy() {
        this.destroyed = true;
        this.emit("destroy", this);
        this.emit("change", this);
        this.removeAllListeners();
      }
    };
    /** default options for the style */
    _TextureStyle.defaultOptions = {
      addressMode: "clamp-to-edge",
      scaleMode: "linear"
    };
    let TextureStyle = _TextureStyle;

    "use strict";
    var __defProp$1a = Object.defineProperty;
    var __getOwnPropSymbols$1c = Object.getOwnPropertySymbols;
    var __hasOwnProp$1c = Object.prototype.hasOwnProperty;
    var __propIsEnum$1c = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$1a = (obj, key, value) => key in obj ? __defProp$1a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$1a = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1c.call(b, prop))
          __defNormalProp$1a(a, prop, b[prop]);
      if (__getOwnPropSymbols$1c)
        for (var prop of __getOwnPropSymbols$1c(b)) {
          if (__propIsEnum$1c.call(b, prop))
            __defNormalProp$1a(a, prop, b[prop]);
        }
      return a;
    };
    const _TextureSource = class _TextureSource extends EventEmitter {
      /**
       * @param options - options for creating a new TextureSource
       */
      constructor(options = {}) {
        var _a, _b, _c;
        super();
        this.options = options;
        /** @internal */
        this._gpuData = /* @__PURE__ */ Object.create(null);
        /** @internal */
        this._gcLastUsed = -1;
        /** unique id for this Texture source */
        this.uid = uid$1("textureSource");
        /**
         * The resource type used by this TextureSource. This is used by the bind groups to determine
         * how to handle this resource.
         * @internal
         */
        this._resourceType = "textureSource";
        /**
         * i unique resource id, used by the bind group systems.
         * This can change if the texture is resized or its resource changes
         * @internal
         */
        this._resourceId = uid$1("resource");
        /**
         * this is how the backends know how to upload this texture to the GPU
         * It changes depending on the resource type. Classes that extend TextureSource
         * should override this property.
         * @internal
         */
        this.uploadMethodId = "unknown";
        /** @internal */
        this._resolution = 1;
        /** the pixel width of this texture source. This is the REAL pure number, not accounting resolution */
        this.pixelWidth = 1;
        /** the pixel height of this texture source. This is the REAL pure number, not accounting resolution */
        this.pixelHeight = 1;
        /**
         * the width of this texture source, accounting for resolution
         * eg pixelWidth 200, resolution 2, then width will be 100
         */
        this.width = 1;
        /**
         * the height of this texture source, accounting for resolution
         * eg pixelHeight 200, resolution 2, then height will be 100
         */
        this.height = 1;
        /**
         * The number of samples of a multisample texture. This is always 1 for non-multisample textures.
         * To enable multisample for a texture, set antialias to true
         * @internal
         */
        this.sampleCount = 1;
        /** The number of mip levels to generate for this texture. this is  overridden if autoGenerateMipmaps is true */
        this.mipLevelCount = 1;
        /**
         * Should we auto generate mipmaps for this texture? This will automatically generate mipmaps
         * for this texture when uploading to the GPU. Mipmapped textures take up more memory, but
         * can look better when scaled down.
         *
         * For performance reasons, it is recommended to NOT use this with RenderTextures, as they are often updated every frame.
         * If you do, make sure to call `updateMipmaps` after you update the texture.
         */
        this.autoGenerateMipmaps = false;
        /** the format that the texture data has */
        this.format = "rgba8unorm";
        /** how many dimensions does this texture have? currently v8 only supports 2d */
        this.dimension = "2d";
        /**
         * Only really affects RenderTextures.
         * Should we use antialiasing for this texture. It will look better, but may impact performance as a
         * Blit operation will be required to resolve the texture.
         */
        this.antialias = false;
        /**
         * Used by automatic texture Garbage Collection, stores last GC tick when it was bound
         * @protected
         */
        this._touched = 0;
        /**
         * Used by the batcher to build texture batches. faster to have the variable here!
         * @protected
         */
        this._batchTick = -1;
        /**
         * A temporary batch location for the texture batching. Here for performance reasons only!
         * @protected
         */
        this._textureBindLocation = -1;
        options = __spreadValues$1a(__spreadValues$1a({}, _TextureSource.defaultOptions), options);
        this.label = (_a = options.label) != null ? _a : "";
        this.resource = options.resource;
        this.autoGarbageCollect = options.autoGarbageCollect;
        this._resolution = options.resolution;
        if (options.width) {
          this.pixelWidth = options.width * this._resolution;
        } else {
          this.pixelWidth = this.resource ? (_b = this.resourceWidth) != null ? _b : 1 : 1;
        }
        if (options.height) {
          this.pixelHeight = options.height * this._resolution;
        } else {
          this.pixelHeight = this.resource ? (_c = this.resourceHeight) != null ? _c : 1 : 1;
        }
        this.width = this.pixelWidth / this._resolution;
        this.height = this.pixelHeight / this._resolution;
        this.format = options.format;
        this.dimension = options.dimensions;
        this.mipLevelCount = options.mipLevelCount;
        this.autoGenerateMipmaps = options.autoGenerateMipmaps;
        this.sampleCount = options.sampleCount;
        this.antialias = options.antialias;
        this.alphaMode = options.alphaMode;
        this.style = new TextureStyle(definedProps(options));
        this.destroyed = false;
        this._refreshPOT();
      }
      /** returns itself */
      get source() {
        return this;
      }
      /** the style of the texture */
      get style() {
        return this._style;
      }
      set style(value) {
        var _a, _b;
        if (this.style === value)
          return;
        (_a = this._style) == null ? void 0 : _a.off("change", this._onStyleChange, this);
        this._style = value;
        (_b = this._style) == null ? void 0 : _b.on("change", this._onStyleChange, this);
        this._onStyleChange();
      }
      /** Specifies the maximum anisotropy value clamp used by the sampler. */
      set maxAnisotropy(value) {
        this._style.maxAnisotropy = value;
      }
      get maxAnisotropy() {
        return this._style.maxAnisotropy;
      }
      /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */
      get addressMode() {
        return this._style.addressMode;
      }
      set addressMode(value) {
        this._style.addressMode = value;
      }
      /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */
      get repeatMode() {
        return this._style.addressMode;
      }
      set repeatMode(value) {
        this._style.addressMode = value;
      }
      /** Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel. */
      get magFilter() {
        return this._style.magFilter;
      }
      set magFilter(value) {
        this._style.magFilter = value;
      }
      /** Specifies the sampling behavior when the sample footprint is larger than one texel. */
      get minFilter() {
        return this._style.minFilter;
      }
      set minFilter(value) {
        this._style.minFilter = value;
      }
      /** Specifies behavior for sampling between mipmap levels. */
      get mipmapFilter() {
        return this._style.mipmapFilter;
      }
      set mipmapFilter(value) {
        this._style.mipmapFilter = value;
      }
      /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
      get lodMinClamp() {
        return this._style.lodMinClamp;
      }
      set lodMinClamp(value) {
        this._style.lodMinClamp = value;
      }
      /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
      get lodMaxClamp() {
        return this._style.lodMaxClamp;
      }
      set lodMaxClamp(value) {
        this._style.lodMaxClamp = value;
      }
      _onStyleChange() {
        this.emit("styleChange", this);
      }
      /** call this if you have modified the texture outside of the constructor */
      update() {
        if (this.resource) {
          const resolution = this._resolution;
          const didResize = this.resize(this.resourceWidth / resolution, this.resourceHeight / resolution);
          if (didResize)
            return;
        }
        this.emit("update", this);
      }
      /** Destroys this texture source */
      destroy() {
        this.destroyed = true;
        this.unload();
        this.emit("destroy", this);
        if (this._style) {
          this._style.destroy();
          this._style = null;
        }
        this.uploadMethodId = null;
        this.resource = null;
        this.removeAllListeners();
      }
      /**
       * This will unload the Texture source from the GPU. This will free up the GPU memory
       * As soon as it is required fore rendering, it will be re-uploaded.
       */
      unload() {
        var _a, _b;
        this._resourceId = uid$1("resource");
        this.emit("change", this);
        this.emit("unload", this);
        for (const key in this._gpuData) {
          (_b = (_a = this._gpuData[key]) == null ? void 0 : _a.destroy) == null ? void 0 : _b.call(_a);
        }
        this._gpuData = /* @__PURE__ */ Object.create(null);
      }
      /** the width of the resource. This is the REAL pure number, not accounting resolution   */
      get resourceWidth() {
        const { resource } = this;
        return resource.naturalWidth || resource.videoWidth || resource.displayWidth || resource.width;
      }
      /** the height of the resource. This is the REAL pure number, not accounting resolution */
      get resourceHeight() {
        const { resource } = this;
        return resource.naturalHeight || resource.videoHeight || resource.displayHeight || resource.height;
      }
      /**
       * the resolution of the texture. Changing this number, will not change the number of pixels in the actual texture
       * but will the size of the texture when rendered.
       *
       * changing the resolution of this texture to 2 for example will make it appear twice as small when rendered (as pixel
       * density will have increased)
       */
      get resolution() {
        return this._resolution;
      }
      set resolution(resolution) {
        if (this._resolution === resolution)
          return;
        this._resolution = resolution;
        this.width = this.pixelWidth / resolution;
        this.height = this.pixelHeight / resolution;
      }
      /**
       * Resize the texture, this is handy if you want to use the texture as a render texture
       * @param width - the new width of the texture
       * @param height - the new height of the texture
       * @param resolution - the new resolution of the texture
       * @returns - if the texture was resized
       */
      resize(width, height, resolution) {
        resolution || (resolution = this._resolution);
        width || (width = this.width);
        height || (height = this.height);
        const newPixelWidth = Math.round(width * resolution);
        const newPixelHeight = Math.round(height * resolution);
        this.width = newPixelWidth / resolution;
        this.height = newPixelHeight / resolution;
        this._resolution = resolution;
        if (this.pixelWidth === newPixelWidth && this.pixelHeight === newPixelHeight) {
          return false;
        }
        this._refreshPOT();
        this.pixelWidth = newPixelWidth;
        this.pixelHeight = newPixelHeight;
        this.emit("resize", this);
        this._resourceId = uid$1("resource");
        this.emit("change", this);
        return true;
      }
      /**
       * Lets the renderer know that this texture has been updated and its mipmaps should be re-generated.
       * This is only important for RenderTexture instances, as standard Texture instances will have their
       * mipmaps generated on upload. You should call this method after you make any change to the texture
       *
       * The reason for this is is can be quite expensive to update mipmaps for a texture. So by default,
       * We want you, the developer to specify when this action should happen.
       *
       * Generally you don't want to have mipmaps generated on Render targets that are changed every frame,
       */
      updateMipmaps() {
        if (this.autoGenerateMipmaps && this.mipLevelCount > 1) {
          this.emit("updateMipmaps", this);
        }
      }
      set wrapMode(value) {
        this._style.wrapMode = value;
      }
      get wrapMode() {
        return this._style.wrapMode;
      }
      set scaleMode(value) {
        this._style.scaleMode = value;
      }
      /** setting this will set magFilter,minFilter and mipmapFilter all at once!  */
      get scaleMode() {
        return this._style.scaleMode;
      }
      /**
       * Refresh check for isPowerOfTwo texture based on size
       * @private
       */
      _refreshPOT() {
        this.isPowerOfTwo = isPow2(this.pixelWidth) && isPow2(this.pixelHeight);
      }
      static test(_resource) {
        throw new Error("Unimplemented");
      }
    };
    /** The default options used when creating a new TextureSource. override these to add your own defaults */
    _TextureSource.defaultOptions = {
      resolution: 1,
      format: "bgra8unorm",
      alphaMode: "premultiply-alpha-on-upload",
      dimensions: "2d",
      mipLevelCount: 1,
      autoGenerateMipmaps: false,
      sampleCount: 1,
      antialias: false,
      autoGarbageCollect: false
    };
    let TextureSource = _TextureSource;

    "use strict";
    var __defProp$19 = Object.defineProperty;
    var __defProps$s = Object.defineProperties;
    var __getOwnPropDescs$s = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$1b = Object.getOwnPropertySymbols;
    var __hasOwnProp$1b = Object.prototype.hasOwnProperty;
    var __propIsEnum$1b = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$19 = (obj, key, value) => key in obj ? __defProp$19(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$19 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1b.call(b, prop))
          __defNormalProp$19(a, prop, b[prop]);
      if (__getOwnPropSymbols$1b)
        for (var prop of __getOwnPropSymbols$1b(b)) {
          if (__propIsEnum$1b.call(b, prop))
            __defNormalProp$19(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$s = (a, b) => __defProps$s(a, __getOwnPropDescs$s(b));
    class BufferImageSource extends TextureSource {
      constructor(options) {
        const buffer = options.resource || new Float32Array(options.width * options.height * 4);
        let format = options.format;
        if (!format) {
          if (buffer instanceof Float32Array) {
            format = "rgba32float";
          } else if (buffer instanceof Int32Array) {
            format = "rgba32uint";
          } else if (buffer instanceof Uint32Array) {
            format = "rgba32uint";
          } else if (buffer instanceof Int16Array) {
            format = "rgba16uint";
          } else if (buffer instanceof Uint16Array) {
            format = "rgba16uint";
          } else if (buffer instanceof Int8Array) {
            format = "bgra8unorm";
          } else {
            format = "bgra8unorm";
          }
        }
        super(__spreadProps$s(__spreadValues$19({}, options), {
          resource: buffer,
          format
        }));
        this.uploadMethodId = "buffer";
      }
      static test(resource) {
        return resource instanceof Int8Array || resource instanceof Uint8Array || resource instanceof Uint8ClampedArray || resource instanceof Int16Array || resource instanceof Uint16Array || resource instanceof Int32Array || resource instanceof Uint32Array || resource instanceof Float32Array;
      }
    }
    BufferImageSource.extension = ExtensionType.TextureSource;

    "use strict";
    const tempMat = new Matrix();
    class TextureMatrix {
      /**
       * @param texture - observed texture
       * @param clampMargin - Changes frame clamping, 0.5 by default. Use -0.5 for extra border.
       */
      constructor(texture, clampMargin) {
        this.mapCoord = new Matrix();
        this.uClampFrame = new Float32Array(4);
        this.uClampOffset = new Float32Array(2);
        this._textureID = -1;
        this._updateID = 0;
        this.clampOffset = 0;
        if (typeof clampMargin === "undefined") {
          this.clampMargin = texture.width < 10 ? 0 : 0.5;
        } else {
          this.clampMargin = clampMargin;
        }
        this.isSimple = false;
        this.texture = texture;
      }
      /** Texture property. */
      get texture() {
        return this._texture;
      }
      set texture(value) {
        var _a;
        if (this.texture === value)
          return;
        (_a = this._texture) == null ? void 0 : _a.removeListener("update", this.update, this);
        this._texture = value;
        this._texture.addListener("update", this.update, this);
        this.update();
      }
      /**
       * Multiplies uvs array to transform
       * @param uvs - mesh uvs
       * @param [out=uvs] - output
       * @returns - output
       */
      multiplyUvs(uvs, out) {
        if (out === void 0) {
          out = uvs;
        }
        const mat = this.mapCoord;
        for (let i = 0; i < uvs.length; i += 2) {
          const x = uvs[i];
          const y = uvs[i + 1];
          out[i] = x * mat.a + y * mat.c + mat.tx;
          out[i + 1] = x * mat.b + y * mat.d + mat.ty;
        }
        return out;
      }
      /**
       * Updates matrices if texture was changed
       * @returns - whether or not it was updated
       */
      update() {
        const tex = this._texture;
        this._updateID++;
        const uvs = tex.uvs;
        this.mapCoord.set(uvs.x1 - uvs.x0, uvs.y1 - uvs.y0, uvs.x3 - uvs.x0, uvs.y3 - uvs.y0, uvs.x0, uvs.y0);
        const orig = tex.orig;
        const trim = tex.trim;
        if (trim) {
          tempMat.set(
            orig.width / trim.width,
            0,
            0,
            orig.height / trim.height,
            -trim.x / trim.width,
            -trim.y / trim.height
          );
          this.mapCoord.append(tempMat);
        }
        const texBase = tex.source;
        const frame = this.uClampFrame;
        const margin = this.clampMargin / texBase._resolution;
        const offset = this.clampOffset / texBase._resolution;
        frame[0] = (tex.frame.x + margin + offset) / texBase.width;
        frame[1] = (tex.frame.y + margin + offset) / texBase.height;
        frame[2] = (tex.frame.x + tex.frame.width - margin + offset) / texBase.width;
        frame[3] = (tex.frame.y + tex.frame.height - margin + offset) / texBase.height;
        this.uClampOffset[0] = this.clampOffset / texBase.pixelWidth;
        this.uClampOffset[1] = this.clampOffset / texBase.pixelHeight;
        this.isSimple = tex.frame.width === texBase.width && tex.frame.height === texBase.height && tex.rotate === 0;
        return true;
      }
    }

    "use strict";
    class Texture extends EventEmitter {
      /**
       * @param {TextureOptions} options - Options for the texture
       */
      constructor({
        source,
        label,
        frame,
        orig,
        trim,
        defaultAnchor,
        defaultBorders,
        rotate,
        dynamic
      } = {}) {
        var _a;
        super();
        /** unique id for this texture */
        this.uid = uid$1("texture");
        /** A uvs object based on the given frame and the texture source */
        this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 };
        /**
         * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
         * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
         */
        this.frame = new Rectangle();
        /**
         * Does this Texture have any frame data assigned to it?
         *
         * This mode is enabled automatically if no frame was passed inside constructor.
         *
         * In this mode texture is subscribed to baseTexture events, and fires `update` on any change.
         *
         * Beware, after loading or resize of baseTexture event can fired two times!
         * If you want more control, subscribe on baseTexture itself.
         * @example
         * texture.on('update', () => {});
         */
        this.noFrame = false;
        /**
         * Set to true if you plan on modifying the uvs of this texture.
         * When this is the case, sprites and other objects using the texture will
         * make sure to listen for changes to the uvs and update their vertices accordingly.
         */
        this.dynamic = false;
        /** is it a texture? yes! used for type checking */
        this.isTexture = true;
        this.label = label;
        this.source = (_a = source == null ? void 0 : source.source) != null ? _a : new TextureSource();
        this.noFrame = !frame;
        if (frame) {
          this.frame.copyFrom(frame);
        } else {
          const { width, height } = this._source;
          this.frame.width = width;
          this.frame.height = height;
        }
        this.orig = orig || this.frame;
        this.trim = trim;
        this.rotate = rotate != null ? rotate : 0;
        this.defaultAnchor = defaultAnchor;
        this.defaultBorders = defaultBorders;
        this.destroyed = false;
        this.dynamic = dynamic || false;
        this.updateUvs();
      }
      set source(value) {
        if (this._source) {
          this._source.off("resize", this.update, this);
        }
        this._source = value;
        value.on("resize", this.update, this);
        this.emit("update", this);
      }
      /** the underlying source of the texture (equivalent of baseTexture in v7) */
      get source() {
        return this._source;
      }
      /** returns a TextureMatrix instance for this texture. By default, that object is not created because its heavy. */
      get textureMatrix() {
        if (!this._textureMatrix) {
          this._textureMatrix = new TextureMatrix(this);
        }
        return this._textureMatrix;
      }
      /** The width of the Texture in pixels. */
      get width() {
        return this.orig.width;
      }
      /** The height of the Texture in pixels. */
      get height() {
        return this.orig.height;
      }
      /** Call this function when you have modified the frame of this texture. */
      updateUvs() {
        const { uvs, frame } = this;
        const { width, height } = this._source;
        const nX = frame.x / width;
        const nY = frame.y / height;
        const nW = frame.width / width;
        const nH = frame.height / height;
        let rotate = this.rotate;
        if (rotate) {
          const w2 = nW / 2;
          const h2 = nH / 2;
          const cX = nX + w2;
          const cY = nY + h2;
          rotate = groupD8.add(rotate, groupD8.NW);
          uvs.x0 = cX + w2 * groupD8.uX(rotate);
          uvs.y0 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          uvs.x1 = cX + w2 * groupD8.uX(rotate);
          uvs.y1 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          uvs.x2 = cX + w2 * groupD8.uX(rotate);
          uvs.y2 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          uvs.x3 = cX + w2 * groupD8.uX(rotate);
          uvs.y3 = cY + h2 * groupD8.uY(rotate);
        } else {
          uvs.x0 = nX;
          uvs.y0 = nY;
          uvs.x1 = nX + nW;
          uvs.y1 = nY;
          uvs.x2 = nX + nW;
          uvs.y2 = nY + nH;
          uvs.x3 = nX;
          uvs.y3 = nY + nH;
        }
      }
      /**
       * Destroys this texture
       * @param destroySource - Destroy the source when the texture is destroyed.
       */
      destroy(destroySource = false) {
        if (this._source) {
          this._source.off("resize", this.update, this);
          if (destroySource) {
            this._source.destroy();
            this._source = null;
          }
        }
        this._textureMatrix = null;
        this.destroyed = true;
        this.emit("destroy", this);
        this.removeAllListeners();
      }
      /**
       * Call this if you have modified the `texture outside` of the constructor.
       *
       * If you have modified this texture's source, you must separately call `texture.source.update()` to see those changes.
       */
      update() {
        if (this.noFrame) {
          this.frame.width = this._source.width;
          this.frame.height = this._source.height;
        }
        this.updateUvs();
        this.emit("update", this);
      }
      /** @deprecated since 8.0.0 */
      get baseTexture() {
        deprecation(v8_0_0, "Texture.baseTexture is now Texture.source");
        return this._source;
      }
    }
    Texture.EMPTY = new Texture({
      label: "EMPTY",
      source: new TextureSource({
        label: "EMPTY"
      })
    });
    Texture.EMPTY.destroy = NOOP;
    Texture.WHITE = new Texture({
      source: new BufferImageSource({
        resource: new Uint8Array([255, 255, 255, 255]),
        width: 1,
        height: 1,
        alphaMode: "premultiply-alpha-on-upload",
        label: "WHITE"
      }),
      label: "WHITE"
    });
    Texture.WHITE.destroy = NOOP;

    "use strict";
    const _Spritesheet = class _Spritesheet {
      constructor(optionsOrTexture, arg1) {
        /** For multi-packed spritesheets, this contains a reference to all the other spritesheets it depends on. */
        this.linkedSheets = [];
        let options = optionsOrTexture;
        if ((optionsOrTexture == null ? void 0 : optionsOrTexture.source) instanceof TextureSource) {
          options = {
            texture: optionsOrTexture,
            data: arg1
          };
        }
        const { texture, data, cachePrefix = "" } = options;
        this.cachePrefix = cachePrefix;
        this._texture = texture instanceof Texture ? texture : null;
        this.textureSource = texture.source;
        this.textures = {};
        this.animations = {};
        this.data = data;
        const metaResolution = parseFloat(data.meta.scale);
        if (metaResolution) {
          this.resolution = metaResolution;
          texture.source.resolution = this.resolution;
        } else {
          this.resolution = texture.source._resolution;
        }
        this._frames = this.data.frames;
        this._frameKeys = Object.keys(this._frames);
        this._batchIndex = 0;
        this._callback = null;
      }
      /**
       * Parser spritesheet from loaded data. This is done asynchronously
       * to prevent creating too many Texture within a single process.
       */
      parse() {
        return new Promise((resolve) => {
          this._callback = resolve;
          this._batchIndex = 0;
          if (this._frameKeys.length <= _Spritesheet.BATCH_SIZE) {
            this._processFrames(0);
            this._processAnimations();
            this._parseComplete();
          } else {
            this._nextBatch();
          }
        });
      }
      /**
       * Process a batch of frames
       * @param initialFrameIndex - The index of frame to start.
       */
      _processFrames(initialFrameIndex) {
        let frameIndex = initialFrameIndex;
        const maxFrames = _Spritesheet.BATCH_SIZE;
        while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) {
          const i = this._frameKeys[frameIndex];
          const data = this._frames[i];
          const rect = data.frame;
          if (rect) {
            let frame = null;
            let trim = null;
            const sourceSize = data.trimmed !== false && data.sourceSize ? data.sourceSize : data.frame;
            const orig = new Rectangle(
              0,
              0,
              Math.floor(sourceSize.w) / this.resolution,
              Math.floor(sourceSize.h) / this.resolution
            );
            if (data.rotated) {
              frame = new Rectangle(
                Math.floor(rect.x) / this.resolution,
                Math.floor(rect.y) / this.resolution,
                Math.floor(rect.h) / this.resolution,
                Math.floor(rect.w) / this.resolution
              );
            } else {
              frame = new Rectangle(
                Math.floor(rect.x) / this.resolution,
                Math.floor(rect.y) / this.resolution,
                Math.floor(rect.w) / this.resolution,
                Math.floor(rect.h) / this.resolution
              );
            }
            if (data.trimmed !== false && data.spriteSourceSize) {
              trim = new Rectangle(
                Math.floor(data.spriteSourceSize.x) / this.resolution,
                Math.floor(data.spriteSourceSize.y) / this.resolution,
                Math.floor(rect.w) / this.resolution,
                Math.floor(rect.h) / this.resolution
              );
            }
            this.textures[i] = new Texture({
              source: this.textureSource,
              frame,
              orig,
              trim,
              rotate: data.rotated ? 2 : 0,
              defaultAnchor: data.anchor,
              defaultBorders: data.borders,
              label: i.toString()
            });
          }
          frameIndex++;
        }
      }
      /** Parse animations config. */
      _processAnimations() {
        const animations = this.data.animations || {};
        for (const animName in animations) {
          this.animations[animName] = [];
          for (let i = 0; i < animations[animName].length; i++) {
            const frameName = animations[animName][i];
            this.animations[animName].push(this.textures[frameName]);
          }
        }
      }
      /** The parse has completed. */
      _parseComplete() {
        const callback = this._callback;
        this._callback = null;
        this._batchIndex = 0;
        callback.call(this, this.textures);
      }
      /** Begin the next batch of textures. */
      _nextBatch() {
        this._processFrames(this._batchIndex * _Spritesheet.BATCH_SIZE);
        this._batchIndex++;
        setTimeout(() => {
          if (this._batchIndex * _Spritesheet.BATCH_SIZE < this._frameKeys.length) {
            this._nextBatch();
          } else {
            this._processAnimations();
            this._parseComplete();
          }
        }, 0);
      }
      /**
       * Destroy Spritesheet and don't use after this.
       * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well
       */
      destroy(destroyBase = false) {
        var _a;
        for (const i in this.textures) {
          this.textures[i].destroy();
        }
        this._frames = null;
        this._frameKeys = null;
        this.data = null;
        this.textures = null;
        if (destroyBase) {
          (_a = this._texture) == null ? void 0 : _a.destroy();
          this.textureSource.destroy();
        }
        this._texture = null;
        this.textureSource = null;
        this.linkedSheets = [];
      }
    };
    /**
     * The maximum number of Textures to build per process.
     * @advanced
     */
    _Spritesheet.BATCH_SIZE = 1e3;
    let Spritesheet = _Spritesheet;

    "use strict";
    const validImages = [
      "jpg",
      "png",
      "jpeg",
      "avif",
      "webp",
      "basis",
      "etc2",
      "bc7",
      "bc6h",
      "bc5",
      "bc4",
      "bc3",
      "bc2",
      "bc1",
      "eac",
      "astc"
    ];
    function getCacheableAssets(keys, asset, ignoreMultiPack) {
      const out = {};
      keys.forEach((key) => {
        out[key] = asset;
      });
      Object.keys(asset.textures).forEach((key) => {
        out[`${asset.cachePrefix}${key}`] = asset.textures[key];
      });
      if (!ignoreMultiPack) {
        const basePath = path.dirname(keys[0]);
        asset.linkedSheets.forEach((item, i) => {
          const out2 = getCacheableAssets([`${basePath}/${asset.data.meta.related_multi_packs[i]}`], item, true);
          Object.assign(out, out2);
        });
      }
      return out;
    }
    const spritesheetAsset = {
      extension: ExtensionType.Asset,
      /** Handle the caching of the related Spritesheet Textures */
      cache: {
        test: (asset) => asset instanceof Spritesheet,
        getCacheableAssets: (keys, asset) => getCacheableAssets(keys, asset, false)
      },
      /** Resolve the resolution of the asset. */
      resolver: {
        extension: {
          type: ExtensionType.ResolveParser,
          name: "resolveSpritesheet"
        },
        test: (value) => {
          const tempURL = value.split("?")[0];
          const split = tempURL.split(".");
          const extension = split.pop();
          const format = split.pop();
          return extension === "json" && validImages.includes(format);
        },
        parse: (value) => {
          var _a, _b;
          const split = value.split(".");
          return {
            resolution: parseFloat((_b = (_a = Resolver.RETINA_PREFIX.exec(value)) == null ? void 0 : _a[1]) != null ? _b : "1"),
            format: split[split.length - 2],
            src: value
          };
        }
      },
      /**
       * Loader plugin that parses sprite sheets!
       * once the JSON has been loaded this checks to see if the JSON is spritesheet data.
       * If it is, we load the spritesheets image and parse the data into Spritesheet
       * All textures in the sprite sheet are then added to the cache
       */
      loader: {
        /** used for deprecation purposes */
        name: "spritesheetLoader",
        id: "spritesheet",
        extension: {
          type: ExtensionType.LoadParser,
          priority: LoaderParserPriority.Normal,
          name: "spritesheetLoader"
        },
        async testParse(asset, options) {
          return path.extname(options.src).toLowerCase() === ".json" && !!asset.frames;
        },
        async parse(asset, options, loader) {
          var _a, _b, _c;
          const {
            texture: imageTexture,
            // if user need to use preloaded texture
            imageFilename,
            // if user need to use custom filename (not from jsonFile.meta.image)
            textureOptions,
            // if user need to set texture options on texture
            cachePrefix
            // if user need to use custom cache prefix
          } = (_a = options == null ? void 0 : options.data) != null ? _a : {};
          let basePath = path.dirname(options.src);
          if (basePath && basePath.lastIndexOf("/") !== basePath.length - 1) {
            basePath += "/";
          }
          let texture;
          if (imageTexture instanceof Texture) {
            texture = imageTexture;
          } else {
            const imagePath = copySearchParams(basePath + (imageFilename != null ? imageFilename : asset.meta.image), options.src);
            const assets = await loader.load([{ src: imagePath, data: textureOptions }]);
            texture = assets[imagePath];
          }
          const spritesheet = new Spritesheet({
            texture: texture.source,
            data: asset,
            cachePrefix
          });
          await spritesheet.parse();
          const multiPacks = (_b = asset == null ? void 0 : asset.meta) == null ? void 0 : _b.related_multi_packs;
          if (Array.isArray(multiPacks)) {
            const promises = [];
            for (const item of multiPacks) {
              if (typeof item !== "string") {
                continue;
              }
              let itemUrl = basePath + item;
              if ((_c = options.data) == null ? void 0 : _c.ignoreMultiPack) {
                continue;
              }
              itemUrl = copySearchParams(itemUrl, options.src);
              promises.push(loader.load({
                src: itemUrl,
                data: {
                  textureOptions,
                  ignoreMultiPack: true
                }
              }));
            }
            const res = await Promise.all(promises);
            spritesheet.linkedSheets = res;
            res.forEach((item) => {
              item.linkedSheets = [spritesheet].concat(spritesheet.linkedSheets.filter((sp) => sp !== item));
            });
          }
          return spritesheet;
        },
        async unload(spritesheet, _resolvedAsset, loader) {
          await loader.unload(spritesheet.textureSource._sourceOrigin);
          spritesheet.destroy(false);
        }
      }
    };

    "use strict";
    extensions.add(spritesheetAsset);

    "use strict";
    class ObservablePoint {
      /**
       * Creates a new `ObservablePoint`
       * @param observer - Observer to pass to listen for change events.
       * @param {number} [x=0] - position of the point on the x axis
       * @param {number} [y=0] - position of the point on the y axis
       */
      constructor(observer, x, y) {
        this._x = x || 0;
        this._y = y || 0;
        this._observer = observer;
      }
      /**
       * Creates a clone of this point.
       * @example
       * ```ts
       * // Basic cloning
       * const point = new ObservablePoint(observer, 100, 200);
       * const copy = point.clone();
       *
       * // Clone with new observer
       * const newObserver = {
       *     _onUpdate: (p) => console.log(`Clone updated: (${p.x}, ${p.y})`)
       * };
       * const watched = point.clone(newObserver);
       *
       * // Verify independence
       * watched.set(300, 400); // Only triggers new observer
       * ```
       * @param observer - Optional observer to pass to the new observable point
       * @returns A copy of this observable point
       * @see {@link ObservablePoint.copyFrom} For copying into existing point
       * @see {@link Observer} For observer interface details
       */
      clone(observer) {
        return new ObservablePoint(observer != null ? observer : this._observer, this._x, this._y);
      }
      /**
       * Sets the point to a new x and y position.
       *
       * If y is omitted, both x and y will be set to x.
       * @example
       * ```ts
       * // Basic position setting
       * const point = new ObservablePoint(observer);
       * point.set(100, 200);
       *
       * // Set both x and y to same value
       * point.set(50); // x=50, y=50
       * ```
       * @param x - Position on the x axis
       * @param y - Position on the y axis, defaults to x
       * @returns The point instance itself
       * @see {@link ObservablePoint.copyFrom} For copying from another point
       * @see {@link ObservablePoint.equals} For comparing positions
       */
      set(x = 0, y = x) {
        if (this._x !== x || this._y !== y) {
          this._x = x;
          this._y = y;
          this._observer._onUpdate(this);
        }
        return this;
      }
      /**
       * Copies x and y from the given point into this point.
       * @example
       * ```ts
       * // Basic copying
       * const source = new ObservablePoint(observer, 100, 200);
       * const target = new ObservablePoint();
       * target.copyFrom(source);
       *
       * // Copy and chain operations
       * const point = new ObservablePoint()
       *     .copyFrom(source)
       *     .set(x + 50, y + 50);
       *
       * // Copy from any PointData
       * const data = { x: 10, y: 20 };
       * point.copyFrom(data);
       * ```
       * @param p - The point to copy from
       * @returns The point instance itself
       * @see {@link ObservablePoint.copyTo} For copying to another point
       * @see {@link ObservablePoint.clone} For creating new point copy
       */
      copyFrom(p) {
        if (this._x !== p.x || this._y !== p.y) {
          this._x = p.x;
          this._y = p.y;
          this._observer._onUpdate(this);
        }
        return this;
      }
      /**
       * Copies this point's x and y into the given point.
       * @example
       * ```ts
       * // Basic copying
       * const source = new ObservablePoint(100, 200);
       * const target = new ObservablePoint();
       * source.copyTo(target);
       * ```
       * @param p - The point to copy to. Can be any type that is or extends `PointLike`
       * @returns The point (`p`) with values updated
       * @see {@link ObservablePoint.copyFrom} For copying from another point
       * @see {@link ObservablePoint.clone} For creating new point copy
       */
      copyTo(p) {
        p.set(this._x, this._y);
        return p;
      }
      /**
       * Checks if another point is equal to this point.
       *
       * Compares x and y values using strict equality.
       * @example
       * ```ts
       * // Basic equality check
       * const p1 = new ObservablePoint(100, 200);
       * const p2 = new ObservablePoint(100, 200);
       * console.log(p1.equals(p2)); // true
       *
       * // Compare with PointData
       * const data = { x: 100, y: 200 };
       * console.log(p1.equals(data)); // true
       *
       * // Check different points
       * const p3 = new ObservablePoint(200, 300);
       * console.log(p1.equals(p3)); // false
       * ```
       * @param p - The point to check
       * @returns `true` if both `x` and `y` are equal
       * @see {@link ObservablePoint.copyFrom} For making points equal
       * @see {@link PointData} For point data interface
       */
      equals(p) {
        return p.x === this._x && p.y === this._y;
      }
      toString() {
        return `[pixi.js/math:ObservablePoint x=${this._x} y=${this._y} scope=${this._observer}]`;
      }
      /**
       * Position of the observable point on the x axis.
       * Triggers observer callback when value changes.
       * @example
       * ```ts
       * // Basic x position
       * const point = new ObservablePoint(observer);
       * point.x = 100; // Triggers observer
       *
       * // Use in calculations
       * const width = rightPoint.x - leftPoint.x;
       * ```
       * @default 0
       */
      get x() {
        return this._x;
      }
      set x(value) {
        if (this._x !== value) {
          this._x = value;
          this._observer._onUpdate(this);
        }
      }
      /**
       * Position of the observable point on the y axis.
       * Triggers observer callback when value changes.
       * @example
       * ```ts
       * // Basic y position
       * const point = new ObservablePoint(observer);
       * point.y = 200; // Triggers observer
       *
       * // Use in calculations
       * const height = bottomPoint.y - topPoint.y;
       * ```
       * @default 0
       */
      get y() {
        return this._y;
      }
      set y(value) {
        if (this._y !== value) {
          this._y = value;
          this._observer._onUpdate(this);
        }
      }
    }

    "use strict";
    function updateQuadBounds(bounds, anchor, texture) {
      const { width, height } = texture.orig;
      const trim = texture.trim;
      if (trim) {
        const sourceWidth = trim.width;
        const sourceHeight = trim.height;
        bounds.minX = trim.x - anchor._x * width;
        bounds.maxX = bounds.minX + sourceWidth;
        bounds.minY = trim.y - anchor._y * height;
        bounds.maxY = bounds.minY + sourceHeight;
      } else {
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
    }

    "use strict";
    const defaultMatrix = new Matrix();
    class Bounds {
      /**
       * Creates a new Bounds object.
       * @param minX - The minimum X coordinate of the bounds.
       * @param minY - The minimum Y coordinate of the bounds.
       * @param maxX - The maximum X coordinate of the bounds.
       * @param maxY - The maximum Y coordinate of the bounds.
       */
      constructor(minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity) {
        /**
         * The minimum X coordinate of the bounds.
         * Represents the leftmost edge of the bounding box.
         * @example
         * ```ts
         * const bounds = new Bounds();
         * // Set left edge
         * bounds.minX = 100;
         * ```
         * @default Infinity
         */
        this.minX = Infinity;
        /**
         * The minimum Y coordinate of the bounds.
         * Represents the topmost edge of the bounding box.
         * @example
         * ```ts
         * const bounds = new Bounds();
         * // Set top edge
         * bounds.minY = 100;
         * ```
         * @default Infinity
         */
        this.minY = Infinity;
        /**
         * The maximum X coordinate of the bounds.
         * Represents the rightmost edge of the bounding box.
         * @example
         * ```ts
         * const bounds = new Bounds();
         * // Set right edge
         * bounds.maxX = 200;
         * // Get width
         * const width = bounds.maxX - bounds.minX;
         * ```
         * @default -Infinity
         */
        this.maxX = -Infinity;
        /**
         * The maximum Y coordinate of the bounds.
         * Represents the bottommost edge of the bounding box.
         * @example
         * ```ts
         * const bounds = new Bounds();
         * // Set bottom edge
         * bounds.maxY = 200;
         * // Get height
         * const height = bounds.maxY - bounds.minY;
         * ```
         * @default -Infinity
         */
        this.maxY = -Infinity;
        /**
         * The transformation matrix applied to this bounds object.
         * Used when calculating bounds with transforms.
         * @example
         * ```ts
         * const bounds = new Bounds();
         *
         * // Apply translation matrix
         * bounds.matrix = new Matrix()
         *     .translate(100, 100);
         *
         * // Combine transformations
         * bounds.matrix = new Matrix()
         *     .translate(50, 50)
         *     .rotate(Math.PI / 4)
         *     .scale(2, 2);
         *
         * // Use in bounds calculations
         * bounds.addFrame(0, 0, 100, 100); // Uses current matrix
         * bounds.addFrame(0, 0, 100, 100, customMatrix); // Override matrix
         * ```
         * @advanced
         */
        this.matrix = defaultMatrix;
        this.minX = minX;
        this.minY = minY;
        this.maxX = maxX;
        this.maxY = maxY;
      }
      /**
       * Checks if bounds are empty, meaning either width or height is zero or negative.
       * Empty bounds occur when min values exceed max values on either axis.
       * @example
       * ```ts
       * const bounds = new Bounds();
       *
       * // Check if newly created bounds are empty
       * console.log(bounds.isEmpty()); // true, default bounds are empty
       *
       * // Add frame and check again
       * bounds.addFrame(0, 0, 100, 100);
       * console.log(bounds.isEmpty()); // false, bounds now have area
       *
       * // Clear bounds
       * bounds.clear();
       * console.log(bounds.isEmpty()); // true, bounds are empty again
       * ```
       * @returns True if bounds are empty (have no area)
       * @see {@link Bounds#clear} For resetting bounds
       * @see {@link Bounds#isValid} For checking validity
       */
      isEmpty() {
        return this.minX > this.maxX || this.minY > this.maxY;
      }
      /**
       * The bounding rectangle representation of these bounds.
       * Lazily creates and updates a Rectangle instance based on the current bounds.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       *
       * // Get rectangle representation
       * const rect = bounds.rectangle;
       * console.log(rect.x, rect.y, rect.width, rect.height);
       *
       * // Use for hit testing
       * if (bounds.rectangle.contains(mouseX, mouseY)) {
       *     console.log('Mouse is inside bounds!');
       * }
       * ```
       * @see {@link Rectangle} For rectangle methods
       * @see {@link Bounds.isEmpty} For bounds validation
       */
      get rectangle() {
        if (!this._rectangle) {
          this._rectangle = new Rectangle();
        }
        const rectangle = this._rectangle;
        if (this.minX > this.maxX || this.minY > this.maxY) {
          rectangle.x = 0;
          rectangle.y = 0;
          rectangle.width = 0;
          rectangle.height = 0;
        } else {
          rectangle.copyFromBounds(this);
        }
        return rectangle;
      }
      /**
       * Clears the bounds and resets all coordinates to their default values.
       * Resets the transformation matrix back to identity.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * console.log(bounds.isEmpty()); // false
       * // Clear the bounds
       * bounds.clear();
       * console.log(bounds.isEmpty()); // true
       * ```
       * @returns This bounds object for chaining
       */
      clear() {
        this.minX = Infinity;
        this.minY = Infinity;
        this.maxX = -Infinity;
        this.maxY = -Infinity;
        this.matrix = defaultMatrix;
        return this;
      }
      /**
       * Sets the bounds directly using coordinate values.
       * Provides a way to set all bounds values at once.
       * @example
       * ```ts
       * const bounds = new Bounds();
       * bounds.set(0, 0, 100, 100);
       * ```
       * @param x0 - Left X coordinate of frame
       * @param y0 - Top Y coordinate of frame
       * @param x1 - Right X coordinate of frame
       * @param y1 - Bottom Y coordinate of frame
       * @see {@link Bounds#addFrame} For matrix-aware bounds setting
       * @see {@link Bounds#clear} For resetting bounds
       */
      set(x0, y0, x1, y1) {
        this.minX = x0;
        this.minY = y0;
        this.maxX = x1;
        this.maxY = y1;
      }
      /**
       * Adds a rectangular frame to the bounds, optionally transformed by a matrix.
       * Updates the bounds to encompass the new frame coordinates.
       * @example
       * ```ts
       * const bounds = new Bounds();
       * bounds.addFrame(0, 0, 100, 100);
       *
       * // Add transformed frame
       * const matrix = new Matrix()
       *     .translate(50, 50)
       *     .rotate(Math.PI / 4);
       * bounds.addFrame(0, 0, 100, 100, matrix);
       * ```
       * @param x0 - Left X coordinate of frame
       * @param y0 - Top Y coordinate of frame
       * @param x1 - Right X coordinate of frame
       * @param y1 - Bottom Y coordinate of frame
       * @param matrix - Optional transformation matrix
       * @see {@link Bounds#addRect} For adding Rectangle objects
       * @see {@link Bounds#addBounds} For adding other Bounds
       */
      addFrame(x0, y0, x1, y1, matrix) {
        matrix || (matrix = this.matrix);
        const a = matrix.a;
        const b = matrix.b;
        const c = matrix.c;
        const d = matrix.d;
        const tx = matrix.tx;
        const ty = matrix.ty;
        let minX = this.minX;
        let minY = this.minY;
        let maxX = this.maxX;
        let maxY = this.maxY;
        let x = a * x0 + c * y0 + tx;
        let y = b * x0 + d * y0 + ty;
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        x = a * x1 + c * y0 + tx;
        y = b * x1 + d * y0 + ty;
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        x = a * x0 + c * y1 + tx;
        y = b * x0 + d * y1 + ty;
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        x = a * x1 + c * y1 + tx;
        y = b * x1 + d * y1 + ty;
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        this.minX = minX;
        this.minY = minY;
        this.maxX = maxX;
        this.maxY = maxY;
      }
      /**
       * Adds a rectangle to the bounds, optionally transformed by a matrix.
       * Updates the bounds to encompass the given rectangle.
       * @example
       * ```ts
       * const bounds = new Bounds();
       * // Add simple rectangle
       * const rect = new Rectangle(0, 0, 100, 100);
       * bounds.addRect(rect);
       *
       * // Add transformed rectangle
       * const matrix = new Matrix()
       *     .translate(50, 50)
       *     .rotate(Math.PI / 4);
       * bounds.addRect(rect, matrix);
       * ```
       * @param rect - The rectangle to be added
       * @param matrix - Optional transformation matrix
       * @see {@link Bounds#addFrame} For adding raw coordinates
       * @see {@link Bounds#addBounds} For adding other bounds
       */
      addRect(rect, matrix) {
        this.addFrame(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, matrix);
      }
      /**
       * Adds another bounds object to this one, optionally transformed by a matrix.
       * Expands the bounds to include the given bounds' area.
       * @example
       * ```ts
       * const bounds = new Bounds();
       *
       * // Add child bounds
       * const childBounds = sprite.getBounds();
       * bounds.addBounds(childBounds);
       *
       * // Add transformed bounds
       * const matrix = new Matrix()
       *     .scale(2, 2);
       * bounds.addBounds(childBounds, matrix);
       * ```
       * @param bounds - The bounds to be added
       * @param matrix - Optional transformation matrix
       * @see {@link Bounds#addFrame} For adding raw coordinates
       * @see {@link Bounds#addRect} For adding rectangles
       */
      addBounds(bounds, matrix) {
        this.addFrame(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, matrix);
      }
      /**
       * Adds other Bounds as a mask, creating an intersection of the two bounds.
       * Only keeps the overlapping region between current bounds and mask bounds.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Create mask bounds
       * const mask = new Bounds();
       * mask.addFrame(50, 50, 150, 150);
       * // Apply mask - results in bounds of (50,50,100,100)
       * bounds.addBoundsMask(mask);
       * ```
       * @param mask - The Bounds to use as a mask
       * @see {@link Bounds#addBounds} For union operation
       * @see {@link Bounds#fit} For fitting to rectangle
       */
      addBoundsMask(mask) {
        this.minX = this.minX > mask.minX ? this.minX : mask.minX;
        this.minY = this.minY > mask.minY ? this.minY : mask.minY;
        this.maxX = this.maxX < mask.maxX ? this.maxX : mask.maxX;
        this.maxY = this.maxY < mask.maxY ? this.maxY : mask.maxY;
      }
      /**
       * Applies a transformation matrix to the bounds, updating its coordinates.
       * Transforms all corners of the bounds using the given matrix.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Apply translation
       * const translateMatrix = new Matrix()
       *     .translate(50, 50);
       * bounds.applyMatrix(translateMatrix);
       * ```
       * @param matrix - The matrix to apply to the bounds
       * @see {@link Matrix} For matrix operations
       * @see {@link Bounds#addFrame} For adding transformed frames
       */
      applyMatrix(matrix) {
        const minX = this.minX;
        const minY = this.minY;
        const maxX = this.maxX;
        const maxY = this.maxY;
        const { a, b, c, d, tx, ty } = matrix;
        let x = a * minX + c * minY + tx;
        let y = b * minX + d * minY + ty;
        this.minX = x;
        this.minY = y;
        this.maxX = x;
        this.maxY = y;
        x = a * maxX + c * minY + tx;
        y = b * maxX + d * minY + ty;
        this.minX = x < this.minX ? x : this.minX;
        this.minY = y < this.minY ? y : this.minY;
        this.maxX = x > this.maxX ? x : this.maxX;
        this.maxY = y > this.maxY ? y : this.maxY;
        x = a * minX + c * maxY + tx;
        y = b * minX + d * maxY + ty;
        this.minX = x < this.minX ? x : this.minX;
        this.minY = y < this.minY ? y : this.minY;
        this.maxX = x > this.maxX ? x : this.maxX;
        this.maxY = y > this.maxY ? y : this.maxY;
        x = a * maxX + c * maxY + tx;
        y = b * maxX + d * maxY + ty;
        this.minX = x < this.minX ? x : this.minX;
        this.minY = y < this.minY ? y : this.minY;
        this.maxX = x > this.maxX ? x : this.maxX;
        this.maxY = y > this.maxY ? y : this.maxY;
      }
      /**
       * Resizes the bounds object to fit within the given rectangle.
       * Clips the bounds if they extend beyond the rectangle's edges.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 200, 200);
       * // Fit within viewport
       * const viewport = new Rectangle(50, 50, 100, 100);
       * bounds.fit(viewport);
       * // bounds are now (50, 50, 150, 150)
       * ```
       * @param rect - The rectangle to fit within
       * @returns This bounds object for chaining
       * @see {@link Bounds#addBoundsMask} For intersection
       * @see {@link Bounds#pad} For expanding bounds
       */
      fit(rect) {
        if (this.minX < rect.left)
          this.minX = rect.left;
        if (this.maxX > rect.right)
          this.maxX = rect.right;
        if (this.minY < rect.top)
          this.minY = rect.top;
        if (this.maxY > rect.bottom)
          this.maxY = rect.bottom;
        return this;
      }
      /**
       * Resizes the bounds object to include the given bounds.
       * Similar to fit() but works with raw coordinate values instead of a Rectangle.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 200, 200);
       * // Fit to specific coordinates
       * bounds.fitBounds(50, 150, 50, 150);
       * // bounds are now (50, 50, 150, 150)
       * ```
       * @param left - The left value of the bounds
       * @param right - The right value of the bounds
       * @param top - The top value of the bounds
       * @param bottom - The bottom value of the bounds
       * @returns This bounds object for chaining
       * @see {@link Bounds#fit} For fitting to Rectangle
       * @see {@link Bounds#addBoundsMask} For intersection
       */
      fitBounds(left, right, top, bottom) {
        if (this.minX < left)
          this.minX = left;
        if (this.maxX > right)
          this.maxX = right;
        if (this.minY < top)
          this.minY = top;
        if (this.maxY > bottom)
          this.maxY = bottom;
        return this;
      }
      /**
       * Pads bounds object, making it grow in all directions.
       * If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       *
       * // Add equal padding
       * bounds.pad(10);
       * // bounds are now (-10, -10, 110, 110)
       *
       * // Add different padding for x and y
       * bounds.pad(20, 10);
       * // bounds are now (-30, -20, 130, 120)
       * ```
       * @param paddingX - The horizontal padding amount
       * @param paddingY - The vertical padding amount
       * @returns This bounds object for chaining
       * @see {@link Bounds#fit} For constraining bounds
       * @see {@link Bounds#scale} For uniform scaling
       */
      pad(paddingX, paddingY = paddingX) {
        this.minX -= paddingX;
        this.maxX += paddingX;
        this.minY -= paddingY;
        this.maxY += paddingY;
        return this;
      }
      /**
       * Ceils the bounds by rounding up max values and rounding down min values.
       * Useful for pixel-perfect calculations and avoiding fractional pixels.
       * @example
       * ```ts
       * const bounds = new Bounds();
       * bounds.set(10.2, 10.9, 50.1, 50.8);
       *
       * // Round to whole pixels
       * bounds.ceil();
       * // bounds are now (10, 10, 51, 51)
       * ```
       * @returns This bounds object for chaining
       * @see {@link Bounds#scale} For size adjustments
       * @see {@link Bounds#fit} For constraining bounds
       */
      ceil() {
        this.minX = Math.floor(this.minX);
        this.minY = Math.floor(this.minY);
        this.maxX = Math.ceil(this.maxX);
        this.maxY = Math.ceil(this.maxY);
        return this;
      }
      /**
       * Creates a new Bounds instance with the same values.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       *
       * // Create a copy
       * const copy = bounds.clone();
       *
       * // Original and copy are independent
       * bounds.pad(10);
       * console.log(copy.width === bounds.width); // false
       * ```
       * @returns A new Bounds instance with the same values
       * @see {@link Bounds#copyFrom} For reusing existing bounds
       */
      clone() {
        return new Bounds(this.minX, this.minY, this.maxX, this.maxY);
      }
      /**
       * Scales the bounds by the given values, adjusting all edges proportionally.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       *
       * // Scale uniformly
       * bounds.scale(2);
       * // bounds are now (0, 0, 200, 200)
       *
       * // Scale non-uniformly
       * bounds.scale(0.5, 2);
       * // bounds are now (0, 0, 100, 400)
       * ```
       * @param x - The X value to scale by
       * @param y - The Y value to scale by (defaults to x)
       * @returns This bounds object for chaining
       * @see {@link Bounds#pad} For adding padding
       * @see {@link Bounds#fit} For constraining size
       */
      scale(x, y = x) {
        this.minX *= x;
        this.minY *= y;
        this.maxX *= x;
        this.maxY *= y;
        return this;
      }
      /**
       * The x position of the bounds in local space.
       * Setting this value will move the bounds while maintaining its width.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Get x position
       * console.log(bounds.x); // 0
       *
       * // Move bounds horizontally
       * bounds.x = 50;
       * console.log(bounds.minX, bounds.maxX); // 50, 150
       *
       * // Width stays the same
       * console.log(bounds.width); // Still 100
       * ```
       */
      get x() {
        return this.minX;
      }
      set x(value) {
        const width = this.maxX - this.minX;
        this.minX = value;
        this.maxX = value + width;
      }
      /**
       * The y position of the bounds in local space.
       * Setting this value will move the bounds while maintaining its height.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Get y position
       * console.log(bounds.y); // 0
       *
       * // Move bounds vertically
       * bounds.y = 50;
       * console.log(bounds.minY, bounds.maxY); // 50, 150
       *
       * // Height stays the same
       * console.log(bounds.height); // Still 100
       * ```
       */
      get y() {
        return this.minY;
      }
      set y(value) {
        const height = this.maxY - this.minY;
        this.minY = value;
        this.maxY = value + height;
      }
      /**
       * The width value of the bounds.
       * Represents the distance between minX and maxX coordinates.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Get width
       * console.log(bounds.width); // 100
       * // Resize width
       * bounds.width = 200;
       * console.log(bounds.maxX - bounds.minX); // 200
       * ```
       */
      get width() {
        return this.maxX - this.minX;
      }
      set width(value) {
        this.maxX = this.minX + value;
      }
      /**
       * The height value of the bounds.
       * Represents the distance between minY and maxY coordinates.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Get height
       * console.log(bounds.height); // 100
       * // Resize height
       * bounds.height = 150;
       * console.log(bounds.maxY - bounds.minY); // 150
       * ```
       */
      get height() {
        return this.maxY - this.minY;
      }
      set height(value) {
        this.maxY = this.minY + value;
      }
      /**
       * The left edge coordinate of the bounds.
       * Alias for minX.
       * @example
       * ```ts
       * const bounds = new Bounds(50, 0, 150, 100);
       * console.log(bounds.left); // 50
       * console.log(bounds.left === bounds.minX); // true
       * ```
       * @readonly
       */
      get left() {
        return this.minX;
      }
      /**
       * The right edge coordinate of the bounds.
       * Alias for maxX.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * console.log(bounds.right); // 100
       * console.log(bounds.right === bounds.maxX); // true
       * ```
       * @readonly
       */
      get right() {
        return this.maxX;
      }
      /**
       * The top edge coordinate of the bounds.
       * Alias for minY.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 25, 100, 125);
       * console.log(bounds.top); // 25
       * console.log(bounds.top === bounds.minY); // true
       * ```
       * @readonly
       */
      get top() {
        return this.minY;
      }
      /**
       * The bottom edge coordinate of the bounds.
       * Alias for maxY.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 200);
       * console.log(bounds.bottom); // 200
       * console.log(bounds.bottom === bounds.maxY); // true
       * ```
       * @readonly
       */
      get bottom() {
        return this.maxY;
      }
      /**
       * Whether the bounds has positive width and height.
       * Checks if both dimensions are greater than zero.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Check if bounds are positive
       * console.log(bounds.isPositive); // true
       *
       * // Negative bounds
       * bounds.maxX = bounds.minX;
       * console.log(bounds.isPositive); // false, width is 0
       * ```
       * @readonly
       * @see {@link Bounds#isEmpty} For checking empty state
       * @see {@link Bounds#isValid} For checking validity
       */
      get isPositive() {
        return this.maxX - this.minX > 0 && this.maxY - this.minY > 0;
      }
      /**
       * Whether the bounds has valid coordinates.
       * Checks if the bounds has been initialized with real values.
       * @example
       * ```ts
       * const bounds = new Bounds();
       * console.log(bounds.isValid); // false, default state
       *
       * // Set valid bounds
       * bounds.addFrame(0, 0, 100, 100);
       * console.log(bounds.isValid); // true
       * ```
       * @readonly
       * @see {@link Bounds#isEmpty} For checking empty state
       * @see {@link Bounds#isPositive} For checking dimensions
       */
      get isValid() {
        return this.minX + this.minY !== Infinity;
      }
      /**
       * Adds vertices from a Float32Array to the bounds, optionally transformed by a matrix.
       * Used for efficiently updating bounds from raw vertex data.
       * @example
       * ```ts
       * const bounds = new Bounds();
       *
       * // Add vertices from geometry
       * const vertices = new Float32Array([
       *     0, 0,    // Vertex 1
       *     100, 0,  // Vertex 2
       *     100, 100 // Vertex 3
       * ]);
       * bounds.addVertexData(vertices, 0, 6);
       *
       * // Add transformed vertices
       * const matrix = new Matrix()
       *     .translate(50, 50)
       *     .rotate(Math.PI / 4);
       * bounds.addVertexData(vertices, 0, 6, matrix);
       *
       * // Add subset of vertices
       * bounds.addVertexData(vertices, 2, 4); // Only second vertex
       * ```
       * @param vertexData - The array of vertices to add
       * @param beginOffset - Starting index in the vertex array
       * @param endOffset - Ending index in the vertex array (excluded)
       * @param matrix - Optional transformation matrix
       * @see {@link Bounds#addFrame} For adding rectangular frames
       * @see {@link Matrix} For transformation details
       */
      addVertexData(vertexData, beginOffset, endOffset, matrix) {
        let minX = this.minX;
        let minY = this.minY;
        let maxX = this.maxX;
        let maxY = this.maxY;
        matrix || (matrix = this.matrix);
        const a = matrix.a;
        const b = matrix.b;
        const c = matrix.c;
        const d = matrix.d;
        const tx = matrix.tx;
        const ty = matrix.ty;
        for (let i = beginOffset; i < endOffset; i += 2) {
          const localX = vertexData[i];
          const localY = vertexData[i + 1];
          const x = a * localX + c * localY + tx;
          const y = b * localX + d * localY + ty;
          minX = x < minX ? x : minX;
          minY = y < minY ? y : minY;
          maxX = x > maxX ? x : maxX;
          maxY = y > maxY ? y : maxY;
        }
        this.minX = minX;
        this.minY = minY;
        this.maxX = maxX;
        this.maxY = maxY;
      }
      /**
       * Checks if a point is contained within the bounds.
       * Returns true if the point's coordinates fall within the bounds' area.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * // Basic point check
       * console.log(bounds.containsPoint(50, 50)); // true
       * console.log(bounds.containsPoint(150, 150)); // false
       *
       * // Check edges
       * console.log(bounds.containsPoint(0, 0));   // true, includes edges
       * console.log(bounds.containsPoint(100, 100)); // true, includes edges
       * ```
       * @param x - x coordinate to check
       * @param y - y coordinate to check
       * @returns True if the point is inside the bounds
       * @see {@link Bounds#isPositive} For valid bounds check
       * @see {@link Bounds#rectangle} For Rectangle representation
       */
      containsPoint(x, y) {
        if (this.minX <= x && this.minY <= y && this.maxX >= x && this.maxY >= y) {
          return true;
        }
        return false;
      }
      /**
       * Returns a string representation of the bounds.
       * Useful for debugging and logging bounds information.
       * @example
       * ```ts
       * const bounds = new Bounds(0, 0, 100, 100);
       * console.log(bounds.toString()); // "[pixi.js:Bounds minX=0 minY=0 maxX=100 maxY=100 width=100 height=100]"
       * ```
       * @returns A string describing the bounds
       * @see {@link Bounds#copyFrom} For copying bounds
       * @see {@link Bounds#clone} For creating a new instance
       */
      toString() {
        return `[pixi.js:Bounds minX=${this.minX} minY=${this.minY} maxX=${this.maxX} maxY=${this.maxY} width=${this.width} height=${this.height}]`;
      }
      /**
       * Copies the bounds from another bounds object.
       * Useful for reusing bounds objects and avoiding allocations.
       * @example
       * ```ts
       * const sourceBounds = new Bounds(0, 0, 100, 100);
       * // Copy bounds
       * const targetBounds = new Bounds();
       * targetBounds.copyFrom(sourceBounds);
       * ```
       * @param bounds - The bounds to copy from
       * @returns This bounds object for chaining
       * @see {@link Bounds#clone} For creating new instances
       */
      copyFrom(bounds) {
        this.minX = bounds.minX;
        this.minY = bounds.minY;
        this.maxX = bounds.maxX;
        this.maxY = bounds.maxY;
        return this;
      }
    }

    var r={grad:.9,turn:360,rad:360/(2*Math.PI)},t=function(r){return "string"==typeof r?r.length>0:"number"==typeof r},n=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=Math.pow(10,t)),Math.round(n*r)/n+0},e=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=1),r>n?n:r>t?r:t},u=function(r){return (r=isFinite(r)?r%360:0)>0?r:r+360},a=function(r){return {r:e(r.r,0,255),g:e(r.g,0,255),b:e(r.b,0,255),a:e(r.a)}},o=function(r){return {r:n(r.r),g:n(r.g),b:n(r.b),a:n(r.a,3)}},i=/^#([0-9a-f]{3,8})$/i,s=function(r){var t=r.toString(16);return t.length<2?"0"+t:t},h=function(r){var t=r.r,n=r.g,e=r.b,u=r.a,a=Math.max(t,n,e),o=a-Math.min(t,n,e),i=o?a===t?(n-e)/o:a===n?2+(e-t)/o:4+(t-n)/o:0;return {h:60*(i<0?i+6:i),s:a?o/a*100:0,v:a/255*100,a:u}},b=function(r){var t=r.h,n=r.s,e=r.v,u=r.a;t=t/360*6,n/=100,e/=100;var a=Math.floor(t),o=e*(1-n),i=e*(1-(t-a)*n),s=e*(1-(1-t+a)*n),h=a%6;return {r:255*[e,i,o,o,s,e][h],g:255*[s,e,e,i,o,o][h],b:255*[o,o,s,e,e,i][h],a:u}},g=function(r){return {h:u(r.h),s:e(r.s,0,100),l:e(r.l,0,100),a:e(r.a)}},d=function(r){return {h:n(r.h),s:n(r.s),l:n(r.l),a:n(r.a,3)}},f=function(r){return b((n=(t=r).s,{h:t.h,s:(n*=((e=t.l)<50?e:100-e)/100)>0?2*n/(e+n)*100:0,v:e+n,a:t.a}));var t,n,e;},c=function(r){return {h:(t=h(r)).h,s:(u=(200-(n=t.s))*(e=t.v)/100)>0&&u<200?n*e/100/(u<=100?u:200-u)*100:0,l:u/2,a:t.a};var t,n,e,u;},l=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,p=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,v=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,m=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,y={string:[[function(r){var t=i.exec(r);return t?(r=t[1]).length<=4?{r:parseInt(r[0]+r[0],16),g:parseInt(r[1]+r[1],16),b:parseInt(r[2]+r[2],16),a:4===r.length?n(parseInt(r[3]+r[3],16)/255,2):1}:6===r.length||8===r.length?{r:parseInt(r.substr(0,2),16),g:parseInt(r.substr(2,2),16),b:parseInt(r.substr(4,2),16),a:8===r.length?n(parseInt(r.substr(6,2),16)/255,2):1}:null:null},"hex"],[function(r){var t=v.exec(r)||m.exec(r);return t?t[2]!==t[4]||t[4]!==t[6]?null:a({r:Number(t[1])/(t[2]?100/255:1),g:Number(t[3])/(t[4]?100/255:1),b:Number(t[5])/(t[6]?100/255:1),a:void 0===t[7]?1:Number(t[7])/(t[8]?100:1)}):null},"rgb"],[function(t){var n=l.exec(t)||p.exec(t);if(!n)return null;var e,u,a=g({h:(e=n[1],u=n[2],void 0===u&&(u="deg"),Number(e)*(r[u]||1)),s:Number(n[3]),l:Number(n[4]),a:void 0===n[5]?1:Number(n[5])/(n[6]?100:1)});return f(a)},"hsl"]],object:[[function(r){var n=r.r,e=r.g,u=r.b,o=r.a,i=void 0===o?1:o;return t(n)&&t(e)&&t(u)?a({r:Number(n),g:Number(e),b:Number(u),a:Number(i)}):null},"rgb"],[function(r){var n=r.h,e=r.s,u=r.l,a=r.a,o=void 0===a?1:a;if(!t(n)||!t(e)||!t(u))return null;var i=g({h:Number(n),s:Number(e),l:Number(u),a:Number(o)});return f(i)},"hsl"],[function(r){var n=r.h,a=r.s,o=r.v,i=r.a,s=void 0===i?1:i;if(!t(n)||!t(a)||!t(o))return null;var h=function(r){return {h:u(r.h),s:e(r.s,0,100),v:e(r.v,0,100),a:e(r.a)}}({h:Number(n),s:Number(a),v:Number(o),a:Number(s)});return b(h)},"hsv"]]},N=function(r,t){for(var n=0;n<t.length;n++){var e=t[n][0](r);if(e)return [e,t[n][1]]}return [null,void 0]},x=function(r){return "string"==typeof r?N(r.trim(),y.string):"object"==typeof r&&null!==r?N(r,y.object):[null,void 0]},I=function(r){return x(r)[1]},M=function(r,t){var n=c(r);return {h:n.h,s:e(n.s+100*t,0,100),l:n.l,a:n.a}},H=function(r){return (299*r.r+587*r.g+114*r.b)/1e3/255},$=function(r,t){var n=c(r);return {h:n.h,s:n.s,l:e(n.l+100*t,0,100),a:n.a}},j=function(){function r(r){this.parsed=x(r)[0],this.rgba=this.parsed||{r:0,g:0,b:0,a:1};}return r.prototype.isValid=function(){return null!==this.parsed},r.prototype.brightness=function(){return n(H(this.rgba),2)},r.prototype.isDark=function(){return H(this.rgba)<.5},r.prototype.isLight=function(){return H(this.rgba)>=.5},r.prototype.toHex=function(){return r=o(this.rgba),t=r.r,e=r.g,u=r.b,i=(a=r.a)<1?s(n(255*a)):"","#"+s(t)+s(e)+s(u)+i;var r,t,e,u,a,i;},r.prototype.toRgb=function(){return o(this.rgba)},r.prototype.toRgbString=function(){return r=o(this.rgba),t=r.r,n=r.g,e=r.b,(u=r.a)<1?"rgba("+t+", "+n+", "+e+", "+u+")":"rgb("+t+", "+n+", "+e+")";var r,t,n,e,u;},r.prototype.toHsl=function(){return d(c(this.rgba))},r.prototype.toHslString=function(){return r=d(c(this.rgba)),t=r.h,n=r.s,e=r.l,(u=r.a)<1?"hsla("+t+", "+n+"%, "+e+"%, "+u+")":"hsl("+t+", "+n+"%, "+e+"%)";var r,t,n,e,u;},r.prototype.toHsv=function(){return r=h(this.rgba),{h:n(r.h),s:n(r.s),v:n(r.v),a:n(r.a,3)};var r;},r.prototype.invert=function(){return w({r:255-(r=this.rgba).r,g:255-r.g,b:255-r.b,a:r.a});var r;},r.prototype.saturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,r))},r.prototype.desaturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,-r))},r.prototype.grayscale=function(){return w(M(this.rgba,-1))},r.prototype.lighten=function(r){return void 0===r&&(r=.1),w($(this.rgba,r))},r.prototype.darken=function(r){return void 0===r&&(r=.1),w($(this.rgba,-r))},r.prototype.rotate=function(r){return void 0===r&&(r=15),this.hue(this.hue()+r)},r.prototype.alpha=function(r){return "number"==typeof r?w({r:(t=this.rgba).r,g:t.g,b:t.b,a:r}):n(this.rgba.a,3);var t;},r.prototype.hue=function(r){var t=c(this.rgba);return "number"==typeof r?w({h:r,s:t.s,l:t.l,a:t.a}):n(t.h)},r.prototype.isEqual=function(r){return this.toHex()===w(r).toHex()},r}(),w=function(r){return r instanceof j?r:new j(r)},S=[],k=function(r){r.forEach(function(r){S.indexOf(r)<0&&(r(j,y),S.push(r));});},E=function(){return new j({r:255*Math.random(),g:255*Math.random(),b:255*Math.random()})};

    function namesPlugin(e,f){var a={white:"#ffffff",bisque:"#ffe4c4",blue:"#0000ff",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",antiquewhite:"#faebd7",aqua:"#00ffff",azure:"#f0ffff",whitesmoke:"#f5f5f5",papayawhip:"#ffefd5",plum:"#dda0dd",blanchedalmond:"#ffebcd",black:"#000000",gold:"#ffd700",goldenrod:"#daa520",gainsboro:"#dcdcdc",cornsilk:"#fff8dc",cornflowerblue:"#6495ed",burlywood:"#deb887",aquamarine:"#7fffd4",beige:"#f5f5dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkkhaki:"#bdb76b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",peachpuff:"#ffdab9",darkmagenta:"#8b008b",darkred:"#8b0000",darkorchid:"#9932cc",darkorange:"#ff8c00",darkslateblue:"#483d8b",gray:"#808080",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",deeppink:"#ff1493",deepskyblue:"#00bfff",wheat:"#f5deb3",firebrick:"#b22222",floralwhite:"#fffaf0",ghostwhite:"#f8f8ff",darkviolet:"#9400d3",magenta:"#ff00ff",green:"#008000",dodgerblue:"#1e90ff",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",blueviolet:"#8a2be2",forestgreen:"#228b22",lawngreen:"#7cfc00",indianred:"#cd5c5c",indigo:"#4b0082",fuchsia:"#ff00ff",brown:"#a52a2a",maroon:"#800000",mediumblue:"#0000cd",lightcoral:"#f08080",darkturquoise:"#00ced1",lightcyan:"#e0ffff",ivory:"#fffff0",lightyellow:"#ffffe0",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",linen:"#faf0e6",mediumaquamarine:"#66cdaa",lemonchiffon:"#fffacd",lime:"#00ff00",khaki:"#f0e68c",mediumseagreen:"#3cb371",limegreen:"#32cd32",mediumspringgreen:"#00fa9a",lightskyblue:"#87cefa",lightblue:"#add8e6",midnightblue:"#191970",lightpink:"#ffb6c1",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",mintcream:"#f5fffa",lightslategray:"#778899",lightslategrey:"#778899",navajowhite:"#ffdead",navy:"#000080",mediumvioletred:"#c71585",powderblue:"#b0e0e6",palegoldenrod:"#eee8aa",oldlace:"#fdf5e6",paleturquoise:"#afeeee",mediumturquoise:"#48d1cc",mediumorchid:"#ba55d3",rebeccapurple:"#663399",lightsteelblue:"#b0c4de",mediumslateblue:"#7b68ee",thistle:"#d8bfd8",tan:"#d2b48c",orchid:"#da70d6",mediumpurple:"#9370db",purple:"#800080",pink:"#ffc0cb",skyblue:"#87ceeb",springgreen:"#00ff7f",palegreen:"#98fb98",red:"#ff0000",yellow:"#ffff00",slateblue:"#6a5acd",lavenderblush:"#fff0f5",peru:"#cd853f",palevioletred:"#db7093",violet:"#ee82ee",teal:"#008080",slategray:"#708090",slategrey:"#708090",aliceblue:"#f0f8ff",darkseagreen:"#8fbc8f",darkolivegreen:"#556b2f",greenyellow:"#adff2f",seagreen:"#2e8b57",seashell:"#fff5ee",tomato:"#ff6347",silver:"#c0c0c0",sienna:"#a0522d",lavender:"#e6e6fa",lightgreen:"#90ee90",orange:"#ffa500",orangered:"#ff4500",steelblue:"#4682b4",royalblue:"#4169e1",turquoise:"#40e0d0",yellowgreen:"#9acd32",salmon:"#fa8072",saddlebrown:"#8b4513",sandybrown:"#f4a460",rosybrown:"#bc8f8f",darksalmon:"#e9967a",lightgoldenrodyellow:"#fafad2",snow:"#fffafa",lightgrey:"#d3d3d3",lightgray:"#d3d3d3",dimgray:"#696969",dimgrey:"#696969",olivedrab:"#6b8e23",olive:"#808000"},r={};for(var d in a)r[a[d]]=d;var l={};e.prototype.toName=function(f){if(!(this.rgba.a||this.rgba.r||this.rgba.g||this.rgba.b))return "transparent";var d,i,n=r[this.toHex()];if(n)return n;if(null==f?void 0:f.closest){var o=this.toRgb(),t=1/0,b="black";if(!l.length)for(var c in a)l[c]=new e(a[c]).toRgb();for(var g in a){var u=(d=o,i=l[g],Math.pow(d.r-i.r,2)+Math.pow(d.g-i.g,2)+Math.pow(d.b-i.b,2));u<t&&(t=u,b=g);}return b}};f.string.push([function(f){var r=f.toLowerCase(),d="transparent"===r?"#0000":a[r];return d?new e(d).toRgb():null},"name"]);}

    "use strict";
    var __defProp$18 = Object.defineProperty;
    var __getOwnPropSymbols$1a = Object.getOwnPropertySymbols;
    var __hasOwnProp$1a = Object.prototype.hasOwnProperty;
    var __propIsEnum$1a = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$18 = (obj, key, value) => key in obj ? __defProp$18(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$18 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1a.call(b, prop))
          __defNormalProp$18(a, prop, b[prop]);
      if (__getOwnPropSymbols$1a)
        for (var prop of __getOwnPropSymbols$1a(b)) {
          if (__propIsEnum$1a.call(b, prop))
            __defNormalProp$18(a, prop, b[prop]);
        }
      return a;
    };
    k([namesPlugin]);
    const _Color = class _Color {
      /**
       * @param {ColorSource} value - Optional value to use, if not provided, white is used.
       */
      constructor(value = 16777215) {
        this._value = null;
        this._components = new Float32Array(4);
        this._components.fill(1);
        this._int = 16777215;
        this.value = value;
      }
      /**
       * Get the red component of the color, normalized between 0 and 1.
       * @example
       * ```ts
       * const color = new Color('red');
       * console.log(color.red); // 1
       *
       * const green = new Color('#00ff00');
       * console.log(green.red); // 0
       * ```
       */
      get red() {
        return this._components[0];
      }
      /**
       * Get the green component of the color, normalized between 0 and 1.
       * @example
       * ```ts
       * const color = new Color('lime');
       * console.log(color.green); // 1
       *
       * const red = new Color('#ff0000');
       * console.log(red.green); // 0
       * ```
       */
      get green() {
        return this._components[1];
      }
      /**
       * Get the blue component of the color, normalized between 0 and 1.
       * @example
       * ```ts
       * const color = new Color('blue');
       * console.log(color.blue); // 1
       *
       * const yellow = new Color('#ffff00');
       * console.log(yellow.blue); // 0
       * ```
       */
      get blue() {
        return this._components[2];
      }
      /**
       * Get the alpha component of the color, normalized between 0 and 1.
       * @example
       * ```ts
       * const color = new Color('red');
       * console.log(color.alpha); // 1 (fully opaque)
       *
       * const transparent = new Color('rgba(255, 0, 0, 0.5)');
       * console.log(transparent.alpha); // 0.5 (semi-transparent)
       * ```
       */
      get alpha() {
        return this._components[3];
      }
      /**
       * Sets the color value and returns the instance for chaining.
       *
       * This is a chainable version of setting the `value` property.
       * @param value - The color to set. Accepts various formats:
       * - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
       * - RGB/RGBA values (arrays, objects)
       * - CSS color names
       * - HSL/HSLA values
       * - HSV/HSVA values
       * @returns The Color instance for chaining
       * @example
       * ```ts
       * // Basic usage
       * const color = new Color();
       * color.setValue('#ff0000')
       *     .setAlpha(0.5)
       *     .premultiply(0.8);
       *
       * // Different formats
       * color.setValue(0xff0000);          // Hex number
       * color.setValue('#ff0000');         // Hex string
       * color.setValue([1, 0, 0]);         // RGB array
       * color.setValue([1, 0, 0, 0.5]);    // RGBA array
       * color.setValue({ r: 1, g: 0, b: 0 }); // RGB object
       *
       * // Copy from another color
       * const red = new Color('red');
       * color.setValue(red);
       * ```
       * @throws {Error} If the color value is invalid or null
       * @see {@link Color.value} For the underlying value property
       */
      setValue(value) {
        this.value = value;
        return this;
      }
      /**
       * The current color source. This property allows getting and setting the color value
       * while preserving the original format where possible.
       * @remarks
       * When setting:
       * - Setting to a `Color` instance copies its source and components
       * - Setting to other valid sources normalizes and stores the value
       * - Setting to `null` throws an Error
       * - The color remains unchanged if normalization fails
       *
       * When getting:
       * - Returns `null` if color was modified by {@link Color.multiply} or {@link Color.premultiply}
       * - Otherwise returns the original color source
       * @example
       * ```ts
       * // Setting different color formats
       * const color = new Color();
       *
       * color.value = 0xff0000;         // Hex number
       * color.value = '#ff0000';        // Hex string
       * color.value = [1, 0, 0];        // RGB array
       * color.value = [1, 0, 0, 0.5];   // RGBA array
       * color.value = { r: 1, g: 0, b: 0 }; // RGB object
       *
       * // Copying from another color
       * const red = new Color('red');
       * color.value = red;  // Copies red's components
       *
       * // Getting the value
       * console.log(color.value);  // Returns original format
       *
       * // After modifications
       * color.multiply([0.5, 0.5, 0.5]);
       * console.log(color.value);  // Returns null
       * ```
       * @throws {Error} When attempting to set `null`
       */
      set value(value) {
        if (value instanceof _Color) {
          this._value = this._cloneSource(value._value);
          this._int = value._int;
          this._components.set(value._components);
        } else if (value === null) {
          throw new Error("Cannot set Color#value to null");
        } else if (this._value === null || !this._isSourceEqual(this._value, value)) {
          this._value = this._cloneSource(value);
          this._normalize(this._value);
        }
      }
      get value() {
        return this._value;
      }
      /**
       * Copy a color source internally.
       * @param value - Color source
       */
      _cloneSource(value) {
        if (typeof value === "string" || typeof value === "number" || value instanceof Number || value === null) {
          return value;
        } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
          return value.slice(0);
        } else if (typeof value === "object" && value !== null) {
          return __spreadValues$18({}, value);
        }
        return value;
      }
      /**
       * Equality check for color sources.
       * @param value1 - First color source
       * @param value2 - Second color source
       * @returns `true` if the color sources are equal, `false` otherwise.
       */
      _isSourceEqual(value1, value2) {
        const type1 = typeof value1;
        const type2 = typeof value2;
        if (type1 !== type2) {
          return false;
        } else if (type1 === "number" || type1 === "string" || value1 instanceof Number) {
          return value1 === value2;
        } else if (Array.isArray(value1) && Array.isArray(value2) || ArrayBuffer.isView(value1) && ArrayBuffer.isView(value2)) {
          if (value1.length !== value2.length) {
            return false;
          }
          return value1.every((v, i) => v === value2[i]);
        } else if (value1 !== null && value2 !== null) {
          const keys1 = Object.keys(value1);
          const keys2 = Object.keys(value2);
          if (keys1.length !== keys2.length) {
            return false;
          }
          return keys1.every((key) => value1[key] === value2[key]);
        }
        return value1 === value2;
      }
      /**
       * Convert to a RGBA color object with normalized components (0-1).
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Convert colors to RGBA objects
       * new Color('white').toRgba();     // returns { r: 1, g: 1, b: 1, a: 1 }
       * new Color('#ff0000').toRgba();   // returns { r: 1, g: 0, b: 0, a: 1 }
       *
       * // With transparency
       * new Color('rgba(255,0,0,0.5)').toRgba(); // returns { r: 1, g: 0, b: 0, a: 0.5 }
       * ```
       * @returns An RGBA object with normalized components
       */
      toRgba() {
        const [r, g, b, a] = this._components;
        return { r, g, b, a };
      }
      /**
       * Convert to a RGB color object with normalized components (0-1).
       *
       * Alpha component is omitted in the output.
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Convert colors to RGB objects
       * new Color('white').toRgb();     // returns { r: 1, g: 1, b: 1 }
       * new Color('#ff0000').toRgb();   // returns { r: 1, g: 0, b: 0 }
       *
       * // Alpha is ignored
       * new Color('rgba(255,0,0,0.5)').toRgb(); // returns { r: 1, g: 0, b: 0 }
       * ```
       * @returns An RGB object with normalized components
       */
      toRgb() {
        const [r, g, b] = this._components;
        return { r, g, b };
      }
      /**
       * Convert to a CSS-style rgba string representation.
       *
       * RGB components are scaled to 0-255 range, alpha remains 0-1.
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Convert colors to RGBA strings
       * new Color('white').toRgbaString();     // returns "rgba(255,255,255,1)"
       * new Color('#ff0000').toRgbaString();   // returns "rgba(255,0,0,1)"
       *
       * // With transparency
       * new Color([1, 0, 0, 0.5]).toRgbaString(); // returns "rgba(255,0,0,0.5)"
       * ```
       * @returns A CSS-compatible rgba string
       */
      toRgbaString() {
        const [r, g, b] = this.toUint8RgbArray();
        return `rgba(${r},${g},${b},${this.alpha})`;
      }
      /**
       * Convert to an [R, G, B] array of clamped uint8 values (0 to 255).
       * @param {number[]|Uint8Array|Uint8ClampedArray} [out] - Optional output array. If not provided,
       * a cached array will be used and returned.
       * @returns Array containing RGB components as integers between 0-255
       * @example
       * ```ts
       * // Basic usage
       * new Color('white').toUint8RgbArray(); // returns [255, 255, 255]
       * new Color('#ff0000').toUint8RgbArray(); // returns [255, 0, 0]
       *
       * // Using custom output array
       * const rgb = new Uint8Array(3);
       * new Color('blue').toUint8RgbArray(rgb); // rgb is now [0, 0, 255]
       *
       * // Using different array types
       * new Color('red').toUint8RgbArray(new Uint8ClampedArray(3)); // [255, 0, 0]
       * new Color('red').toUint8RgbArray([]); // [255, 0, 0]
       * ```
       * @remarks
       * - Output values are always clamped between 0-255
       * - Alpha component is not included in output
       * - Reuses internal cache array if no output array provided
       */
      toUint8RgbArray(out) {
        const [r, g, b] = this._components;
        if (!this._arrayRgb) {
          this._arrayRgb = [];
        }
        out || (out = this._arrayRgb);
        out[0] = Math.round(r * 255);
        out[1] = Math.round(g * 255);
        out[2] = Math.round(b * 255);
        return out;
      }
      /**
       * Convert to an [R, G, B, A] array of normalized floats (numbers from 0.0 to 1.0).
       * @param {number[]|Float32Array} [out] - Optional output array. If not provided,
       * a cached array will be used and returned.
       * @returns Array containing RGBA components as floats between 0-1
       * @example
       * ```ts
       * // Basic usage
       * new Color('white').toArray();  // returns [1, 1, 1, 1]
       * new Color('red').toArray();    // returns [1, 0, 0, 1]
       *
       * // With alpha
       * new Color('rgba(255,0,0,0.5)').toArray(); // returns [1, 0, 0, 0.5]
       *
       * // Using custom output array
       * const rgba = new Float32Array(4);
       * new Color('blue').toArray(rgba); // rgba is now [0, 0, 1, 1]
       * ```
       * @remarks
       * - Output values are normalized between 0-1
       * - Includes alpha component as the fourth value
       * - Reuses internal cache array if no output array provided
       */
      toArray(out) {
        if (!this._arrayRgba) {
          this._arrayRgba = [];
        }
        out || (out = this._arrayRgba);
        const [r, g, b, a] = this._components;
        out[0] = r;
        out[1] = g;
        out[2] = b;
        out[3] = a;
        return out;
      }
      /**
       * Convert to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0).
       * @param {number[]|Float32Array} [out] - Optional output array. If not provided,
       * a cached array will be used and returned.
       * @returns Array containing RGB components as floats between 0-1
       * @example
       * ```ts
       * // Basic usage
       * new Color('white').toRgbArray(); // returns [1, 1, 1]
       * new Color('red').toRgbArray();   // returns [1, 0, 0]
       *
       * // Using custom output array
       * const rgb = new Float32Array(3);
       * new Color('blue').toRgbArray(rgb); // rgb is now [0, 0, 1]
       * ```
       * @remarks
       * - Output values are normalized between 0-1
       * - Alpha component is omitted from output
       * - Reuses internal cache array if no output array provided
       */
      toRgbArray(out) {
        if (!this._arrayRgb) {
          this._arrayRgb = [];
        }
        out || (out = this._arrayRgb);
        const [r, g, b] = this._components;
        out[0] = r;
        out[1] = g;
        out[2] = b;
        return out;
      }
      /**
       * Convert to a hexadecimal number.
       * @returns The color as a 24-bit RGB integer
       * @example
       * ```ts
       * // Basic usage
       * new Color('white').toNumber(); // returns 0xffffff
       * new Color('red').toNumber();   // returns 0xff0000
       *
       * // Store as hex
       * const color = new Color('blue');
       * const hex = color.toNumber(); // 0x0000ff
       * ```
       */
      toNumber() {
        return this._int;
      }
      /**
       * Convert to a BGR number.
       *
       * Useful for platforms that expect colors in BGR format.
       * @returns The color as a 24-bit BGR integer
       * @example
       * ```ts
       * // Convert RGB to BGR
       * new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff
       *
       * // Common use case: platform-specific color format
       * const color = new Color('orange');
       * const bgrColor = color.toBgrNumber(); // Color with swapped R/B channels
       * ```
       * @remarks
       * This swaps the red and blue channels compared to the normal RGB format:
       * - RGB 0xRRGGBB becomes BGR 0xBBGGRR
       */
      toBgrNumber() {
        const [r, g, b] = this.toUint8RgbArray();
        return (b << 16) + (g << 8) + r;
      }
      /**
       * Convert to a hexadecimal number in little endian format (e.g., BBGGRR).
       *
       * Useful for platforms that expect colors in little endian byte order.
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Convert RGB color to little endian format
       * new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff
       *
       * // Common use cases:
       * const color = new Color('orange');
       * const leColor = color.toLittleEndianNumber(); // Swaps byte order for LE systems
       *
       * // Multiple conversions
       * const colors = {
       *     normal: 0xffcc99,
       *     littleEndian: new Color(0xffcc99).toLittleEndianNumber(), // 0x99ccff
       *     backToNormal: new Color(0x99ccff).toLittleEndianNumber()  // 0xffcc99
       * };
       * ```
       * @remarks
       * - Swaps R and B channels in the color value
       * - RGB 0xRRGGBB becomes 0xBBGGRR
       * - Useful for systems that use little endian byte order
       * - Can be used to convert back and forth between formats
       * @returns The color as a number in little endian format (BBGGRR)
       * @see {@link Color.toBgrNumber} For BGR format without byte swapping
       */
      toLittleEndianNumber() {
        const value = this._int;
        return (value >> 16) + (value & 65280) + ((value & 255) << 16);
      }
      /**
       * Multiply with another color.
       *
       * This action is destructive and modifies the original color.
       * @param {ColorSource} value - The color to multiply by. Accepts any valid color format:
       * - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
       * - RGB/RGBA arrays ([1, 0, 0], [1, 0, 0, 1])
       * - Color objects ({ r: 1, g: 0, b: 0 })
       * - CSS color names ('red', 'blue')
       * @returns this - The Color instance for chaining
       * @example
       * ```ts
       * // Basic multiplication
       * const color = new Color('#ff0000');
       * color.multiply(0x808080); // 50% darker red
       *
       * // With transparency
       * color.multiply([1, 1, 1, 0.5]); // 50% transparent
       *
       * // Chain operations
       * color
       *     .multiply('#808080')
       *     .multiply({ r: 1, g: 1, b: 1, a: 0.5 });
       * ```
       * @remarks
       * - Multiplies each RGB component and alpha separately
       * - Values are clamped between 0-1
       * - Original color format is lost (value becomes null)
       * - Operation cannot be undone
       */
      multiply(value) {
        const [r, g, b, a] = _Color._temp.setValue(value)._components;
        this._components[0] *= r;
        this._components[1] *= g;
        this._components[2] *= b;
        this._components[3] *= a;
        this._refreshInt();
        this._value = null;
        return this;
      }
      /**
       * Converts color to a premultiplied alpha format.
       *
       * This action is destructive and modifies the original color.
       * @param alpha - The alpha value to multiply by (0-1)
       * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
       * @returns {Color} The Color instance for chaining
       * @example
       * ```ts
       * // Basic premultiplication
       * const color = new Color('red');
       * color.premultiply(0.5); // 50% transparent red with premultiplied RGB
       *
       * // Alpha only (RGB unchanged)
       * color.premultiply(0.5, false); // 50% transparent, original RGB
       *
       * // Chain with other operations
       * color
       *     .multiply(0x808080)
       *     .premultiply(0.5)
       *     .toNumber();
       * ```
       * @remarks
       * - RGB channels are multiplied by alpha when applyToRGB is true
       * - Alpha is always set to the provided value
       * - Values are clamped between 0-1
       * - Original color format is lost (value becomes null)
       * - Operation cannot be undone
       */
      premultiply(alpha, applyToRGB = true) {
        if (applyToRGB) {
          this._components[0] *= alpha;
          this._components[1] *= alpha;
          this._components[2] *= alpha;
        }
        this._components[3] = alpha;
        this._refreshInt();
        this._value = null;
        return this;
      }
      /**
       * Returns the color as a 32-bit premultiplied alpha integer.
       *
       * Format: 0xAARRGGBB
       * @param {number} alpha - The alpha value to multiply by (0-1)
       * @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
       * @returns {number} The premultiplied color as a 32-bit integer
       * @example
       * ```ts
       * // Convert to premultiplied format
       * const color = new Color('red');
       *
       * // Full opacity (0xFFRRGGBB)
       * color.toPremultiplied(1.0); // 0xFFFF0000
       *
       * // 50% transparency with premultiplied RGB
       * color.toPremultiplied(0.5); // 0x7F7F0000
       *
       * // 50% transparency without RGB premultiplication
       * color.toPremultiplied(0.5, false); // 0x7FFF0000
       * ```
       * @remarks
       * - Returns full opacity (0xFF000000) when alpha is 1.0
       * - Returns 0 when alpha is 0.0 and applyToRGB is true
       * - RGB values are rounded during premultiplication
       */
      toPremultiplied(alpha, applyToRGB = true) {
        if (alpha === 1) {
          return (255 << 24) + this._int;
        }
        if (alpha === 0) {
          return applyToRGB ? 0 : this._int;
        }
        let r = this._int >> 16 & 255;
        let g = this._int >> 8 & 255;
        let b = this._int & 255;
        if (applyToRGB) {
          r = r * alpha + 0.5 | 0;
          g = g * alpha + 0.5 | 0;
          b = b * alpha + 0.5 | 0;
        }
        return (alpha * 255 << 24) + (r << 16) + (g << 8) + b;
      }
      /**
       * Convert to a hexadecimal string (6 characters).
       * @returns A CSS-compatible hex color string (e.g., "#ff0000")
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Basic colors
       * new Color('red').toHex();    // returns "#ff0000"
       * new Color('white').toHex();  // returns "#ffffff"
       * new Color('black').toHex();  // returns "#000000"
       *
       * // From different formats
       * new Color(0xff0000).toHex(); // returns "#ff0000"
       * new Color([1, 0, 0]).toHex(); // returns "#ff0000"
       * new Color({ r: 1, g: 0, b: 0 }).toHex(); // returns "#ff0000"
       * ```
       * @remarks
       * - Always returns a 6-character hex string
       * - Includes leading "#" character
       * - Alpha channel is ignored
       * - Values are rounded to nearest hex value
       */
      toHex() {
        const hexString = this._int.toString(16);
        return `#${"000000".substring(0, 6 - hexString.length) + hexString}`;
      }
      /**
       * Convert to a hexadecimal string with alpha (8 characters).
       * @returns A CSS-compatible hex color string with alpha (e.g., "#ff0000ff")
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // Fully opaque colors
       * new Color('red').toHexa();   // returns "#ff0000ff"
       * new Color('white').toHexa(); // returns "#ffffffff"
       *
       * // With transparency
       * new Color('rgba(255, 0, 0, 0.5)').toHexa(); // returns "#ff00007f"
       * new Color([1, 0, 0, 0]).toHexa(); // returns "#ff000000"
       * ```
       * @remarks
       * - Returns an 8-character hex string
       * - Includes leading "#" character
       * - Alpha is encoded in last two characters
       * - Values are rounded to nearest hex value
       */
      toHexa() {
        const alphaValue = Math.round(this._components[3] * 255);
        const alphaString = alphaValue.toString(16);
        return this.toHex() + "00".substring(0, 2 - alphaString.length) + alphaString;
      }
      /**
       * Set alpha (transparency) value while preserving color components.
       *
       * Provides a chainable interface for setting alpha.
       * @param alpha - Alpha value between 0 (fully transparent) and 1 (fully opaque)
       * @returns The Color instance for chaining
       * @example
       * ```ts
       * // Basic alpha setting
       * const color = new Color('red');
       * color.setAlpha(0.5);  // 50% transparent red
       *
       * // Chain with other operations
       * color
       *     .setValue('#ff0000')
       *     .setAlpha(0.8)    // 80% opaque
       *     .premultiply(0.5); // Further modify alpha
       *
       * // Reset to fully opaque
       * color.setAlpha(1);
       * ```
       * @remarks
       * - Alpha value is clamped between 0-1
       * - Can be chained with other color operations
       */
      setAlpha(alpha) {
        this._components[3] = this._clamp(alpha);
        return this;
      }
      /**
       * Normalize the input value into rgba
       * @param value - Input value
       */
      _normalize(value) {
        let r;
        let g;
        let b;
        let a;
        if ((typeof value === "number" || value instanceof Number) && value >= 0 && value <= 16777215) {
          const int = value;
          r = (int >> 16 & 255) / 255;
          g = (int >> 8 & 255) / 255;
          b = (int & 255) / 255;
          a = 1;
        } else if ((Array.isArray(value) || value instanceof Float32Array) && value.length >= 3 && value.length <= 4) {
          value = this._clamp(value);
          [r, g, b, a = 1] = value;
        } else if ((value instanceof Uint8Array || value instanceof Uint8ClampedArray) && value.length >= 3 && value.length <= 4) {
          value = this._clamp(value, 0, 255);
          [r, g, b, a = 255] = value;
          r /= 255;
          g /= 255;
          b /= 255;
          a /= 255;
        } else if (typeof value === "string" || typeof value === "object") {
          if (typeof value === "string") {
            const match = _Color.HEX_PATTERN.exec(value);
            if (match) {
              value = `#${match[2]}`;
            }
          }
          const color = w(value);
          if (color.isValid()) {
            ({ r, g, b, a } = color.rgba);
            r /= 255;
            g /= 255;
            b /= 255;
          }
        }
        if (r !== void 0) {
          this._components[0] = r;
          this._components[1] = g;
          this._components[2] = b;
          this._components[3] = a;
          this._refreshInt();
        } else {
          throw new Error(`Unable to convert color ${value}`);
        }
      }
      /** Refresh the internal color rgb number */
      _refreshInt() {
        this._clamp(this._components);
        const [r, g, b] = this._components;
        this._int = (r * 255 << 16) + (g * 255 << 8) + (b * 255 | 0);
      }
      /**
       * Clamps values to a range. Will override original values
       * @param value - Value(s) to clamp
       * @param min - Minimum value
       * @param max - Maximum value
       */
      _clamp(value, min = 0, max = 1) {
        if (typeof value === "number") {
          return Math.min(Math.max(value, min), max);
        }
        value.forEach((v, i) => {
          value[i] = Math.min(Math.max(v, min), max);
        });
        return value;
      }
      /**
       * Check if a value can be interpreted as a valid color format.
       * Supports all color formats that can be used with the Color class.
       * @param value - Value to check
       * @returns True if the value can be used as a color
       * @example
       * ```ts
       * import { Color } from 'pixi.js';
       *
       * // CSS colors and hex values
       * Color.isColorLike('red');          // true
       * Color.isColorLike('#ff0000');      // true
       * Color.isColorLike(0xff0000);       // true
       *
       * // Arrays (RGB/RGBA)
       * Color.isColorLike([1, 0, 0]);      // true
       * Color.isColorLike([1, 0, 0, 0.5]); // true
       *
       * // TypedArrays
       * Color.isColorLike(new Float32Array([1, 0, 0]));          // true
       * Color.isColorLike(new Uint8Array([255, 0, 0]));          // true
       * Color.isColorLike(new Uint8ClampedArray([255, 0, 0]));   // true
       *
       * // Object formats
       * Color.isColorLike({ r: 1, g: 0, b: 0 });            // true (RGB)
       * Color.isColorLike({ r: 1, g: 0, b: 0, a: 0.5 });    // true (RGBA)
       * Color.isColorLike({ h: 0, s: 100, l: 50 });         // true (HSL)
       * Color.isColorLike({ h: 0, s: 100, l: 50, a: 0.5 }); // true (HSLA)
       * Color.isColorLike({ h: 0, s: 100, v: 100 });        // true (HSV)
       * Color.isColorLike({ h: 0, s: 100, v: 100, a: 0.5 });// true (HSVA)
       *
       * // Color instances
       * Color.isColorLike(new Color('red')); // true
       *
       * // Invalid values
       * Color.isColorLike(null);           // false
       * Color.isColorLike(undefined);      // false
       * Color.isColorLike({});             // false
       * Color.isColorLike([]);             // false
       * Color.isColorLike('not-a-color');  // false
       * ```
       * @remarks
       * Checks for the following formats:
       * - Numbers (0x000000 to 0xffffff)
       * - CSS color strings
       * - RGB/RGBA arrays and objects
       * - HSL/HSLA objects
       * - HSV/HSVA objects
       * - TypedArrays (Float32Array, Uint8Array, Uint8ClampedArray)
       * - Color instances
       * @see {@link ColorSource} For supported color format types
       * @see {@link Color.setValue} For setting color values
       * @category utility
       */
      static isColorLike(value) {
        return typeof value === "number" || typeof value === "string" || value instanceof Number || value instanceof _Color || Array.isArray(value) || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Float32Array || value.r !== void 0 && value.g !== void 0 && value.b !== void 0 || value.r !== void 0 && value.g !== void 0 && value.b !== void 0 && value.a !== void 0 || value.h !== void 0 && value.s !== void 0 && value.l !== void 0 || value.h !== void 0 && value.s !== void 0 && value.l !== void 0 && value.a !== void 0 || value.h !== void 0 && value.s !== void 0 && value.v !== void 0 || value.h !== void 0 && value.s !== void 0 && value.v !== void 0 && value.a !== void 0;
      }
    };
    /**
     * Static shared Color instance used for utility operations. This is a singleton color object
     * that can be reused to avoid creating unnecessary Color instances.
     * > [!IMPORTANT] You should be careful when using this shared instance, as it is mutable and can be
     * > changed by any code that uses it.
     * >
     * > It is best used for one-off color operations or temporary transformations.
     * > For persistent colors, create your own Color instance instead.
     * @example
     * ```ts
     * import { Color } from 'pixi.js';
     *
     * // Use shared instance for one-off color operations
     * Color.shared.setValue(0xff0000);
     * const redHex = Color.shared.toHex();     // "#ff0000"
     * const redRgb = Color.shared.toRgbArray(); // [1, 0, 0]
     *
     * // Temporary color transformations
     * const colorNumber = Color.shared
     *     .setValue('#ff0000')     // Set to red
     *     .setAlpha(0.5)          // Make semi-transparent
     *     .premultiply(0.8)       // Apply premultiplication
     *     .toNumber();            // Convert to number
     *
     * // Chain multiple operations
     * const result = Color.shared
     *     .setValue(someColor)
     *     .multiply(tintColor)
     *     .toPremultiplied(alpha);
     * ```
     * @remarks
     * - This is a shared instance - be careful about multiple code paths using it simultaneously
     * - Use for temporary color operations to avoid allocating new Color instances
     * - The value is preserved between operations, so reset if needed
     * - For persistent colors, create your own Color instance instead
     */
    _Color.shared = new _Color();
    /**
     * Temporary Color object for static uses internally.
     * As to not conflict with Color.shared.
     * @ignore
     */
    _Color._temp = new _Color();
    /** Pattern for hex strings */
    // eslint-disable-next-line @typescript-eslint/naming-convention
    _Color.HEX_PATTERN = /^(#|0x)?(([a-f0-9]{3}){1,2}([a-f0-9]{2})?)$/i;
    let Color = _Color;

    "use strict";
    const cullingMixin = {
      cullArea: null,
      cullable: false,
      cullableChildren: true
    };

    "use strict";
    const GlobalResourceRegistry = {
      /**
       * Set of registered pools and cleanable objects.
       * @private
       */
      _registeredResources: /* @__PURE__ */ new Set(),
      /**
       * Registers a pool or cleanable object for cleanup.
       * @param {Cleanable} pool - The pool or object to register.
       */
      register(pool) {
        this._registeredResources.add(pool);
      },
      /**
       * Unregisters a pool or cleanable object from cleanup.
       * @param {Cleanable} pool - The pool or object to unregister.
       */
      unregister(pool) {
        this._registeredResources.delete(pool);
      },
      /** Clears all registered pools and cleanable objects. This will call clear() on each registered item. */
      release() {
        this._registeredResources.forEach((pool) => pool.clear());
      },
      /**
       * Gets the number of registered pools and cleanable objects.
       * @returns {number} The count of registered items.
       */
      get registeredCount() {
        return this._registeredResources.size;
      },
      /**
       * Checks if a specific pool or cleanable object is registered.
       * @param {Cleanable} pool - The pool or object to check.
       * @returns {boolean} True if the item is registered, false otherwise.
       */
      isRegistered(pool) {
        return this._registeredResources.has(pool);
      },
      /**
       * Removes all registrations without clearing the pools.
       * Useful if you want to reset the collector without affecting the pools.
       */
      reset() {
        this._registeredResources.clear();
      }
    };

    "use strict";
    class Pool {
      /**
       * Constructs a new Pool.
       * @param ClassType - The constructor of the items in the pool.
       * @param {number} [initialSize] - The initial size of the pool.
       */
      constructor(ClassType, initialSize) {
        this._pool = [];
        this._count = 0;
        this._index = 0;
        this._classType = ClassType;
        if (initialSize) {
          this.prepopulate(initialSize);
        }
      }
      /**
       * Prepopulates the pool with a given number of items.
       * @param total - The number of items to add to the pool.
       */
      prepopulate(total) {
        for (let i = 0; i < total; i++) {
          this._pool[this._index++] = new this._classType();
        }
        this._count += total;
      }
      /**
       * Gets an item from the pool. Calls the item's `init` method if it exists.
       * If there are no items left in the pool, a new one will be created.
       * @param {unknown} [data] - Optional data to pass to the item's constructor.
       * @returns {T} The item from the pool.
       */
      get(data) {
        var _a;
        let item;
        if (this._index > 0) {
          item = this._pool[--this._index];
        } else {
          item = new this._classType();
          this._count++;
        }
        (_a = item.init) == null ? void 0 : _a.call(item, data);
        return item;
      }
      /**
       * Returns an item to the pool. Calls the item's `reset` method if it exists.
       * @param {T} item - The item to return to the pool.
       */
      return(item) {
        var _a;
        (_a = item.reset) == null ? void 0 : _a.call(item);
        this._pool[this._index++] = item;
      }
      /**
       * Gets the number of items in the pool.
       * @readonly
       */
      get totalSize() {
        return this._count;
      }
      /**
       * Gets the number of items in the pool that are free to use without needing to create more.
       * @readonly
       */
      get totalFree() {
        return this._index;
      }
      /**
       * Gets the number of items in the pool that are currently in use.
       * @readonly
       */
      get totalUsed() {
        return this._count - this._index;
      }
      /** clears the pool */
      clear() {
        if (this._pool.length > 0 && this._pool[0].destroy) {
          for (let i = 0; i < this._index; i++) {
            this._pool[i].destroy();
          }
        }
        this._pool.length = 0;
        this._count = 0;
        this._index = 0;
      }
    }

    "use strict";
    class PoolGroupClass {
      constructor() {
        /**
         * A map to store the pools by their class type.
         * @private
         */
        this._poolsByClass = /* @__PURE__ */ new Map();
      }
      /**
       * Prepopulates a specific pool with a given number of items.
       * @template T The type of items in the pool. Must extend PoolItem.
       * @param {PoolItemConstructor<T>} Class - The constructor of the items in the pool.
       * @param {number} total - The number of items to add to the pool.
       */
      prepopulate(Class, total) {
        const classPool = this.getPool(Class);
        classPool.prepopulate(total);
      }
      /**
       * Gets an item from a specific pool.
       * @template T The type of items in the pool. Must extend PoolItem.
       * @param {PoolItemConstructor<T>} Class - The constructor of the items in the pool.
       * @param {unknown} [data] - Optional data to pass to the item's constructor.
       * @returns {T} The item from the pool.
       */
      get(Class, data) {
        const pool = this.getPool(Class);
        return pool.get(data);
      }
      /**
       * Returns an item to its respective pool.
       * @param {PoolItem} item - The item to return to the pool.
       */
      return(item) {
        const pool = this.getPool(item.constructor);
        pool.return(item);
      }
      /**
       * Gets a specific pool based on the class type.
       * @template T The type of items in the pool. Must extend PoolItem.
       * @param {PoolItemConstructor<T>} ClassType - The constructor of the items in the pool.
       * @returns {Pool<T>} The pool of the given class type.
       */
      getPool(ClassType) {
        if (!this._poolsByClass.has(ClassType)) {
          this._poolsByClass.set(ClassType, new Pool(ClassType));
        }
        return this._poolsByClass.get(ClassType);
      }
      /** gets the usage stats of each pool in the system */
      stats() {
        const stats = {};
        this._poolsByClass.forEach((pool) => {
          const name = stats[pool._classType.name] ? pool._classType.name + pool._classType.ID : pool._classType.name;
          stats[name] = {
            free: pool.totalFree,
            used: pool.totalUsed,
            size: pool.totalSize
          };
        });
        return stats;
      }
      /** Clears all pools in the group. This will reset all pools and free their resources. */
      clear() {
        this._poolsByClass.forEach((pool) => pool.clear());
        this._poolsByClass.clear();
      }
    }
    const BigPool = new PoolGroupClass();
    GlobalResourceRegistry.register(BigPool);

    "use strict";
    const cacheAsTextureMixin = {
      get isCachedAsTexture() {
        var _a;
        return !!((_a = this.renderGroup) == null ? void 0 : _a.isCachedAsTexture);
      },
      cacheAsTexture(val) {
        if (typeof val === "boolean" && val === false) {
          this.disableRenderGroup();
        } else {
          this.enableRenderGroup();
          this.renderGroup.enableCacheAsTexture(val === true ? {} : val);
        }
      },
      updateCacheTexture() {
        var _a;
        (_a = this.renderGroup) == null ? void 0 : _a.updateCacheTexture();
      },
      get cacheAsBitmap() {
        return this.isCachedAsTexture;
      },
      set cacheAsBitmap(val) {
        deprecation("v8.6.0", "cacheAsBitmap is deprecated, use cacheAsTexture instead.");
        this.cacheAsTexture(val);
      }
    };

    "use strict";
    function removeItems(arr, startIdx, removeCount) {
      const length = arr.length;
      let i;
      if (startIdx >= length || removeCount === 0) {
        return;
      }
      removeCount = startIdx + removeCount > length ? length - startIdx : removeCount;
      const len = length - removeCount;
      for (i = startIdx; i < len; ++i) {
        arr[i] = arr[i + removeCount];
      }
      arr.length = len;
    }

    "use strict";
    const childrenHelperMixin = {
      allowChildren: true,
      removeChildren(beginIndex = 0, endIndex) {
        var _a;
        const end = endIndex != null ? endIndex : this.children.length;
        const range = end - beginIndex;
        const removed = [];
        if (range > 0 && range <= end) {
          for (let i = end - 1; i >= beginIndex; i--) {
            const child = this.children[i];
            if (!child)
              continue;
            removed.push(child);
            child.parent = null;
          }
          removeItems(this.children, beginIndex, end);
          const renderGroup = this.renderGroup || this.parentRenderGroup;
          if (renderGroup) {
            renderGroup.removeChildren(removed);
          }
          for (let i = 0; i < removed.length; ++i) {
            const child = removed[i];
            (_a = child.parentRenderLayer) == null ? void 0 : _a.detach(child);
            this.emit("childRemoved", child, this, i);
            removed[i].emit("removed", this);
          }
          if (removed.length > 0) {
            this._didViewChangeTick++;
          }
          return removed;
        } else if (range === 0 && this.children.length === 0) {
          return removed;
        }
        throw new RangeError("removeChildren: numeric values are outside the acceptable range.");
      },
      removeChildAt(index) {
        const child = this.getChildAt(index);
        return this.removeChild(child);
      },
      getChildAt(index) {
        if (index < 0 || index >= this.children.length) {
          throw new Error(`getChildAt: Index (${index}) does not exist.`);
        }
        return this.children[index];
      },
      setChildIndex(child, index) {
        if (index < 0 || index >= this.children.length) {
          throw new Error(`The index ${index} supplied is out of bounds ${this.children.length}`);
        }
        this.getChildIndex(child);
        this.addChildAt(child, index);
      },
      getChildIndex(child) {
        const index = this.children.indexOf(child);
        if (index === -1) {
          throw new Error("The supplied Container must be a child of the caller");
        }
        return index;
      },
      addChildAt(child, index) {
        if (!this.allowChildren) {
          deprecation(v8_0_0, "addChildAt: Only Containers will be allowed to add children in v8.0.0");
        }
        const { children } = this;
        if (index < 0 || index > children.length) {
          throw new Error(`${child}addChildAt: The index ${index} supplied is out of bounds ${children.length}`);
        }
        if (child.parent) {
          const currentIndex = child.parent.children.indexOf(child);
          if (child.parent === this && currentIndex === index) {
            return child;
          }
          if (currentIndex !== -1) {
            child.parent.children.splice(currentIndex, 1);
          }
        }
        if (index === children.length) {
          children.push(child);
        } else {
          children.splice(index, 0, child);
        }
        child.parent = this;
        child.didChange = true;
        child._updateFlags = 15;
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (renderGroup) {
          renderGroup.addChild(child);
        }
        if (this.sortableChildren)
          this.sortDirty = true;
        this.emit("childAdded", child, this, index);
        child.emit("added", this);
        return child;
      },
      swapChildren(child, child2) {
        if (child === child2) {
          return;
        }
        const index1 = this.getChildIndex(child);
        const index2 = this.getChildIndex(child2);
        this.children[index1] = child2;
        this.children[index2] = child;
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (renderGroup) {
          renderGroup.structureDidChange = true;
        }
        this._didContainerChangeTick++;
      },
      removeFromParent() {
        var _a;
        (_a = this.parent) == null ? void 0 : _a.removeChild(this);
      },
      reparentChild(...child) {
        if (child.length === 1) {
          return this.reparentChildAt(child[0], this.children.length);
        }
        child.forEach((c) => this.reparentChildAt(c, this.children.length));
        return child[0];
      },
      reparentChildAt(child, index) {
        if (child.parent === this) {
          this.setChildIndex(child, index);
          return child;
        }
        const childMat = child.worldTransform.clone();
        child.removeFromParent();
        this.addChildAt(child, index);
        const newMatrix = this.worldTransform.clone();
        newMatrix.invert();
        childMat.prepend(newMatrix);
        child.setFromMatrix(childMat);
        return child;
      },
      replaceChild(oldChild, newChild) {
        oldChild.updateLocalTransform();
        this.addChildAt(newChild, this.getChildIndex(oldChild));
        newChild.setFromMatrix(oldChild.localTransform);
        newChild.updateLocalTransform();
        this.removeChild(oldChild);
      }
    };

    "use strict";
    const collectRenderablesMixin = {
      collectRenderables(instructionSet, renderer, currentLayer) {
        if (this.parentRenderLayer && this.parentRenderLayer !== currentLayer || this.globalDisplayStatus < 7 || !this.includeInBuild)
          return;
        if (this.sortableChildren) {
          this.sortChildren();
        }
        if (this.isSimple) {
          this.collectRenderablesSimple(instructionSet, renderer, currentLayer);
        } else if (this.renderGroup) {
          renderer.renderPipes.renderGroup.addRenderGroup(this.renderGroup, instructionSet);
        } else {
          this.collectRenderablesWithEffects(instructionSet, renderer, currentLayer);
        }
      },
      collectRenderablesSimple(instructionSet, renderer, currentLayer) {
        const children = this.children;
        const length = children.length;
        for (let i = 0; i < length; i++) {
          children[i].collectRenderables(instructionSet, renderer, currentLayer);
        }
      },
      collectRenderablesWithEffects(instructionSet, renderer, currentLayer) {
        const { renderPipes } = renderer;
        for (let i = 0; i < this.effects.length; i++) {
          const effect = this.effects[i];
          const pipe = renderPipes[effect.pipe];
          pipe.push(effect, this, instructionSet);
        }
        this.collectRenderablesSimple(instructionSet, renderer, currentLayer);
        for (let i = this.effects.length - 1; i >= 0; i--) {
          const effect = this.effects[i];
          const pipe = renderPipes[effect.pipe];
          pipe.pop(effect, this, instructionSet);
        }
      }
    };

    "use strict";
    class FilterEffect {
      constructor() {
        /** the pipe that knows how to handle this effect */
        this.pipe = "filter";
        /** the priority of this effect */
        this.priority = 1;
      }
      destroy() {
        for (let i = 0; i < this.filters.length; i++) {
          this.filters[i].destroy();
        }
        this.filters = null;
        this.filterArea = null;
      }
    }

    "use strict";
    class MaskEffectManagerClass {
      constructor() {
        /** @private */
        this._effectClasses = [];
        this._tests = [];
        this._initialized = false;
      }
      init() {
        if (this._initialized)
          return;
        this._initialized = true;
        this._effectClasses.forEach((test) => {
          this.add({
            test: test.test,
            maskClass: test
          });
        });
      }
      add(test) {
        this._tests.push(test);
      }
      getMaskEffect(item) {
        if (!this._initialized)
          this.init();
        for (let i = 0; i < this._tests.length; i++) {
          const test = this._tests[i];
          if (test.test(item)) {
            return BigPool.get(test.maskClass, item);
          }
        }
        return item;
      }
      returnMaskEffect(effect) {
        BigPool.return(effect);
      }
    }
    const MaskEffectManager = new MaskEffectManagerClass();
    extensions.handleByList(ExtensionType.MaskEffect, MaskEffectManager._effectClasses);

    "use strict";
    var __defProp$17 = Object.defineProperty;
    var __getOwnPropSymbols$19 = Object.getOwnPropertySymbols;
    var __hasOwnProp$19 = Object.prototype.hasOwnProperty;
    var __propIsEnum$19 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$17 = (obj, key, value) => key in obj ? __defProp$17(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$17 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$19.call(b, prop))
          __defNormalProp$17(a, prop, b[prop]);
      if (__getOwnPropSymbols$19)
        for (var prop of __getOwnPropSymbols$19(b)) {
          if (__propIsEnum$19.call(b, prop))
            __defNormalProp$17(a, prop, b[prop]);
        }
      return a;
    };
    const effectsMixin = {
      _maskEffect: null,
      _maskOptions: {
        inverse: false
      },
      _filterEffect: null,
      effects: [],
      _markStructureAsChanged() {
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (renderGroup) {
          renderGroup.structureDidChange = true;
        }
      },
      addEffect(effect) {
        const index = this.effects.indexOf(effect);
        if (index !== -1)
          return;
        this.effects.push(effect);
        this.effects.sort((a, b) => a.priority - b.priority);
        this._markStructureAsChanged();
        this._updateIsSimple();
      },
      removeEffect(effect) {
        const index = this.effects.indexOf(effect);
        if (index === -1)
          return;
        this.effects.splice(index, 1);
        this._markStructureAsChanged();
        this._updateIsSimple();
      },
      set mask(value) {
        const effect = this._maskEffect;
        if ((effect == null ? void 0 : effect.mask) === value)
          return;
        if (effect) {
          this.removeEffect(effect);
          MaskEffectManager.returnMaskEffect(effect);
          this._maskEffect = null;
        }
        if (value === null || value === void 0)
          return;
        this._maskEffect = MaskEffectManager.getMaskEffect(value);
        this.addEffect(this._maskEffect);
      },
      get mask() {
        var _a;
        return (_a = this._maskEffect) == null ? void 0 : _a.mask;
      },
      setMask(options) {
        this._maskOptions = __spreadValues$17(__spreadValues$17({}, this._maskOptions), options);
        if (options.mask) {
          this.mask = options.mask;
        }
        this._markStructureAsChanged();
      },
      set filters(value) {
        var _a;
        if (!Array.isArray(value) && value)
          value = [value];
        const effect = this._filterEffect || (this._filterEffect = new FilterEffect());
        value = value;
        const hasFilters = (value == null ? void 0 : value.length) > 0;
        const hadFilters = ((_a = effect.filters) == null ? void 0 : _a.length) > 0;
        const didChange = hasFilters !== hadFilters;
        value = Array.isArray(value) ? value.slice(0) : value;
        effect.filters = Object.freeze(value);
        if (didChange) {
          if (hasFilters) {
            this.addEffect(effect);
          } else {
            this.removeEffect(effect);
            effect.filters = value != null ? value : null;
          }
        }
      },
      get filters() {
        var _a;
        return (_a = this._filterEffect) == null ? void 0 : _a.filters;
      },
      set filterArea(value) {
        this._filterEffect || (this._filterEffect = new FilterEffect());
        this._filterEffect.filterArea = value;
      },
      get filterArea() {
        var _a;
        return (_a = this._filterEffect) == null ? void 0 : _a.filterArea;
      }
    };

    "use strict";
    const findMixin = {
      label: null,
      get name() {
        deprecation(v8_0_0, "Container.name property has been removed, use Container.label instead");
        return this.label;
      },
      set name(value) {
        deprecation(v8_0_0, "Container.name property has been removed, use Container.label instead");
        this.label = value;
      },
      getChildByName(name, deep = false) {
        return this.getChildByLabel(name, deep);
      },
      getChildByLabel(label, deep = false) {
        const children = this.children;
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          if (child.label === label || label instanceof RegExp && label.test(child.label))
            return child;
        }
        if (deep) {
          for (let i = 0; i < children.length; i++) {
            const child = children[i];
            const found = child.getChildByLabel(label, true);
            if (found) {
              return found;
            }
          }
        }
        return null;
      },
      getChildrenByLabel(label, deep = false, out = []) {
        const children = this.children;
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          if (child.label === label || label instanceof RegExp && label.test(child.label)) {
            out.push(child);
          }
        }
        if (deep) {
          for (let i = 0; i < children.length; i++) {
            children[i].getChildrenByLabel(label, true, out);
          }
        }
        return out;
      }
    };

    "use strict";
    const matrixPool = BigPool.getPool(Matrix);
    const boundsPool = BigPool.getPool(Bounds);

    "use strict";
    const tempMatrix$5 = new Matrix();
    const getFastGlobalBoundsMixin = {
      getFastGlobalBounds(factorRenderLayers, bounds) {
        bounds || (bounds = new Bounds());
        bounds.clear();
        this._getGlobalBoundsRecursive(!!factorRenderLayers, bounds, this.parentRenderLayer);
        if (!bounds.isValid) {
          bounds.set(0, 0, 0, 0);
        }
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        bounds.applyMatrix(renderGroup.worldTransform);
        return bounds;
      },
      _getGlobalBoundsRecursive(factorRenderLayers, bounds, currentLayer) {
        let localBounds = bounds;
        if (factorRenderLayers && this.parentRenderLayer && this.parentRenderLayer !== currentLayer)
          return;
        if (this.localDisplayStatus !== 7 || !this.measurable) {
          return;
        }
        const manageEffects = !!this.effects.length;
        if (this.renderGroup || manageEffects) {
          localBounds = boundsPool.get().clear();
        }
        if (this.boundsArea) {
          bounds.addRect(this.boundsArea, this.worldTransform);
        } else {
          if (this.renderPipeId) {
            const viewBounds = this.bounds;
            localBounds.addFrame(
              viewBounds.minX,
              viewBounds.minY,
              viewBounds.maxX,
              viewBounds.maxY,
              this.groupTransform
            );
          }
          const children = this.children;
          for (let i = 0; i < children.length; i++) {
            children[i]._getGlobalBoundsRecursive(factorRenderLayers, localBounds, currentLayer);
          }
        }
        if (manageEffects) {
          let advanced = false;
          const renderGroup = this.renderGroup || this.parentRenderGroup;
          for (let i = 0; i < this.effects.length; i++) {
            if (this.effects[i].addBounds) {
              if (!advanced) {
                advanced = true;
                localBounds.applyMatrix(renderGroup.worldTransform);
              }
              this.effects[i].addBounds(localBounds, true);
            }
          }
          if (advanced) {
            localBounds.applyMatrix(renderGroup.worldTransform.copyTo(tempMatrix$5).invert());
          }
          bounds.addBounds(localBounds);
          boundsPool.return(localBounds);
        } else if (this.renderGroup) {
          bounds.addBounds(localBounds, this.relativeGroupTransform);
          boundsPool.return(localBounds);
        }
      }
    };

    "use strict";
    function getGlobalBounds(target, skipUpdateTransform, bounds) {
      bounds.clear();
      let parentTransform;
      let pooledMatrix;
      if (target.parent) {
        if (!skipUpdateTransform) {
          pooledMatrix = matrixPool.get().identity();
          parentTransform = updateTransformBackwards(target, pooledMatrix);
        } else {
          parentTransform = target.parent.worldTransform;
        }
      } else {
        parentTransform = Matrix.IDENTITY;
      }
      _getGlobalBounds(target, bounds, parentTransform, skipUpdateTransform);
      if (pooledMatrix) {
        matrixPool.return(pooledMatrix);
      }
      if (!bounds.isValid) {
        bounds.set(0, 0, 0, 0);
      }
      return bounds;
    }
    function _getGlobalBounds(target, bounds, parentTransform, skipUpdateTransform) {
      var _a, _b;
      if (!target.visible || !target.measurable)
        return;
      let worldTransform;
      if (!skipUpdateTransform) {
        target.updateLocalTransform();
        worldTransform = matrixPool.get();
        worldTransform.appendFrom(target.localTransform, parentTransform);
      } else {
        worldTransform = target.worldTransform;
      }
      const parentBounds = bounds;
      const preserveBounds = !!target.effects.length;
      if (preserveBounds) {
        bounds = boundsPool.get().clear();
      }
      if (target.boundsArea) {
        bounds.addRect(target.boundsArea, worldTransform);
      } else {
        const renderableBounds = target.bounds;
        if (renderableBounds && !renderableBounds.isEmpty()) {
          bounds.matrix = worldTransform;
          bounds.addBounds(renderableBounds);
        }
        for (let i = 0; i < target.children.length; i++) {
          _getGlobalBounds(target.children[i], bounds, worldTransform, skipUpdateTransform);
        }
      }
      if (preserveBounds) {
        for (let i = 0; i < target.effects.length; i++) {
          (_b = (_a = target.effects[i]).addBounds) == null ? void 0 : _b.call(_a, bounds);
        }
        parentBounds.addBounds(bounds, Matrix.IDENTITY);
        boundsPool.return(bounds);
      }
      if (!skipUpdateTransform) {
        matrixPool.return(worldTransform);
      }
    }
    function updateTransformBackwards(target, parentTransform) {
      const parent = target.parent;
      if (parent) {
        updateTransformBackwards(parent, parentTransform);
        parent.updateLocalTransform();
        parentTransform.append(parent.localTransform);
      }
      return parentTransform;
    }

    "use strict";
    function multiplyHexColors(color1, color2) {
      if (color1 === 16777215 || !color2)
        return color2;
      if (color2 === 16777215 || !color1)
        return color1;
      const r1 = color1 >> 16 & 255;
      const g1 = color1 >> 8 & 255;
      const b1 = color1 & 255;
      const r2 = color2 >> 16 & 255;
      const g2 = color2 >> 8 & 255;
      const b2 = color2 & 255;
      const r = r1 * r2 / 255 | 0;
      const g = g1 * g2 / 255 | 0;
      const b = b1 * b2 / 255 | 0;
      return (r << 16) + (g << 8) + b;
    }

    "use strict";
    const WHITE_BGR = 16777215;
    function multiplyColors(localBGRColor, parentBGRColor) {
      if (localBGRColor === WHITE_BGR) {
        return parentBGRColor;
      }
      if (parentBGRColor === WHITE_BGR) {
        return localBGRColor;
      }
      return multiplyHexColors(localBGRColor, parentBGRColor);
    }

    "use strict";
    function bgr2rgb(color) {
      return ((color & 255) << 16) + (color & 65280) + (color >> 16 & 255);
    }
    const getGlobalMixin = {
      getGlobalAlpha(skipUpdate) {
        if (skipUpdate) {
          if (this.renderGroup) {
            return this.renderGroup.worldAlpha;
          }
          if (this.parentRenderGroup) {
            return this.parentRenderGroup.worldAlpha * this.alpha;
          }
          return this.alpha;
        }
        let alpha = this.alpha;
        let current = this.parent;
        while (current) {
          alpha *= current.alpha;
          current = current.parent;
        }
        return alpha;
      },
      getGlobalTransform(matrix = new Matrix(), skipUpdate) {
        if (skipUpdate) {
          return matrix.copyFrom(this.worldTransform);
        }
        this.updateLocalTransform();
        const parentTransform = updateTransformBackwards(this, matrixPool.get().identity());
        matrix.appendFrom(this.localTransform, parentTransform);
        matrixPool.return(parentTransform);
        return matrix;
      },
      getGlobalTint(skipUpdate) {
        if (skipUpdate) {
          if (this.renderGroup) {
            return bgr2rgb(this.renderGroup.worldColor);
          }
          if (this.parentRenderGroup) {
            return bgr2rgb(
              multiplyColors(this.localColor, this.parentRenderGroup.worldColor)
            );
          }
          return this.tint;
        }
        let color = this.localColor;
        let parent = this.parent;
        while (parent) {
          color = multiplyColors(color, parent.localColor);
          parent = parent.parent;
        }
        return bgr2rgb(color);
      }
    };

    "use strict";
    function getLocalBounds(target, bounds, relativeMatrix) {
      bounds.clear();
      relativeMatrix || (relativeMatrix = Matrix.IDENTITY);
      _getLocalBounds(target, bounds, relativeMatrix, target, true);
      if (!bounds.isValid) {
        bounds.set(0, 0, 0, 0);
      }
      return bounds;
    }
    function _getLocalBounds(target, bounds, parentTransform, rootContainer, isRoot) {
      var _a, _b;
      let relativeTransform;
      if (!isRoot) {
        if (!target.visible || !target.measurable)
          return;
        target.updateLocalTransform();
        const localTransform = target.localTransform;
        relativeTransform = matrixPool.get();
        relativeTransform.appendFrom(localTransform, parentTransform);
      } else {
        relativeTransform = matrixPool.get();
        relativeTransform = parentTransform.copyTo(relativeTransform);
      }
      const parentBounds = bounds;
      const preserveBounds = !!target.effects.length;
      if (preserveBounds) {
        bounds = boundsPool.get().clear();
      }
      if (target.boundsArea) {
        bounds.addRect(target.boundsArea, relativeTransform);
      } else {
        if (target.renderPipeId) {
          bounds.matrix = relativeTransform;
          bounds.addBounds(target.bounds);
        }
        const children = target.children;
        for (let i = 0; i < children.length; i++) {
          _getLocalBounds(children[i], bounds, relativeTransform, rootContainer, false);
        }
      }
      if (preserveBounds) {
        for (let i = 0; i < target.effects.length; i++) {
          (_b = (_a = target.effects[i]).addLocalBounds) == null ? void 0 : _b.call(_a, bounds, rootContainer);
        }
        parentBounds.addBounds(bounds, Matrix.IDENTITY);
        boundsPool.return(bounds);
      }
      matrixPool.return(relativeTransform);
    }

    "use strict";
    function checkChildrenDidChange(container, previousData) {
      const children = container.children;
      for (let i = 0; i < children.length; i++) {
        const child = children[i];
        const uid = child.uid;
        const didChange = (child._didViewChangeTick & 65535) << 16 | child._didContainerChangeTick & 65535;
        const index = previousData.index;
        if (previousData.data[index] !== uid || previousData.data[index + 1] !== didChange) {
          previousData.data[previousData.index] = uid;
          previousData.data[previousData.index + 1] = didChange;
          previousData.didChange = true;
        }
        previousData.index = index + 2;
        if (child.children.length) {
          checkChildrenDidChange(child, previousData);
        }
      }
      return previousData.didChange;
    }

    "use strict";
    const tempMatrix$4 = new Matrix();
    const measureMixin = {
      _localBoundsCacheId: -1,
      _localBoundsCacheData: null,
      _setWidth(value, localWidth) {
        const sign = Math.sign(this.scale.x) || 1;
        if (localWidth !== 0) {
          this.scale.x = value / localWidth * sign;
        } else {
          this.scale.x = sign;
        }
      },
      _setHeight(value, localHeight) {
        const sign = Math.sign(this.scale.y) || 1;
        if (localHeight !== 0) {
          this.scale.y = value / localHeight * sign;
        } else {
          this.scale.y = sign;
        }
      },
      getLocalBounds() {
        if (!this._localBoundsCacheData) {
          this._localBoundsCacheData = {
            data: [],
            index: 1,
            didChange: false,
            localBounds: new Bounds()
          };
        }
        const localBoundsCacheData = this._localBoundsCacheData;
        localBoundsCacheData.index = 1;
        localBoundsCacheData.didChange = false;
        if (localBoundsCacheData.data[0] !== this._didViewChangeTick) {
          localBoundsCacheData.didChange = true;
          localBoundsCacheData.data[0] = this._didViewChangeTick;
        }
        checkChildrenDidChange(this, localBoundsCacheData);
        if (localBoundsCacheData.didChange) {
          getLocalBounds(this, localBoundsCacheData.localBounds, tempMatrix$4);
        }
        return localBoundsCacheData.localBounds;
      },
      getBounds(skipUpdate, bounds) {
        return getGlobalBounds(this, skipUpdate, bounds || new Bounds());
      }
    };

    "use strict";
    const onRenderMixin = {
      _onRender: null,
      set onRender(func) {
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (!func) {
          if (this._onRender) {
            renderGroup == null ? void 0 : renderGroup.removeOnRender(this);
          }
          this._onRender = null;
          return;
        }
        if (!this._onRender) {
          renderGroup == null ? void 0 : renderGroup.addOnRender(this);
        }
        this._onRender = func;
      },
      get onRender() {
        return this._onRender;
      }
    };

    "use strict";
    const sortMixin = {
      _zIndex: 0,
      sortDirty: false,
      sortableChildren: false,
      get zIndex() {
        return this._zIndex;
      },
      set zIndex(value) {
        if (this._zIndex === value)
          return;
        this._zIndex = value;
        this.depthOfChildModified();
      },
      depthOfChildModified() {
        if (this.parent) {
          this.parent.sortableChildren = true;
          this.parent.sortDirty = true;
        }
        if (this.parentRenderGroup) {
          this.parentRenderGroup.structureDidChange = true;
        }
      },
      sortChildren() {
        if (!this.sortDirty)
          return;
        this.sortDirty = false;
        this.children.sort(sortChildren);
      }
    };
    function sortChildren(a, b) {
      return a._zIndex - b._zIndex;
    }

    "use strict";
    const toLocalGlobalMixin = {
      getGlobalPosition(point = new Point(), skipUpdate = false) {
        if (this.parent) {
          this.parent.toGlobal(this._position, point, skipUpdate);
        } else {
          point.x = this._position.x;
          point.y = this._position.y;
        }
        return point;
      },
      toGlobal(position, point, skipUpdate = false) {
        const globalMatrix = this.getGlobalTransform(matrixPool.get(), skipUpdate);
        point = globalMatrix.apply(position, point);
        matrixPool.return(globalMatrix);
        return point;
      },
      toLocal(position, from, point, skipUpdate) {
        if (from) {
          position = from.toGlobal(position, point, skipUpdate);
        }
        const globalMatrix = this.getGlobalTransform(matrixPool.get(), skipUpdate);
        point = globalMatrix.applyInverse(position, point);
        matrixPool.return(globalMatrix);
        return point;
      }
    };

    "use strict";
    class InstructionSet {
      constructor() {
        /** a unique id for this instruction set used through the renderer */
        this.uid = uid$1("instructionSet");
        /** the array of instructions */
        this.instructions = [];
        /** the actual size of the array (any instructions passed this should be ignored) */
        this.instructionSize = 0;
        this.renderables = [];
        /** used by the garbage collector to track when the instruction set was last used */
        this.gcTick = 0;
      }
      /** reset the instruction set so it can be reused set size back to 0 */
      reset() {
        this.instructionSize = 0;
      }
      /**
       * Destroy the instruction set, clearing the instructions and renderables.
       * @internal
       */
      destroy() {
        this.instructions.length = 0;
        this.renderables.length = 0;
        this.renderPipes = null;
        this.gcTick = 0;
      }
      /**
       * Add an instruction to the set
       * @param instruction - add an instruction to the set
       */
      add(instruction) {
        this.instructions[this.instructionSize++] = instruction;
      }
      /**
       * Log the instructions to the console (for debugging)
       * @internal
       */
      log() {
        this.instructions.length = this.instructionSize;
        console.table(this.instructions, ["type", "action"]);
      }
    }

    "use strict";
    var __defProp$16 = Object.defineProperty;
    var __defProps$r = Object.defineProperties;
    var __getOwnPropDescs$r = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$18 = Object.getOwnPropertySymbols;
    var __hasOwnProp$18 = Object.prototype.hasOwnProperty;
    var __propIsEnum$18 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$16 = (obj, key, value) => key in obj ? __defProp$16(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$16 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$18.call(b, prop))
          __defNormalProp$16(a, prop, b[prop]);
      if (__getOwnPropSymbols$18)
        for (var prop of __getOwnPropSymbols$18(b)) {
          if (__propIsEnum$18.call(b, prop))
            __defNormalProp$16(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$r = (a, b) => __defProps$r(a, __getOwnPropDescs$r(b));
    let count = 0;
    class TexturePoolClass {
      /**
       * @param textureOptions - options that will be passed to BaseRenderTexture constructor
       * @param {SCALE_MODE} [textureOptions.scaleMode] - See {@link SCALE_MODE} for possible values.
       */
      constructor(textureOptions) {
        this._poolKeyHash = /* @__PURE__ */ Object.create(null);
        this._texturePool = {};
        this.textureOptions = textureOptions || {};
        this.enableFullScreen = false;
        this.textureStyle = new TextureStyle(this.textureOptions);
      }
      /**
       * Creates texture with params that were specified in pool constructor.
       * @param pixelWidth - Width of texture in pixels.
       * @param pixelHeight - Height of texture in pixels.
       * @param antialias
       */
      createTexture(pixelWidth, pixelHeight, antialias) {
        const textureSource = new TextureSource(__spreadProps$r(__spreadValues$16({}, this.textureOptions), {
          width: pixelWidth,
          height: pixelHeight,
          resolution: 1,
          antialias,
          autoGarbageCollect: false
        }));
        return new Texture({
          source: textureSource,
          label: `texturePool_${count++}`
        });
      }
      /**
       * Gets a Power-of-Two render texture or fullScreen texture
       * @param frameWidth - The minimum width of the render texture.
       * @param frameHeight - The minimum height of the render texture.
       * @param resolution - The resolution of the render texture.
       * @param antialias
       * @returns The new render texture.
       */
      getOptimalTexture(frameWidth, frameHeight, resolution = 1, antialias) {
        let po2Width = Math.ceil(frameWidth * resolution - 1e-6);
        let po2Height = Math.ceil(frameHeight * resolution - 1e-6);
        po2Width = nextPow2(po2Width);
        po2Height = nextPow2(po2Height);
        const key = (po2Width << 17) + (po2Height << 1) + (antialias ? 1 : 0);
        if (!this._texturePool[key]) {
          this._texturePool[key] = [];
        }
        let texture = this._texturePool[key].pop();
        if (!texture) {
          texture = this.createTexture(po2Width, po2Height, antialias);
        }
        texture.source._resolution = resolution;
        texture.source.width = po2Width / resolution;
        texture.source.height = po2Height / resolution;
        texture.source.pixelWidth = po2Width;
        texture.source.pixelHeight = po2Height;
        texture.frame.x = 0;
        texture.frame.y = 0;
        texture.frame.width = frameWidth;
        texture.frame.height = frameHeight;
        texture.updateUvs();
        this._poolKeyHash[texture.uid] = key;
        return texture;
      }
      /**
       * Gets extra texture of the same size as input renderTexture
       * @param texture - The texture to check what size it is.
       * @param antialias - Whether to use antialias.
       * @returns A texture that is a power of two
       */
      getSameSizeTexture(texture, antialias = false) {
        const source = texture.source;
        return this.getOptimalTexture(texture.width, texture.height, source._resolution, antialias);
      }
      /**
       * Place a render texture back into the pool. Optionally reset the style of the texture to the default texture style.
       * useful if you modified the style of the texture after getting it from the pool.
       * @param renderTexture - The renderTexture to free
       * @param resetStyle - Whether to reset the style of the texture to the default texture style
       */
      returnTexture(renderTexture, resetStyle = false) {
        const key = this._poolKeyHash[renderTexture.uid];
        if (resetStyle) {
          renderTexture.source.style = this.textureStyle;
        }
        this._texturePool[key].push(renderTexture);
      }
      /**
       * Clears the pool.
       * @param destroyTextures - Destroy all stored textures.
       */
      clear(destroyTextures) {
        destroyTextures = destroyTextures !== false;
        if (destroyTextures) {
          for (const i in this._texturePool) {
            const textures = this._texturePool[i];
            if (textures) {
              for (let j = 0; j < textures.length; j++) {
                textures[j].destroy(true);
              }
            }
          }
        }
        this._texturePool = {};
      }
    }
    const TexturePool = new TexturePoolClass();
    GlobalResourceRegistry.register(TexturePool);

    "use strict";
    class RenderGroup {
      constructor() {
        this.renderPipeId = "renderGroup";
        this.root = null;
        this.canBundle = false;
        this.renderGroupParent = null;
        this.renderGroupChildren = [];
        this.worldTransform = new Matrix();
        this.worldColorAlpha = 4294967295;
        this.worldColor = 16777215;
        this.worldAlpha = 1;
        // these updates are transform changes..
        this.childrenToUpdate = /* @__PURE__ */ Object.create(null);
        this.updateTick = 0;
        this.gcTick = 0;
        // these update are renderable changes..
        this.childrenRenderablesToUpdate = { list: [], index: 0 };
        // other
        this.structureDidChange = true;
        this.instructionSet = new InstructionSet();
        this._onRenderContainers = [];
        /**
         * Indicates if the cached texture needs to be updated.
         * @default true
         */
        this.textureNeedsUpdate = true;
        /**
         * Indicates if the container should be cached as a texture.
         * @default false
         */
        this.isCachedAsTexture = false;
        this._matrixDirty = 7;
      }
      init(root) {
        this.root = root;
        if (root._onRender)
          this.addOnRender(root);
        root.didChange = true;
        const children = root.children;
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          child._updateFlags = 15;
          this.addChild(child);
        }
      }
      enableCacheAsTexture(options = {}) {
        this.textureOptions = options;
        this.isCachedAsTexture = true;
        this.textureNeedsUpdate = true;
      }
      disableCacheAsTexture() {
        this.isCachedAsTexture = false;
        if (this.texture) {
          TexturePool.returnTexture(this.texture, true);
          this.texture = null;
        }
      }
      updateCacheTexture() {
        this.textureNeedsUpdate = true;
        const cachedParent = this._parentCacheAsTextureRenderGroup;
        if (cachedParent && !cachedParent.textureNeedsUpdate) {
          cachedParent.updateCacheTexture();
        }
      }
      reset() {
        this.renderGroupChildren.length = 0;
        for (const i in this.childrenToUpdate) {
          const childrenAtDepth = this.childrenToUpdate[i];
          childrenAtDepth.list.fill(null);
          childrenAtDepth.index = 0;
        }
        this.childrenRenderablesToUpdate.index = 0;
        this.childrenRenderablesToUpdate.list.fill(null);
        this.root = null;
        this.updateTick = 0;
        this.structureDidChange = true;
        this._onRenderContainers.length = 0;
        this.renderGroupParent = null;
        this.disableCacheAsTexture();
      }
      get localTransform() {
        return this.root.localTransform;
      }
      addRenderGroupChild(renderGroupChild) {
        if (renderGroupChild.renderGroupParent) {
          renderGroupChild.renderGroupParent._removeRenderGroupChild(renderGroupChild);
        }
        renderGroupChild.renderGroupParent = this;
        this.renderGroupChildren.push(renderGroupChild);
      }
      _removeRenderGroupChild(renderGroupChild) {
        const index = this.renderGroupChildren.indexOf(renderGroupChild);
        if (index > -1) {
          this.renderGroupChildren.splice(index, 1);
        }
        renderGroupChild.renderGroupParent = null;
      }
      addChild(child) {
        this.structureDidChange = true;
        child.parentRenderGroup = this;
        child.updateTick = -1;
        if (child.parent === this.root) {
          child.relativeRenderGroupDepth = 1;
        } else {
          child.relativeRenderGroupDepth = child.parent.relativeRenderGroupDepth + 1;
        }
        child.didChange = true;
        this.onChildUpdate(child);
        if (child.renderGroup) {
          this.addRenderGroupChild(child.renderGroup);
          return;
        }
        if (child._onRender)
          this.addOnRender(child);
        const children = child.children;
        for (let i = 0; i < children.length; i++) {
          this.addChild(children[i]);
        }
      }
      removeChild(child) {
        this.structureDidChange = true;
        if (child._onRender) {
          if (!child.renderGroup) {
            this.removeOnRender(child);
          }
        }
        child.parentRenderGroup = null;
        if (child.renderGroup) {
          this._removeRenderGroupChild(child.renderGroup);
          return;
        }
        const children = child.children;
        for (let i = 0; i < children.length; i++) {
          this.removeChild(children[i]);
        }
      }
      removeChildren(children) {
        for (let i = 0; i < children.length; i++) {
          this.removeChild(children[i]);
        }
      }
      onChildUpdate(child) {
        let childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth];
        if (!childrenToUpdate) {
          childrenToUpdate = this.childrenToUpdate[child.relativeRenderGroupDepth] = {
            index: 0,
            list: []
          };
        }
        childrenToUpdate.list[childrenToUpdate.index++] = child;
      }
      updateRenderable(renderable) {
        if (renderable.globalDisplayStatus < 7)
          return;
        this.instructionSet.renderPipes[renderable.renderPipeId].updateRenderable(renderable);
        renderable.didViewUpdate = false;
      }
      onChildViewUpdate(child) {
        this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = child;
      }
      get isRenderable() {
        return this.root.localDisplayStatus === 7 && this.worldAlpha > 0;
      }
      /**
       * adding a container to the onRender list will make sure the user function
       * passed in to the user defined 'onRender` callBack
       * @param container - the container to add to the onRender list
       */
      addOnRender(container) {
        this._onRenderContainers.push(container);
      }
      removeOnRender(container) {
        this._onRenderContainers.splice(this._onRenderContainers.indexOf(container), 1);
      }
      runOnRender(renderer) {
        for (let i = 0; i < this._onRenderContainers.length; i++) {
          this._onRenderContainers[i]._onRender(renderer);
        }
      }
      destroy() {
        this.disableCacheAsTexture();
        this.renderGroupParent = null;
        this.root = null;
        this.childrenRenderablesToUpdate = null;
        this.childrenToUpdate = null;
        this.renderGroupChildren = null;
        this._onRenderContainers = null;
        this.instructionSet = null;
      }
      getChildren(out = []) {
        const children = this.root.children;
        for (let i = 0; i < children.length; i++) {
          this._getChildren(children[i], out);
        }
        return out;
      }
      _getChildren(container, out = []) {
        out.push(container);
        if (container.renderGroup)
          return out;
        const children = container.children;
        for (let i = 0; i < children.length; i++) {
          this._getChildren(children[i], out);
        }
        return out;
      }
      invalidateMatrices() {
        this._matrixDirty = 7;
      }
      /**
       * Returns the inverse of the world transform matrix.
       * @returns {Matrix} The inverse of the world transform matrix.
       */
      get inverseWorldTransform() {
        if ((this._matrixDirty & 1) === 0)
          return this._inverseWorldTransform;
        this._matrixDirty &= ~1;
        this._inverseWorldTransform || (this._inverseWorldTransform = new Matrix());
        return this._inverseWorldTransform.copyFrom(this.worldTransform).invert();
      }
      /**
       * Returns the inverse of the texture offset transform matrix.
       * @returns {Matrix} The inverse of the texture offset transform matrix.
       */
      get textureOffsetInverseTransform() {
        if ((this._matrixDirty & 2) === 0)
          return this._textureOffsetInverseTransform;
        this._matrixDirty &= ~2;
        this._textureOffsetInverseTransform || (this._textureOffsetInverseTransform = new Matrix());
        return this._textureOffsetInverseTransform.copyFrom(this.inverseWorldTransform).translate(
          -this._textureBounds.x,
          -this._textureBounds.y
        );
      }
      /**
       * Returns the inverse of the parent texture transform matrix.
       * This is used to properly transform coordinates when rendering into cached textures.
       * @returns {Matrix} The inverse of the parent texture transform matrix.
       */
      get inverseParentTextureTransform() {
        if ((this._matrixDirty & 4) === 0)
          return this._inverseParentTextureTransform;
        this._matrixDirty &= ~4;
        const parentCacheAsTexture = this._parentCacheAsTextureRenderGroup;
        if (parentCacheAsTexture) {
          this._inverseParentTextureTransform || (this._inverseParentTextureTransform = new Matrix());
          return this._inverseParentTextureTransform.copyFrom(this.worldTransform).prepend(parentCacheAsTexture.inverseWorldTransform).translate(
            -parentCacheAsTexture._textureBounds.x,
            -parentCacheAsTexture._textureBounds.y
          );
        }
        return this.worldTransform;
      }
      /**
       * Returns a matrix that transforms coordinates to the correct coordinate space of the texture being rendered to.
       * This is the texture offset inverse transform of the closest parent RenderGroup that is cached as a texture.
       * @returns {Matrix | null} The transform matrix for the cached texture coordinate space,
       * or null if no parent is cached as texture.
       */
      get cacheToLocalTransform() {
        if (this.isCachedAsTexture) {
          return this.textureOffsetInverseTransform;
        }
        if (!this._parentCacheAsTextureRenderGroup)
          return null;
        return this._parentCacheAsTextureRenderGroup.textureOffsetInverseTransform;
      }
    }

    "use strict";
    function assignWithIgnore(target, options, ignore = {}) {
      for (const key in options) {
        if (!ignore[key] && options[key] !== void 0) {
          target[key] = options[key];
        }
      }
    }

    "use strict";
    const defaultSkew = new ObservablePoint(null);
    const defaultPivot = new ObservablePoint(null);
    const defaultScale = new ObservablePoint(null, 1, 1);
    const defaultOrigin = new ObservablePoint(null);
    const UPDATE_COLOR = 1;
    const UPDATE_BLEND = 2;
    const UPDATE_VISIBLE = 4;
    const UPDATE_TRANSFORM = 8;
    class Container extends EventEmitter {
      constructor(options = {}) {
        var _a, _b;
        super();
        /**
         * unique id for this container
         * @internal
         */
        this.uid = uid$1("renderable");
        /** @private */
        this._updateFlags = 15;
        // the render group this container owns
        /** @private */
        this.renderGroup = null;
        // the render group this container belongs to
        /** @private */
        this.parentRenderGroup = null;
        // the index of the container in the render group
        /** @private */
        this.parentRenderGroupIndex = 0;
        // set to true if the container has changed. It is reset once the changes have been applied
        // by the transform system
        // its here to stop ensure that when things change, only one update gets registers with the transform system
        /** @private */
        this.didChange = false;
        // same as above, but for the renderable
        /** @private */
        this.didViewUpdate = false;
        // how deep is the container relative to its render group..
        // unless the element is the root render group - it will be relative to its parent
        /** @private */
        this.relativeRenderGroupDepth = 0;
        /**
         * The array of children of this container. Each child must be a Container or extend from it.
         *
         * The array is read-only, but its contents can be modified using Container methods.
         * @example
         * ```ts
         * // Access children
         * const firstChild = container.children[0];
         * const lastChild = container.children[container.children.length - 1];
         * ```
         * @readonly
         * @see {@link Container#addChild} For adding children
         * @see {@link Container#removeChild} For removing children
         */
        this.children = [];
        /**
         * The display object container that contains this display object.
         * This represents the parent-child relationship in the display tree.
         * @example
         * ```ts
         * // Basic parent access
         * const parent = sprite.parent;
         *
         * // Walk up the tree
         * let current = sprite;
         * while (current.parent) {
         *     console.log('Level up:', current.parent.constructor.name);
         *     current = current.parent;
         * }
         * ```
         * @readonly
         * @see {@link Container#addChild} For adding to a parent
         * @see {@link Container#removeChild} For removing from parent
         */
        this.parent = null;
        // used internally for changing up the render order.. mainly for masks and filters
        // TODO setting this should cause a rebuild??
        /** @private */
        this.includeInBuild = true;
        /** @private */
        this.measurable = true;
        /** @private */
        this.isSimple = true;
        /**
         * The RenderLayer this container belongs to, if any.
         * If it belongs to a RenderLayer, it will be rendered from the RenderLayer's position in the scene.
         * @readonly
         * @advanced
         */
        this.parentRenderLayer = null;
        // / /////////////Transform related props//////////////
        // used by the transform system to check if a container needs to be updated that frame
        // if the tick matches the current transform system tick, it is not updated again
        /** @internal */
        this.updateTick = -1;
        /**
         * Current transform of the object based on local factors: position, scale, other stuff.
         * This matrix represents the local transformation without any parent influence.
         * @example
         * ```ts
         * // Basic transform access
         * const localMatrix = sprite.localTransform;
         * console.log(localMatrix.toString());
         * ```
         * @readonly
         * @see {@link Container#worldTransform} For global transform
         * @see {@link Container#groupTransform} For render group transform
         */
        this.localTransform = new Matrix();
        /**
         * The relative group transform is a transform relative to the render group it belongs too. It will include all parent
         * transforms and up to the render group (think of it as kind of like a stage - but the stage can be nested).
         * If this container is is self a render group matrix will be relative to its parent render group
         * @readonly
         * @advanced
         */
        this.relativeGroupTransform = new Matrix();
        /**
         * The group transform is a transform relative to the render group it belongs too.
         * If this container is render group then this will be an identity matrix. other wise it
         * will be the same as the relativeGroupTransform.
         * Use this value when actually rendering things to the screen
         * @readonly
         * @advanced
         */
        this.groupTransform = this.relativeGroupTransform;
        /**
         * Whether this object has been destroyed. If true, the object should no longer be used.
         * After an object is destroyed, all of its functionality is disabled and references are removed.
         * @example
         * ```ts
         * // Cleanup with destroy
         * sprite.destroy();
         * console.log(sprite.destroyed); // true
         * ```
         * @default false
         * @see {@link Container#destroy} For destroying objects
         */
        this.destroyed = false;
        // transform data..
        /**
         * The coordinate of the object relative to the local coordinates of the parent.
         * @internal
         */
        this._position = new ObservablePoint(this, 0, 0);
        /**
         * The scale factor of the object.
         * @internal
         */
        this._scale = defaultScale;
        /**
         * The pivot point of the container that it rotates around.
         * @internal
         */
        this._pivot = defaultPivot;
        /**
         * The origin point around which the container rotates and scales.
         * Unlike pivot, changing origin will not move the container's position.
         * @private
         */
        this._origin = defaultOrigin;
        /**
         * The skew amount, on the x and y axis.
         * @internal
         */
        this._skew = defaultSkew;
        /**
         * The X-coordinate value of the normalized local X axis,
         * the first column of the local transformation matrix without a scale.
         * @internal
         */
        this._cx = 1;
        /**
         * The Y-coordinate value of the normalized local X axis,
         * the first column of the local transformation matrix without a scale.
         * @internal
         */
        this._sx = 0;
        /**
         * The X-coordinate value of the normalized local Y axis,
         * the second column of the local transformation matrix without a scale.
         * @internal
         */
        this._cy = 0;
        /**
         * The Y-coordinate value of the normalized local Y axis,
         * the second column of the local transformation matrix without a scale.
         * @internal
         */
        this._sy = 1;
        /**
         * The rotation amount.
         * @internal
         */
        this._rotation = 0;
        // / COLOR related props //////////////
        // color stored as ABGR
        /** @internal */
        this.localColor = 16777215;
        /** @internal */
        this.localAlpha = 1;
        /** @internal */
        this.groupAlpha = 1;
        // A
        /** @internal */
        this.groupColor = 16777215;
        // BGR
        /** @internal */
        this.groupColorAlpha = 4294967295;
        // ABGR
        // / BLEND related props //////////////
        /** @internal */
        this.localBlendMode = "inherit";
        /** @internal */
        this.groupBlendMode = "normal";
        // / VISIBILITY related props //////////////
        // visibility
        // 0b11
        // first bit is visible, second bit is renderable
        /**
         * This property holds three bits: culled, visible, renderable
         * the third bit represents culling (0 = culled, 1 = not culled) 0b100
         * the second bit represents visibility (0 = not visible, 1 = visible) 0b010
         * the first bit represents renderable (0 = not renderable, 1 = renderable) 0b001
         * @internal
         */
        this.localDisplayStatus = 7;
        // 0b11 | 0b10 | 0b01 | 0b00
        /** @internal */
        this.globalDisplayStatus = 7;
        /**
         * A value that increments each time the containe is modified
         * eg children added, removed etc
         * @ignore
         */
        this._didContainerChangeTick = 0;
        /**
         * A value that increments each time the container view is modified
         * eg texture swap, geometry change etc
         * @ignore
         */
        this._didViewChangeTick = 0;
        /**
         * property that tracks if the container transform has changed
         * @ignore
         */
        this._didLocalTransformChangeId = -1;
        this.effects = [];
        assignWithIgnore(this, options, {
          children: true,
          parent: true,
          effects: true
        });
        (_a = options.children) == null ? void 0 : _a.forEach((child) => this.addChild(child));
        (_b = options.parent) == null ? void 0 : _b.addChild(this);
      }
      /**
       * Mixes all enumerable properties and methods from a source object to Container.
       * @param source - The source of properties and methods to mix in.
       * @deprecated since 8.8.0
       */
      static mixin(source) {
        deprecation("8.8.0", "Container.mixin is deprecated, please use extensions.mixin instead.");
        extensions.mixin(Container, source);
      }
      // = 'default';
      /**
       * We now use the _didContainerChangeTick and _didViewChangeTick to track changes
       * @deprecated since 8.2.6
       * @ignore
       */
      set _didChangeId(value) {
        this._didViewChangeTick = value >> 12 & 4095;
        this._didContainerChangeTick = value & 4095;
      }
      /** @ignore */
      get _didChangeId() {
        return this._didContainerChangeTick & 4095 | (this._didViewChangeTick & 4095) << 12;
      }
      /**
       * Adds one or more children to the container.
       * The children will be rendered as part of this container's display list.
       * @example
       * ```ts
       * // Add a single child
       * container.addChild(sprite);
       *
       * // Add multiple children
       * container.addChild(background, player, foreground);
       *
       * // Add with type checking
       * const sprite = container.addChild<Sprite>(new Sprite(texture));
       * sprite.tint = 'red';
       * ```
       * @param children - The Container(s) to add to the container
       * @returns The first child that was added
       * @see {@link Container#removeChild} For removing children
       * @see {@link Container#addChildAt} For adding at specific index
       */
      addChild(...children) {
        if (!this.allowChildren) {
          deprecation(v8_0_0, "addChild: Only Containers will be allowed to add children in v8.0.0");
        }
        if (children.length > 1) {
          for (let i = 0; i < children.length; i++) {
            this.addChild(children[i]);
          }
          return children[0];
        }
        const child = children[0];
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (child.parent === this) {
          this.children.splice(this.children.indexOf(child), 1);
          this.children.push(child);
          if (renderGroup) {
            renderGroup.structureDidChange = true;
          }
          return child;
        }
        if (child.parent) {
          child.parent.removeChild(child);
        }
        this.children.push(child);
        if (this.sortableChildren)
          this.sortDirty = true;
        child.parent = this;
        child.didChange = true;
        child._updateFlags = 15;
        if (renderGroup) {
          renderGroup.addChild(child);
        }
        this.emit("childAdded", child, this, this.children.length - 1);
        child.emit("added", this);
        this._didViewChangeTick++;
        if (child._zIndex !== 0) {
          child.depthOfChildModified();
        }
        return child;
      }
      /**
       * Removes one or more children from the container.
       * When removing multiple children, events will be triggered for each child in sequence.
       * @example
       * ```ts
       * // Remove a single child
       * const removed = container.removeChild(sprite);
       *
       * // Remove multiple children
       * const bg = container.removeChild(background, player, userInterface);
       *
       * // Remove with type checking
       * const sprite = container.removeChild<Sprite>(childSprite);
       * sprite.texture = newTexture;
       * ```
       * @param children - The Container(s) to remove
       * @returns The first child that was removed
       * @see {@link Container#addChild} For adding children
       * @see {@link Container#removeChildren} For removing multiple children
       */
      removeChild(...children) {
        if (children.length > 1) {
          for (let i = 0; i < children.length; i++) {
            this.removeChild(children[i]);
          }
          return children[0];
        }
        const child = children[0];
        const index = this.children.indexOf(child);
        if (index > -1) {
          this._didViewChangeTick++;
          this.children.splice(index, 1);
          if (this.renderGroup) {
            this.renderGroup.removeChild(child);
          } else if (this.parentRenderGroup) {
            this.parentRenderGroup.removeChild(child);
          }
          if (child.parentRenderLayer) {
            child.parentRenderLayer.detach(child);
          }
          child.parent = null;
          this.emit("childRemoved", child, this, index);
          child.emit("removed", this);
        }
        return child;
      }
      /** @ignore */
      _onUpdate(point) {
        if (point) {
          if (point === this._skew) {
            this._updateSkew();
          }
        }
        this._didContainerChangeTick++;
        if (this.didChange)
          return;
        this.didChange = true;
        if (this.parentRenderGroup) {
          this.parentRenderGroup.onChildUpdate(this);
        }
      }
      set isRenderGroup(value) {
        if (!!this.renderGroup === value)
          return;
        if (value) {
          this.enableRenderGroup();
        } else {
          this.disableRenderGroup();
        }
      }
      /**
       * Returns true if this container is a render group.
       * This means that it will be rendered as a separate pass, with its own set of instructions
       * @advanced
       */
      get isRenderGroup() {
        return !!this.renderGroup;
      }
      /**
       * Calling this enables a render group for this container.
       * This means it will be rendered as a separate set of instructions.
       * The transform of the container will also be handled on the GPU rather than the CPU.
       * @advanced
       */
      enableRenderGroup() {
        if (this.renderGroup)
          return;
        const parentRenderGroup = this.parentRenderGroup;
        parentRenderGroup == null ? void 0 : parentRenderGroup.removeChild(this);
        this.renderGroup = BigPool.get(RenderGroup, this);
        this.groupTransform = Matrix.IDENTITY;
        parentRenderGroup == null ? void 0 : parentRenderGroup.addChild(this);
        this._updateIsSimple();
      }
      /**
       * This will disable the render group for this container.
       * @advanced
       */
      disableRenderGroup() {
        if (!this.renderGroup)
          return;
        const parentRenderGroup = this.parentRenderGroup;
        parentRenderGroup == null ? void 0 : parentRenderGroup.removeChild(this);
        BigPool.return(this.renderGroup);
        this.renderGroup = null;
        this.groupTransform = this.relativeGroupTransform;
        parentRenderGroup == null ? void 0 : parentRenderGroup.addChild(this);
        this._updateIsSimple();
      }
      /** @ignore */
      _updateIsSimple() {
        this.isSimple = !this.renderGroup && this.effects.length === 0;
      }
      /**
       * Current transform of the object based on world (parent) factors.
       *
       * This matrix represents the absolute transformation in the scene graph.
       * @example
       * ```ts
       * // Get world position
       * const worldPos = container.worldTransform;
       * console.log(`World position: (${worldPos.tx}, ${worldPos.ty})`);
       * ```
       * @readonly
       * @see {@link Container#localTransform} For local space transform
       */
      get worldTransform() {
        this._worldTransform || (this._worldTransform = new Matrix());
        if (this.renderGroup) {
          this._worldTransform.copyFrom(this.renderGroup.worldTransform);
        } else if (this.parentRenderGroup) {
          this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform);
        }
        return this._worldTransform;
      }
      /**
       * The position of the container on the x axis relative to the local coordinates of the parent.
       *
       * An alias to position.x
       * @example
       * ```ts
       * // Basic position
       * container.x = 100;
       * ```
       */
      get x() {
        return this._position.x;
      }
      set x(value) {
        this._position.x = value;
      }
      /**
       * The position of the container on the y axis relative to the local coordinates of the parent.
       *
       * An alias to position.y
       * @example
       * ```ts
       * // Basic position
       * container.y = 200;
       * ```
       */
      get y() {
        return this._position.y;
      }
      set y(value) {
        this._position.y = value;
      }
      /**
       * The coordinate of the object relative to the local coordinates of the parent.
       * @example
       * ```ts
       * // Basic position setting
       * container.position.set(100, 200);
       * container.position.set(100); // Sets both x and y to 100
       * // Using point data
       * container.position = { x: 50, y: 75 };
       * ```
       * @since 4.0.0
       */
      get position() {
        return this._position;
      }
      set position(value) {
        this._position.copyFrom(value);
      }
      /**
       * The rotation of the object in radians.
       *
       * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
       * > rotation is in radians, angle is in degrees.
       * @example
       * ```ts
       * // Basic rotation
       * container.rotation = Math.PI / 4; // 45 degrees
       *
       * // Convert from degrees
       * const degrees = 45;
       * container.rotation = degrees * Math.PI / 180;
       *
       * // Rotate around center
       * container.pivot.set(container.width / 2, container.height / 2);
       * container.rotation = Math.PI; // 180 degrees
       *
       * // Rotate around center with origin
       * container.origin.set(container.width / 2, container.height / 2);
       * container.rotation = Math.PI; // 180 degrees
       * ```
       */
      get rotation() {
        return this._rotation;
      }
      set rotation(value) {
        if (this._rotation !== value) {
          this._rotation = value;
          this._onUpdate(this._skew);
        }
      }
      /**
       * The angle of the object in degrees.
       *
       * > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
       * > rotation is in radians, angle is in degrees.
       * @example
       * ```ts
       * // Basic angle rotation
       * sprite.angle = 45; // 45 degrees
       *
       * // Rotate around center
       * sprite.pivot.set(sprite.width / 2, sprite.height / 2);
       * sprite.angle = 180; // Half rotation
       *
       * // Rotate around center with origin
       * sprite.origin.set(sprite.width / 2, sprite.height / 2);
       * sprite.angle = 180; // Half rotation
       *
       * // Reset rotation
       * sprite.angle = 0;
       * ```
       */
      get angle() {
        return this.rotation * RAD_TO_DEG;
      }
      set angle(value) {
        this.rotation = value * DEG_TO_RAD;
      }
      /**
       * The center of rotation, scaling, and skewing for this display object in its local space.
       * The `position` is the projection of `pivot` in the parent's local space.
       *
       * By default, the pivot is the origin (0, 0).
       * @example
       * ```ts
       * // Rotate around center
       * container.pivot.set(container.width / 2, container.height / 2);
       * container.rotation = Math.PI; // Rotates around center
       * ```
       * @since 4.0.0
       */
      get pivot() {
        if (this._pivot === defaultPivot) {
          this._pivot = new ObservablePoint(this, 0, 0);
        }
        return this._pivot;
      }
      set pivot(value) {
        if (this._pivot === defaultPivot) {
          this._pivot = new ObservablePoint(this, 0, 0);
          if (this._origin !== defaultOrigin) {
            warn(`Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.`);
          }
        }
        typeof value === "number" ? this._pivot.set(value) : this._pivot.copyFrom(value);
      }
      /**
       * The skew factor for the object in radians. Skewing is a transformation that distorts
       * the object by rotating it differently at each point, creating a non-uniform shape.
       * @example
       * ```ts
       * // Basic skewing
       * container.skew.set(0.5, 0); // Skew horizontally
       * container.skew.set(0, 0.5); // Skew vertically
       *
       * // Skew with point data
       * container.skew = { x: 0.3, y: 0.3 }; // Diagonal skew
       *
       * // Reset skew
       * container.skew.set(0, 0);
       *
       * // Animate skew
       * app.ticker.add(() => {
       *     // Create wave effect
       *     container.skew.x = Math.sin(Date.now() / 1000) * 0.3;
       * });
       *
       * // Combine with rotation
       * container.rotation = Math.PI / 4; // 45 degrees
       * container.skew.set(0.2, 0.2); // Skew the rotated object
       * ```
       * @since 4.0.0
       * @type {ObservablePoint} Point-like object with x/y properties in radians
       * @default {x: 0, y: 0}
       */
      get skew() {
        if (this._skew === defaultSkew) {
          this._skew = new ObservablePoint(this, 0, 0);
        }
        return this._skew;
      }
      set skew(value) {
        if (this._skew === defaultSkew) {
          this._skew = new ObservablePoint(this, 0, 0);
        }
        this._skew.copyFrom(value);
      }
      /**
       * The scale factors of this object along the local coordinate axes.
       *
       * The default scale is (1, 1).
       * @example
       * ```ts
       * // Basic scaling
       * container.scale.set(2, 2); // Scales to double size
       * container.scale.set(2); // Scales uniformly to double size
       * container.scale = 2; // Scales uniformly to double size
       * // Scale to a specific width and height
       * container.setSize(200, 100); // Sets width to 200 and height to 100
       * ```
       * @since 4.0.0
       */
      get scale() {
        if (this._scale === defaultScale) {
          this._scale = new ObservablePoint(this, 1, 1);
        }
        return this._scale;
      }
      set scale(value) {
        if (this._scale === defaultScale) {
          this._scale = new ObservablePoint(this, 0, 0);
        }
        if (typeof value === "string") {
          value = parseFloat(value);
        }
        typeof value === "number" ? this._scale.set(value) : this._scale.copyFrom(value);
      }
      /**
       * @experimental
       * The origin point around which the container rotates and scales without affecting its position.
       * Unlike pivot, changing the origin will not move the container's position.
       * @example
       * ```ts
       * // Rotate around center point
       * container.origin.set(container.width / 2, container.height / 2);
       * container.rotation = Math.PI; // Rotates around center
       *
       * // Reset origin
       * container.origin.set(0, 0);
       * ```
       */
      get origin() {
        if (this._origin === defaultOrigin) {
          this._origin = new ObservablePoint(this, 0, 0);
        }
        return this._origin;
      }
      set origin(value) {
        if (this._origin === defaultOrigin) {
          this._origin = new ObservablePoint(this, 0, 0);
          if (this._pivot !== defaultPivot) {
            warn(`Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.`);
          }
        }
        typeof value === "number" ? this._origin.set(value) : this._origin.copyFrom(value);
      }
      /**
       * The width of the Container, setting this will actually modify the scale to achieve the value set.
       * > [!NOTE] Changing the width will adjust the scale.x property of the container while maintaining its aspect ratio.
       * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
       * as it is more optimized by not recalculating the local bounds twice.
       * @example
       * ```ts
       * // Basic width setting
       * container.width = 100;
       * // Optimized width setting
       * container.setSize(100, 100);
       * ```
       */
      get width() {
        return Math.abs(this.scale.x * this.getLocalBounds().width);
      }
      set width(value) {
        const localWidth = this.getLocalBounds().width;
        this._setWidth(value, localWidth);
      }
      /**
       * The height of the Container,
       * > [!NOTE] Changing the height will adjust the scale.y property of the container while maintaining its aspect ratio.
       * > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
       * as it is more optimized by not recalculating the local bounds twice.
       * @example
       * ```ts
       * // Basic height setting
       * container.height = 200;
       * // Optimized height setting
       * container.setSize(100, 200);
       * ```
       */
      get height() {
        return Math.abs(this.scale.y * this.getLocalBounds().height);
      }
      set height(value) {
        const localHeight = this.getLocalBounds().height;
        this._setHeight(value, localHeight);
      }
      /**
       * Retrieves the size of the container as a [Size]{@link Size} object.
       *
       * This is faster than get the width and height separately.
       * @example
       * ```ts
       * // Basic size retrieval
       * const size = container.getSize();
       * console.log(`Size: ${size.width}x${size.height}`);
       *
       * // Reuse existing size object
       * const reuseSize = { width: 0, height: 0 };
       * container.getSize(reuseSize);
       * ```
       * @param out - Optional object to store the size in.
       * @returns The size of the container.
       */
      getSize(out) {
        if (!out) {
          out = {};
        }
        const bounds = this.getLocalBounds();
        out.width = Math.abs(this.scale.x * bounds.width);
        out.height = Math.abs(this.scale.y * bounds.height);
        return out;
      }
      /**
       * Sets the size of the container to the specified width and height.
       * This is more efficient than setting width and height separately as it only recalculates bounds once.
       * @example
       * ```ts
       * // Basic size setting
       * container.setSize(100, 200);
       *
       * // Set uniform size
       * container.setSize(100); // Sets both width and height to 100
       * ```
       * @param value - This can be either a number or a [Size]{@link Size} object.
       * @param height - The height to set. Defaults to the value of `width` if not provided.
       */
      setSize(value, height) {
        var _a;
        const size = this.getLocalBounds();
        if (typeof value === "object") {
          height = (_a = value.height) != null ? _a : value.width;
          value = value.width;
        } else {
          height != null ? height : height = value;
        }
        value !== void 0 && this._setWidth(value, size.width);
        height !== void 0 && this._setHeight(height, size.height);
      }
      /** Called when the skew or the rotation changes. */
      _updateSkew() {
        const rotation = this._rotation;
        const skew = this._skew;
        this._cx = Math.cos(rotation + skew._y);
        this._sx = Math.sin(rotation + skew._y);
        this._cy = -Math.sin(rotation - skew._x);
        this._sy = Math.cos(rotation - skew._x);
      }
      /**
       * Updates the transform properties of the container.
       * Allows partial updates of transform properties for optimized manipulation.
       * @example
       * ```ts
       * // Basic transform update
       * container.updateTransform({
       *     x: 100,
       *     y: 200,
       *     rotation: Math.PI / 4
       * });
       *
       * // Scale and rotate around center
       * sprite.updateTransform({
       *     pivotX: sprite.width / 2,
       *     pivotY: sprite.height / 2,
       *     scaleX: 2,
       *     scaleY: 2,
       *     rotation: Math.PI
       * });
       *
       * // Update position only
       * button.updateTransform({
       *     x: button.x + 10, // Move right
       *     y: button.y      // Keep same y
       * });
       * ```
       * @param opts - Transform options to update
       * @param opts.x - The x position
       * @param opts.y - The y position
       * @param opts.scaleX - The x-axis scale factor
       * @param opts.scaleY - The y-axis scale factor
       * @param opts.rotation - The rotation in radians
       * @param opts.skewX - The x-axis skew factor
       * @param opts.skewY - The y-axis skew factor
       * @param opts.pivotX - The x-axis pivot point
       * @param opts.pivotY - The y-axis pivot point
       * @returns This container, for chaining
       * @see {@link Container#setFromMatrix} For matrix-based transforms
       * @see {@link Container#position} For direct position access
       */
      updateTransform(opts) {
        this.position.set(
          typeof opts.x === "number" ? opts.x : this.position.x,
          typeof opts.y === "number" ? opts.y : this.position.y
        );
        this.scale.set(
          typeof opts.scaleX === "number" ? opts.scaleX || 1 : this.scale.x,
          typeof opts.scaleY === "number" ? opts.scaleY || 1 : this.scale.y
        );
        this.rotation = typeof opts.rotation === "number" ? opts.rotation : this.rotation;
        this.skew.set(
          typeof opts.skewX === "number" ? opts.skewX : this.skew.x,
          typeof opts.skewY === "number" ? opts.skewY : this.skew.y
        );
        this.pivot.set(
          typeof opts.pivotX === "number" ? opts.pivotX : this.pivot.x,
          typeof opts.pivotY === "number" ? opts.pivotY : this.pivot.y
        );
        this.origin.set(
          typeof opts.originX === "number" ? opts.originX : this.origin.x,
          typeof opts.originY === "number" ? opts.originY : this.origin.y
        );
        return this;
      }
      /**
       * Updates the local transform properties by decomposing the given matrix.
       * Extracts position, scale, rotation, and skew from a transformation matrix.
       * @example
       * ```ts
       * // Basic matrix transform
       * const matrix = new Matrix()
       *     .translate(100, 100)
       *     .rotate(Math.PI / 4)
       *     .scale(2, 2);
       *
       * container.setFromMatrix(matrix);
       *
       * // Copy transform from another container
       * const source = new Container();
       * source.position.set(100, 100);
       * source.rotation = Math.PI / 2;
       *
       * target.setFromMatrix(source.localTransform);
       *
       * // Reset transform
       * container.setFromMatrix(Matrix.IDENTITY);
       * ```
       * @param matrix - The matrix to use for updating the transform
       * @see {@link Container#updateTransform} For property-based updates
       * @see {@link Matrix#decompose} For matrix decomposition details
       */
      setFromMatrix(matrix) {
        matrix.decompose(this);
      }
      /** Updates the local transform. */
      updateLocalTransform() {
        const localTransformChangeId = this._didContainerChangeTick;
        if (this._didLocalTransformChangeId === localTransformChangeId)
          return;
        this._didLocalTransformChangeId = localTransformChangeId;
        const lt = this.localTransform;
        const scale = this._scale;
        const pivot = this._pivot;
        const origin = this._origin;
        const position = this._position;
        const sx = scale._x;
        const sy = scale._y;
        const px = pivot._x;
        const py = pivot._y;
        const ox = -origin._x;
        const oy = -origin._y;
        lt.a = this._cx * sx;
        lt.b = this._sx * sx;
        lt.c = this._cy * sy;
        lt.d = this._sy * sy;
        lt.tx = position._x - (px * lt.a + py * lt.c) + (ox * lt.a + oy * lt.c) - ox;
        lt.ty = position._y - (px * lt.b + py * lt.d) + (ox * lt.b + oy * lt.d) - oy;
      }
      // / ///// color related stuff
      set alpha(value) {
        if (value === this.localAlpha)
          return;
        this.localAlpha = value;
        this._updateFlags |= UPDATE_COLOR;
        this._onUpdate();
      }
      /**
       * The opacity of the object relative to its parent's opacity.
       * Value ranges from 0 (fully transparent) to 1 (fully opaque).
       * @example
       * ```ts
       * // Basic transparency
       * sprite.alpha = 0.5; // 50% opacity
       *
       * // Inherited opacity
       * container.alpha = 0.5;
       * const child = new Sprite(texture);
       * child.alpha = 0.5;
       * container.addChild(child);
       * // child's effective opacity is 0.25 (0.5 * 0.5)
       * ```
       * @default 1
       * @see {@link Container#visible} For toggling visibility
       * @see {@link Container#renderable} For render control
       */
      get alpha() {
        return this.localAlpha;
      }
      set tint(value) {
        const tempColor = Color.shared.setValue(value != null ? value : 16777215);
        const bgr = tempColor.toBgrNumber();
        if (bgr === this.localColor)
          return;
        this.localColor = bgr;
        this._updateFlags |= UPDATE_COLOR;
        this._onUpdate();
      }
      /**
       * The tint applied to the sprite.
       *
       * This can be any valid {@link ColorSource}.
       * @example
       * ```ts
       * // Basic color tinting
       * container.tint = 0xff0000; // Red tint
       * container.tint = 'red';    // Same as above
       * container.tint = '#00ff00'; // Green
       * container.tint = 'rgb(0,0,255)'; // Blue
       *
       * // Remove tint
       * container.tint = 0xffffff; // White = no tint
       * container.tint = null;     // Also removes tint
       * ```
       * @default 0xFFFFFF
       * @see {@link Container#alpha} For transparency
       * @see {@link Container#visible} For visibility control
       */
      get tint() {
        return bgr2rgb(this.localColor);
      }
      // / //////////////// blend related stuff
      set blendMode(value) {
        if (this.localBlendMode === value)
          return;
        if (this.parentRenderGroup) {
          this.parentRenderGroup.structureDidChange = true;
        }
        this._updateFlags |= UPDATE_BLEND;
        this.localBlendMode = value;
        this._onUpdate();
      }
      /**
       * The blend mode to be applied to the sprite. Controls how pixels are blended when rendering.
       *
       * Setting to 'normal' will reset to default blending.
       * > [!NOTE] More blend modes are available after importing the `pixi.js/advanced-blend-modes` sub-export.
       * @example
       * ```ts
       * // Basic blend modes
       * sprite.blendMode = 'add';        // Additive blending
       * sprite.blendMode = 'multiply';   // Multiply colors
       * sprite.blendMode = 'screen';     // Screen blend
       *
       * // Reset blend mode
       * sprite.blendMode = 'normal';     // Normal blending
       * ```
       * @default 'normal'
       * @see {@link Container#alpha} For transparency
       * @see {@link Container#tint} For color adjustments
       */
      get blendMode() {
        return this.localBlendMode;
      }
      // / ///////// VISIBILITY / RENDERABLE /////////////////
      /**
       * The visibility of the object. If false the object will not be drawn,
       * and the transform will not be updated.
       * @example
       * ```ts
       * // Basic visibility toggle
       * sprite.visible = false; // Hide sprite
       * sprite.visible = true;  // Show sprite
       * ```
       * @default true
       * @see {@link Container#renderable} For render-only control
       * @see {@link Container#alpha} For transparency
       */
      get visible() {
        return !!(this.localDisplayStatus & 2);
      }
      set visible(value) {
        const valueNumber = value ? 2 : 0;
        if ((this.localDisplayStatus & 2) === valueNumber)
          return;
        if (this.parentRenderGroup) {
          this.parentRenderGroup.structureDidChange = true;
        }
        this._updateFlags |= UPDATE_VISIBLE;
        this.localDisplayStatus ^= 2;
        this._onUpdate();
      }
      /** @ignore */
      get culled() {
        return !(this.localDisplayStatus & 4);
      }
      /** @ignore */
      set culled(value) {
        const valueNumber = value ? 0 : 4;
        if ((this.localDisplayStatus & 4) === valueNumber)
          return;
        if (this.parentRenderGroup) {
          this.parentRenderGroup.structureDidChange = true;
        }
        this._updateFlags |= UPDATE_VISIBLE;
        this.localDisplayStatus ^= 4;
        this._onUpdate();
      }
      /**
       * Controls whether this object can be rendered. If false the object will not be drawn,
       * but the transform will still be updated. This is different from visible, which skips
       * transform updates.
       * @example
       * ```ts
       * // Basic render control
       * sprite.renderable = false; // Skip rendering
       * sprite.renderable = true;  // Enable rendering
       * ```
       * @default true
       * @see {@link Container#visible} For skipping transform updates
       * @see {@link Container#alpha} For transparency
       */
      get renderable() {
        return !!(this.localDisplayStatus & 1);
      }
      set renderable(value) {
        const valueNumber = value ? 1 : 0;
        if ((this.localDisplayStatus & 1) === valueNumber)
          return;
        this._updateFlags |= UPDATE_VISIBLE;
        this.localDisplayStatus ^= 1;
        if (this.parentRenderGroup) {
          this.parentRenderGroup.structureDidChange = true;
        }
        this._onUpdate();
      }
      /**
       * Whether or not the object should be rendered.
       * @advanced
       */
      get isRenderable() {
        return this.localDisplayStatus === 7 && this.groupAlpha > 0;
      }
      /**
       * Removes all internal references and listeners as well as removes children from the display list.
       * Do not use a Container after calling `destroy`.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * ```ts
       * container.destroy();
       * container.destroy(true);
       * container.destroy({ children: true });
       * container.destroy({ children: true, texture: true, textureSource: true });
       * ```
       */
      destroy(options = false) {
        var _a;
        if (this.destroyed)
          return;
        this.destroyed = true;
        let oldChildren;
        if (this.children.length) {
          oldChildren = this.removeChildren(0, this.children.length);
        }
        this.removeFromParent();
        this.parent = null;
        this._maskEffect = null;
        this._filterEffect = null;
        this.effects = null;
        this._position = null;
        this._scale = null;
        this._pivot = null;
        this._origin = null;
        this._skew = null;
        this.emit("destroyed", this);
        this.removeAllListeners();
        const destroyChildren = typeof options === "boolean" ? options : options == null ? void 0 : options.children;
        if (destroyChildren && oldChildren) {
          for (let i = 0; i < oldChildren.length; ++i) {
            oldChildren[i].destroy(options);
          }
        }
        (_a = this.renderGroup) == null ? void 0 : _a.destroy();
        this.renderGroup = null;
      }
    }
    extensions.mixin(
      Container,
      childrenHelperMixin,
      getFastGlobalBoundsMixin,
      toLocalGlobalMixin,
      onRenderMixin,
      measureMixin,
      effectsMixin,
      findMixin,
      sortMixin,
      cullingMixin,
      cacheAsTextureMixin,
      getGlobalMixin,
      collectRenderablesMixin
    );

    "use strict";
    class ViewContainer extends Container {
      constructor(options) {
        var _a;
        super(options);
        /** @internal */
        this.canBundle = true;
        /** @internal */
        this.allowChildren = false;
        /** @internal */
        this._roundPixels = 0;
        /** @internal */
        this._lastUsed = -1;
        /** @internal */
        this._gpuData = /* @__PURE__ */ Object.create(null);
        /** If set to true, the resource will be garbage collected automatically when it is not used. */
        this.autoGarbageCollect = true;
        /** @internal */
        this._gcLastUsed = -1;
        this._bounds = new Bounds(0, 1, 0, 0);
        this._boundsDirty = true;
        this.autoGarbageCollect = (_a = options.autoGarbageCollect) != null ? _a : true;
      }
      /**
       * The local bounds of the view in its own coordinate space.
       * Bounds are automatically updated when the view's content changes.
       * @example
       * ```ts
       * // Get bounds dimensions
       * const bounds = view.bounds;
       * console.log(`Width: ${bounds.maxX - bounds.minX}`);
       * console.log(`Height: ${bounds.maxY - bounds.minY}`);
       * ```
       * @returns The rectangular bounds of the view
       * @see {@link Bounds} For bounds operations
       */
      get bounds() {
        if (!this._boundsDirty)
          return this._bounds;
        this.updateBounds();
        this._boundsDirty = false;
        return this._bounds;
      }
      /**
       * Whether or not to round the x/y position of the sprite.
       * @example
       * ```ts
       * // Enable pixel rounding for crisp rendering
       * view.roundPixels = true;
       * ```
       * @default false
       */
      get roundPixels() {
        return !!this._roundPixels;
      }
      set roundPixels(value) {
        this._roundPixels = value ? 1 : 0;
      }
      /**
       * Checks if the object contains the given point in local coordinates.
       * Uses the view's bounds for hit testing.
       * @example
       * ```ts
       * // Basic point check
       * const localPoint = { x: 50, y: 25 };
       * const contains = view.containsPoint(localPoint);
       * console.log('Point is inside:', contains);
       * ```
       * @param point - The point to check in local coordinates
       * @returns True if the point is within the view's bounds
       * @see {@link ViewContainer#bounds} For the bounds used in hit testing
       * @see {@link Container#toLocal} For converting global coordinates to local
       */
      containsPoint(point) {
        const bounds = this.bounds;
        const { x, y } = point;
        return x >= bounds.minX && x <= bounds.maxX && y >= bounds.minY && y <= bounds.maxY;
      }
      /** @private */
      onViewUpdate() {
        this._didViewChangeTick++;
        this._boundsDirty = true;
        if (this.didViewUpdate)
          return;
        this.didViewUpdate = true;
        const renderGroup = this.renderGroup || this.parentRenderGroup;
        if (renderGroup) {
          renderGroup.onChildViewUpdate(this);
        }
      }
      /** Unloads the GPU data from the view. */
      unload() {
        var _a;
        this.emit("unload", this);
        for (const key in this._gpuData) {
          (_a = this._gpuData[key]) == null ? void 0 : _a.destroy();
        }
        this._gpuData = /* @__PURE__ */ Object.create(null);
        this.onViewUpdate();
      }
      destroy(options) {
        this.unload();
        super.destroy(options);
        this._bounds = null;
      }
      /**
       * Collects renderables for the view container.
       * @param instructionSet - The instruction set to collect renderables for.
       * @param renderer - The renderer to collect renderables for.
       * @param currentLayer - The current render layer.
       * @internal
       */
      collectRenderablesSimple(instructionSet, renderer, currentLayer) {
        const { renderPipes } = renderer;
        renderPipes.blendMode.pushBlendMode(this, this.groupBlendMode, instructionSet);
        const rp = renderPipes;
        rp[this.renderPipeId].addRenderable(this, instructionSet);
        this.didViewUpdate = false;
        const children = this.children;
        const length = children.length;
        for (let i = 0; i < length; i++) {
          children[i].collectRenderables(instructionSet, renderer, currentLayer);
        }
        renderPipes.blendMode.popBlendMode(instructionSet);
      }
    }

    "use strict";
    var __defProp$15 = Object.defineProperty;
    var __getOwnPropSymbols$17 = Object.getOwnPropertySymbols;
    var __hasOwnProp$17 = Object.prototype.hasOwnProperty;
    var __propIsEnum$17 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$15 = (obj, key, value) => key in obj ? __defProp$15(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$15 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$17.call(b, prop))
          __defNormalProp$15(a, prop, b[prop]);
      if (__getOwnPropSymbols$17)
        for (var prop of __getOwnPropSymbols$17(b)) {
          if (__propIsEnum$17.call(b, prop))
            __defNormalProp$15(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$n = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$17.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$17)
        for (var prop of __getOwnPropSymbols$17(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$17.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class Sprite extends ViewContainer {
      /**
       * @param options - The options for creating the sprite.
       */
      constructor(options = Texture.EMPTY) {
        if (options instanceof Texture) {
          options = { texture: options };
        }
        const _a = options, { texture = Texture.EMPTY, anchor, roundPixels, width, height } = _a, rest = __objRest$n(_a, ["texture", "anchor", "roundPixels", "width", "height"]);
        super(__spreadValues$15({
          label: "Sprite"
        }, rest));
        /** @internal */
        this.renderPipeId = "sprite";
        /** @internal */
        this.batched = true;
        this._visualBounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
        this._anchor = new ObservablePoint(
          {
            _onUpdate: () => {
              this.onViewUpdate();
            }
          }
        );
        if (anchor) {
          this.anchor = anchor;
        } else if (texture.defaultAnchor) {
          this.anchor = texture.defaultAnchor;
        }
        this.texture = texture;
        this.allowChildren = false;
        this.roundPixels = roundPixels != null ? roundPixels : false;
        if (width !== void 0)
          this.width = width;
        if (height !== void 0)
          this.height = height;
      }
      /**
       * Creates a new sprite based on a source texture, image, video, or canvas element.
       * This is a convenience method that automatically creates and manages textures.
       * @example
       * ```ts
       * // Create from path or URL
       * const sprite = Sprite.from('assets/image.png');
       *
       * // Create from existing texture
       * const sprite = Sprite.from(texture);
       *
       * // Create from canvas
       * const canvas = document.createElement('canvas');
       * const sprite = Sprite.from(canvas, true); // Skip caching new texture
       * ```
       * @param source - The source to create the sprite from. Can be a path to an image, a texture,
       * or any valid texture source (canvas, video, etc.)
       * @param skipCache - Whether to skip adding to the texture cache when creating a new texture
       * @returns A new sprite based on the source
       * @see {@link Texture.from} For texture creation details
       * @see {@link Assets} For asset loading and management
       */
      static from(source, skipCache = false) {
        if (source instanceof Texture) {
          return new Sprite(source);
        }
        return new Sprite(Texture.from(source, skipCache));
      }
      set texture(value) {
        value || (value = Texture.EMPTY);
        const currentTexture = this._texture;
        if (currentTexture === value)
          return;
        if (currentTexture && currentTexture.dynamic)
          currentTexture.off("update", this.onViewUpdate, this);
        if (value.dynamic)
          value.on("update", this.onViewUpdate, this);
        this._texture = value;
        if (this._width) {
          this._setWidth(this._width, this._texture.orig.width);
        }
        if (this._height) {
          this._setHeight(this._height, this._texture.orig.height);
        }
        this.onViewUpdate();
      }
      /**
       * The texture that is displayed by the sprite. When changed, automatically updates
       * the sprite dimensions and manages texture event listeners.
       * @example
       * ```ts
       * // Create sprite with texture
       * const sprite = new Sprite({
       *     texture: Texture.from('sprite.png')
       * });
       *
       * // Update texture
       * sprite.texture = Texture.from('newSprite.png');
       *
       * // Use texture from spritesheet
       * const sheet = await Assets.load('spritesheet.json');
       * sprite.texture = sheet.textures['frame1.png'];
       *
       * // Reset to empty texture
       * sprite.texture = Texture.EMPTY;
       * ```
       * @see {@link Texture} For texture creation and management
       * @see {@link Assets} For asset loading
       */
      get texture() {
        return this._texture;
      }
      /**
       * The bounds of the sprite, taking into account the texture's trim area.
       * @example
       * ```ts
       * const texture = new Texture({
       *     source: new TextureSource({ width: 300, height: 300 }),
       *     frame: new Rectangle(196, 66, 58, 56),
       *     trim: new Rectangle(4, 4, 58, 56),
       *     orig: new Rectangle(0, 0, 64, 64),
       *     rotate: 2,
       * });
       * const sprite = new Sprite(texture);
       * const visualBounds = sprite.visualBounds;
       * // console.log(visualBounds); // { minX: -4, maxX: 62, minY: -4, maxY: 60 }
       */
      get visualBounds() {
        updateQuadBounds(this._visualBounds, this._anchor, this._texture);
        return this._visualBounds;
      }
      /**
       * @deprecated
       * @ignore
       */
      get sourceBounds() {
        deprecation("8.6.1", "Sprite.sourceBounds is deprecated, use visualBounds instead.");
        return this.visualBounds;
      }
      /** @private */
      updateBounds() {
        const anchor = this._anchor;
        const texture = this._texture;
        const bounds = this._bounds;
        const { width, height } = texture.orig;
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * sprite.destroy();
       * sprite.destroy(true);
       * sprite.destroy({ texture: true, textureSource: true });
       */
      destroy(options = false) {
        super.destroy(options);
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          this._texture.destroy(destroyTextureSource);
        }
        this._texture = null;
        this._visualBounds = null;
        this._bounds = null;
        this._anchor = null;
      }
      /**
       * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
       * and passed to the constructor.
       *
       * - The default is `(0,0)`, this means the sprite's origin is the top left.
       * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
       * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
       *
       * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
       * @example
       * ```ts
       * // Center the anchor point
       * sprite.anchor = 0.5; // Sets both x and y to 0.5
       * sprite.position.set(400, 300); // Sprite will be centered at this position
       *
       * // Set specific x/y anchor points
       * sprite.anchor = {
       *     x: 1, // Right edge
       *     y: 0  // Top edge
       * };
       *
       * // Using individual coordinates
       * sprite.anchor.set(0.5, 1); // Center-bottom
       *
       * // For rotation around center
       * sprite.anchor.set(0.5);
       * sprite.rotation = Math.PI / 4; // 45 degrees around center
       *
       * // For scaling from center
       * sprite.anchor.set(0.5);
       * sprite.scale.set(2); // Scales from center point
       * ```
       */
      get anchor() {
        return this._anchor;
      }
      set anchor(value) {
        typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
      }
      /**
       * The width of the sprite, setting this will actually modify the scale to achieve the value set.
       * @example
       * ```ts
       * // Set width directly
       * sprite.width = 200;
       * console.log(sprite.scale.x); // Scale adjusted to match width
       *
       * // Set width while preserving aspect ratio
       * const ratio = sprite.height / sprite.width;
       * sprite.width = 300;
       * sprite.height = 300 * ratio;
       *
       * // For better performance when setting both width and height
       * sprite.setSize(300, 400); // Avoids recalculating bounds twice
       *
       * // Reset to original texture size
       * sprite.width = sprite.texture.orig.width;
       * ```
       */
      get width() {
        return Math.abs(this.scale.x) * this._texture.orig.width;
      }
      set width(value) {
        this._setWidth(value, this._texture.orig.width);
        this._width = value;
      }
      /**
       * The height of the sprite, setting this will actually modify the scale to achieve the value set.
       * @example
       * ```ts
       * // Set height directly
       * sprite.height = 150;
       * console.log(sprite.scale.y); // Scale adjusted to match height
       *
       * // Set height while preserving aspect ratio
       * const ratio = sprite.width / sprite.height;
       * sprite.height = 200;
       * sprite.width = 200 * ratio;
       *
       * // For better performance when setting both width and height
       * sprite.setSize(300, 400); // Avoids recalculating bounds twice
       *
       * // Reset to original texture size
       * sprite.height = sprite.texture.orig.height;
       * ```
       */
      get height() {
        return Math.abs(this.scale.y) * this._texture.orig.height;
      }
      set height(value) {
        this._setHeight(value, this._texture.orig.height);
        this._height = value;
      }
      /**
       * Retrieves the size of the Sprite as a [Size]{@link Size} object based on the texture dimensions and scale.
       * This is faster than getting width and height separately as it only calculates the bounds once.
       * @example
       * ```ts
       * // Basic size retrieval
       * const sprite = new Sprite(Texture.from('sprite.png'));
       * const size = sprite.getSize();
       * console.log(`Size: ${size.width}x${size.height}`);
       *
       * // Reuse existing size object
       * const reuseSize = { width: 0, height: 0 };
       * sprite.getSize(reuseSize);
       * ```
       * @param out - Optional object to store the size in, to avoid allocating a new object
       * @returns The size of the Sprite
       * @see {@link Sprite#width} For getting just the width
       * @see {@link Sprite#height} For getting just the height
       * @see {@link Sprite#setSize} For setting both width and height
       */
      getSize(out) {
        out || (out = {});
        out.width = Math.abs(this.scale.x) * this._texture.orig.width;
        out.height = Math.abs(this.scale.y) * this._texture.orig.height;
        return out;
      }
      /**
       * Sets the size of the Sprite to the specified width and height.
       * This is faster than setting width and height separately as it only recalculates bounds once.
       * @example
       * ```ts
       * // Basic size setting
       * const sprite = new Sprite(Texture.from('sprite.png'));
       * sprite.setSize(100, 200); // Width: 100, Height: 200
       *
       * // Set uniform size
       * sprite.setSize(100); // Sets both width and height to 100
       *
       * // Set size with object
       * sprite.setSize({
       *     width: 200,
       *     height: 300
       * });
       *
       * // Reset to texture size
       * sprite.setSize(
       *     sprite.texture.orig.width,
       *     sprite.texture.orig.height
       * );
       * ```
       * @param value - This can be either a number or a {@link Size} object
       * @param height - The height to set. Defaults to the value of `width` if not provided
       * @see {@link Sprite#width} For setting width only
       * @see {@link Sprite#height} For setting height only
       * @see {@link Sprite#texture} For the source dimensions
       */
      setSize(value, height) {
        var _a;
        if (typeof value === "object") {
          height = (_a = value.height) != null ? _a : value.width;
          value = value.width;
        } else {
          height != null ? height : height = value;
        }
        value !== void 0 && this._setWidth(value, this._texture.orig.width);
        height !== void 0 && this._setHeight(height, this._texture.orig.height);
      }
    }

    "use strict";
    const tempBounds$4 = new Bounds();
    function addMaskBounds(mask, bounds, skipUpdateTransform) {
      const boundsToMask = tempBounds$4;
      mask.measurable = true;
      getGlobalBounds(mask, skipUpdateTransform, boundsToMask);
      bounds.addBoundsMask(boundsToMask);
      mask.measurable = false;
    }

    "use strict";
    function addMaskLocalBounds(mask, bounds, localRoot) {
      const boundsToMask = boundsPool.get();
      mask.measurable = true;
      const tempMatrix = matrixPool.get().identity();
      const relativeMask = getMatrixRelativeToParent(mask, localRoot, tempMatrix);
      getLocalBounds(mask, boundsToMask, relativeMask);
      mask.measurable = false;
      bounds.addBoundsMask(boundsToMask);
      matrixPool.return(tempMatrix);
      boundsPool.return(boundsToMask);
    }
    function getMatrixRelativeToParent(target, root, matrix) {
      if (!target) {
        warn("Mask bounds, renderable is not inside the root container");
        return matrix;
      }
      if (target !== root) {
        getMatrixRelativeToParent(target.parent, root, matrix);
        target.updateLocalTransform();
        matrix.append(target.localTransform);
      }
      return matrix;
    }

    "use strict";
    class AlphaMask {
      constructor(options) {
        this.priority = 0;
        this.inverse = false;
        this.pipe = "alphaMask";
        if (options == null ? void 0 : options.mask) {
          this.init(options.mask);
        }
      }
      init(mask) {
        this.mask = mask;
        this.renderMaskToTexture = !(mask instanceof Sprite);
        this.mask.renderable = this.renderMaskToTexture;
        this.mask.includeInBuild = !this.renderMaskToTexture;
        this.mask.measurable = false;
      }
      reset() {
        if (this.mask === null)
          return;
        this.mask.measurable = true;
        this.mask = null;
      }
      addBounds(bounds, skipUpdateTransform) {
        if (!this.inverse) {
          addMaskBounds(this.mask, bounds, skipUpdateTransform);
        }
      }
      addLocalBounds(bounds, localRoot) {
        addMaskLocalBounds(this.mask, bounds, localRoot);
      }
      containsPoint(point, hitTestFn) {
        const mask = this.mask;
        return hitTestFn(mask, point);
      }
      destroy() {
        this.reset();
      }
      static test(mask) {
        return mask instanceof Sprite;
      }
    }
    AlphaMask.extension = ExtensionType.MaskEffect;

    "use strict";
    class ColorMask {
      constructor(options) {
        this.priority = 0;
        this.pipe = "colorMask";
        if (options == null ? void 0 : options.mask) {
          this.init(options.mask);
        }
      }
      init(mask) {
        this.mask = mask;
      }
      destroy() {
      }
      static test(mask) {
        return typeof mask === "number";
      }
    }
    ColorMask.extension = ExtensionType.MaskEffect;

    "use strict";
    class StencilMask {
      constructor(options) {
        this.priority = 0;
        this.pipe = "stencilMask";
        if (options == null ? void 0 : options.mask) {
          this.init(options.mask);
        }
      }
      init(mask) {
        this.mask = mask;
        this.mask.includeInBuild = false;
        this.mask.measurable = false;
      }
      reset() {
        if (this.mask === null)
          return;
        this.mask.measurable = true;
        this.mask.includeInBuild = true;
        this.mask = null;
      }
      addBounds(bounds, skipUpdateTransform) {
        addMaskBounds(this.mask, bounds, skipUpdateTransform);
      }
      addLocalBounds(bounds, localRoot) {
        addMaskLocalBounds(this.mask, bounds, localRoot);
      }
      containsPoint(point, hitTestFn) {
        const mask = this.mask;
        return hitTestFn(mask, point);
      }
      destroy() {
        this.reset();
      }
      static test(mask) {
        return mask instanceof Container;
      }
    }
    StencilMask.extension = ExtensionType.MaskEffect;

    "use strict";
    class CanvasSource extends TextureSource {
      constructor(options) {
        if (!options.resource) {
          options.resource = DOMAdapter.get().createCanvas();
        }
        if (!options.width) {
          options.width = options.resource.width;
          if (!options.autoDensity) {
            options.width /= options.resolution;
          }
        }
        if (!options.height) {
          options.height = options.resource.height;
          if (!options.autoDensity) {
            options.height /= options.resolution;
          }
        }
        super(options);
        this.uploadMethodId = "image";
        this.autoDensity = options.autoDensity;
        this.resizeCanvas();
        this.transparent = !!options.transparent;
      }
      resizeCanvas() {
        if (this.autoDensity && "style" in this.resource) {
          this.resource.style.width = `${this.width}px`;
          this.resource.style.height = `${this.height}px`;
        }
        if (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) {
          this.resource.width = this.pixelWidth;
          this.resource.height = this.pixelHeight;
        }
      }
      resize(width = this.width, height = this.height, resolution = this._resolution) {
        const didResize = super.resize(width, height, resolution);
        if (didResize) {
          this.resizeCanvas();
        }
        return didResize;
      }
      static test(resource) {
        return globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement || globalThis.OffscreenCanvas && resource instanceof OffscreenCanvas;
      }
      /**
       * Returns the 2D rendering context for the canvas.
       * Caches the context after creating it.
       * @returns The 2D rendering context of the canvas.
       */
      get context2D() {
        return this._context2D || (this._context2D = this.resource.getContext("2d"));
      }
    }
    CanvasSource.extension = ExtensionType.TextureSource;

    "use strict";
    class ImageSource extends TextureSource {
      constructor(options) {
        super(options);
        this.uploadMethodId = "image";
        this.autoGarbageCollect = true;
      }
      static test(resource) {
        return globalThis.HTMLImageElement && resource instanceof HTMLImageElement || typeof ImageBitmap !== "undefined" && resource instanceof ImageBitmap || globalThis.VideoFrame && resource instanceof VideoFrame;
      }
    }
    ImageSource.extension = ExtensionType.TextureSource;

    "use strict";
    let promise;
    async function detectVideoAlphaMode() {
      promise != null ? promise : promise = (async () => {
        var _a;
        const canvas = DOMAdapter.get().createCanvas(1, 1);
        const gl = canvas.getContext("webgl");
        if (!gl) {
          return "premultiply-alpha-on-upload";
        }
        const video = await new Promise((resolve) => {
          const video2 = document.createElement("video");
          video2.onloadeddata = () => resolve(video2);
          video2.onerror = () => resolve(null);
          video2.autoplay = false;
          video2.crossOrigin = "anonymous";
          video2.preload = "auto";
          video2.src = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHTEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggEXTbuMU6uEHFO7a1OsggG97AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQkBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua8yuAQAAAAAAAEPXgQFzxYgAAAAAAAAAAZyBACK1nIN1bmSIgQCGhVZfVlA5g4EBI+ODhAJiWgDglLCBArqBApqBAlPAgQFVsIRVuYEBElTDZ9Vzc9JjwItjxYgAAAAAAAAAAWfInEWjh0VOQ09ERVJEh49MYXZjIGxpYnZweC12cDlnyKJFo4hEVVJBVElPTkSHlDAwOjAwOjAwLjA0MDAwMDAwMAAAH0O2dcfngQCgwqGggQAAAIJJg0IAABAAFgA4JBwYSgAAICAAEb///4r+AAB1oZ2mm+6BAaWWgkmDQgAAEAAWADgkHBhKAAAgIABIQBxTu2uRu4+zgQC3iveBAfGCAXHwgQM=";
          video2.load();
        });
        if (!video) {
          return "premultiply-alpha-on-upload";
        }
        const texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        const framebuffer = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
        gl.framebufferTexture2D(
          gl.FRAMEBUFFER,
          gl.COLOR_ATTACHMENT0,
          gl.TEXTURE_2D,
          texture,
          0
        );
        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
        gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
        const pixel = new Uint8Array(4);
        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
        gl.deleteFramebuffer(framebuffer);
        gl.deleteTexture(texture);
        (_a = gl.getExtension("WEBGL_lose_context")) == null ? void 0 : _a.loseContext();
        return pixel[0] <= pixel[3] ? "premultiplied-alpha" : "premultiply-alpha-on-upload";
      })();
      return promise;
    }

    "use strict";
    var __defProp$14 = Object.defineProperty;
    var __defProps$q = Object.defineProperties;
    var __getOwnPropDescs$q = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$16 = Object.getOwnPropertySymbols;
    var __hasOwnProp$16 = Object.prototype.hasOwnProperty;
    var __propIsEnum$16 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$14 = (obj, key, value) => key in obj ? __defProp$14(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$14 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$16.call(b, prop))
          __defNormalProp$14(a, prop, b[prop]);
      if (__getOwnPropSymbols$16)
        for (var prop of __getOwnPropSymbols$16(b)) {
          if (__propIsEnum$16.call(b, prop))
            __defNormalProp$14(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$q = (a, b) => __defProps$q(a, __getOwnPropDescs$q(b));
    const _VideoSource = class _VideoSource extends TextureSource {
      constructor(options) {
        var _a;
        super(options);
        // Public
        /** Whether or not the video is ready to play. */
        this.isReady = false;
        /** The upload method for this texture. */
        this.uploadMethodId = "video";
        options = __spreadValues$14(__spreadValues$14({}, _VideoSource.defaultOptions), options);
        this._autoUpdate = true;
        this._isConnectedToTicker = false;
        this._updateFPS = options.updateFPS || 0;
        this._msToNextUpdate = 0;
        this.autoPlay = options.autoPlay !== false;
        this.alphaMode = (_a = options.alphaMode) != null ? _a : "premultiply-alpha-on-upload";
        this._videoFrameRequestCallback = this._videoFrameRequestCallback.bind(this);
        this._videoFrameRequestCallbackHandle = null;
        this._load = null;
        this._resolve = null;
        this._reject = null;
        this._onCanPlay = this._onCanPlay.bind(this);
        this._onCanPlayThrough = this._onCanPlayThrough.bind(this);
        this._onError = this._onError.bind(this);
        this._onPlayStart = this._onPlayStart.bind(this);
        this._onPlayStop = this._onPlayStop.bind(this);
        this._onSeeked = this._onSeeked.bind(this);
        if (options.autoLoad !== false) {
          void this.load();
        }
      }
      /** Update the video frame if the source is not destroyed and meets certain conditions. */
      updateFrame() {
        if (this.destroyed) {
          return;
        }
        if (this._updateFPS) {
          const elapsedMS = Ticker.shared.elapsedMS * this.resource.playbackRate;
          this._msToNextUpdate = Math.floor(this._msToNextUpdate - elapsedMS);
        }
        if (!this._updateFPS || this._msToNextUpdate <= 0) {
          this._msToNextUpdate = this._updateFPS ? Math.floor(1e3 / this._updateFPS) : 0;
        }
        if (this.isValid) {
          this.update();
        }
      }
      /** Callback to update the video frame and potentially request the next frame update. */
      _videoFrameRequestCallback() {
        this.updateFrame();
        if (this.destroyed) {
          this._videoFrameRequestCallbackHandle = null;
        } else {
          this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback(
            this._videoFrameRequestCallback
          );
        }
      }
      /**
       * Checks if the resource has valid dimensions.
       * @returns {boolean} True if width and height are set, otherwise false.
       */
      get isValid() {
        return !!this.resource.videoWidth && !!this.resource.videoHeight;
      }
      /**
       * Start preloading the video resource.
       * @returns {Promise<this>} Handle the validate event
       */
      async load() {
        if (this._load) {
          return this._load;
        }
        const source = this.resource;
        const options = this.options;
        if ((source.readyState === source.HAVE_ENOUGH_DATA || source.readyState === source.HAVE_FUTURE_DATA) && source.width && source.height) {
          source.complete = true;
        }
        source.addEventListener("play", this._onPlayStart);
        source.addEventListener("pause", this._onPlayStop);
        source.addEventListener("seeked", this._onSeeked);
        if (!this._isSourceReady()) {
          if (!options.preload) {
            source.addEventListener("canplay", this._onCanPlay);
          }
          source.addEventListener("canplaythrough", this._onCanPlayThrough);
          source.addEventListener("error", this._onError, true);
        } else {
          this._mediaReady();
        }
        this.alphaMode = await detectVideoAlphaMode();
        this._load = new Promise((resolve, reject) => {
          if (this.isValid) {
            resolve(this);
          } else {
            this._resolve = resolve;
            this._reject = reject;
            if (options.preloadTimeoutMs !== void 0) {
              this._preloadTimeout = setTimeout(() => {
                this._onError(new ErrorEvent(`Preload exceeded timeout of ${options.preloadTimeoutMs}ms`));
              });
            }
            source.load();
          }
        });
        return this._load;
      }
      /**
       * Handle video error events.
       * @param event - The error event
       */
      _onError(event) {
        this.resource.removeEventListener("error", this._onError, true);
        this.emit("error", event);
        if (this._reject) {
          this._reject(event);
          this._reject = null;
          this._resolve = null;
        }
      }
      /**
       * Checks if the underlying source is playing.
       * @returns True if playing.
       */
      _isSourcePlaying() {
        const source = this.resource;
        return !source.paused && !source.ended;
      }
      /**
       * Checks if the underlying source is ready for playing.
       * @returns True if ready.
       */
      _isSourceReady() {
        const source = this.resource;
        return source.readyState > 2;
      }
      /** Runs the update loop when the video is ready to play. */
      _onPlayStart() {
        if (!this.isValid) {
          this._mediaReady();
        }
        this._configureAutoUpdate();
      }
      /** Stops the update loop when a pause event is triggered. */
      _onPlayStop() {
        this._configureAutoUpdate();
      }
      /** Handles behavior when the video completes seeking to the current playback position. */
      _onSeeked() {
        if (this._autoUpdate && !this._isSourcePlaying()) {
          this._msToNextUpdate = 0;
          this.updateFrame();
          this._msToNextUpdate = 0;
        }
      }
      _onCanPlay() {
        const source = this.resource;
        source.removeEventListener("canplay", this._onCanPlay);
        this._mediaReady();
      }
      _onCanPlayThrough() {
        const source = this.resource;
        source.removeEventListener("canplaythrough", this._onCanPlay);
        if (this._preloadTimeout) {
          clearTimeout(this._preloadTimeout);
          this._preloadTimeout = void 0;
        }
        this._mediaReady();
      }
      /** Fired when the video is loaded and ready to play. */
      _mediaReady() {
        const source = this.resource;
        if (this.isValid) {
          this.isReady = true;
          this.resize(source.videoWidth, source.videoHeight);
        }
        this._msToNextUpdate = 0;
        this.updateFrame();
        this._msToNextUpdate = 0;
        if (this._resolve) {
          this._resolve(this);
          this._resolve = null;
          this._reject = null;
        }
        if (this._isSourcePlaying()) {
          this._onPlayStart();
        } else if (this.autoPlay) {
          void this.resource.play();
        }
      }
      /** Cleans up resources and event listeners associated with this texture. */
      destroy() {
        this._configureAutoUpdate();
        const source = this.resource;
        if (source) {
          source.removeEventListener("play", this._onPlayStart);
          source.removeEventListener("pause", this._onPlayStop);
          source.removeEventListener("seeked", this._onSeeked);
          source.removeEventListener("canplay", this._onCanPlay);
          source.removeEventListener("canplaythrough", this._onCanPlayThrough);
          source.removeEventListener("error", this._onError, true);
          source.pause();
          source.src = "";
          source.load();
        }
        super.destroy();
      }
      /** Should the base texture automatically update itself, set to true by default. */
      get autoUpdate() {
        return this._autoUpdate;
      }
      set autoUpdate(value) {
        if (value !== this._autoUpdate) {
          this._autoUpdate = value;
          this._configureAutoUpdate();
        }
      }
      /**
       * How many times a second to update the texture from the video.
       * Leave at 0 to update at every render.
       * A lower fps can help performance, as updating the texture at 60fps on a 30ps video may not be efficient.
       */
      get updateFPS() {
        return this._updateFPS;
      }
      set updateFPS(value) {
        if (value !== this._updateFPS) {
          this._updateFPS = value;
          this._configureAutoUpdate();
        }
      }
      /**
       * Configures the updating mechanism based on the current state and settings.
       *
       * This method decides between using the browser's native video frame callback or a custom ticker
       * for updating the video frame. It ensures optimal performance and responsiveness
       * based on the video's state, playback status, and the desired frames-per-second setting.
       *
       * - If `_autoUpdate` is enabled and the video source is playing:
       *   - It will prefer the native video frame callback if available and no specific FPS is set.
       *   - Otherwise, it will use a custom ticker for manual updates.
       * - If `_autoUpdate` is disabled or the video isn't playing, any active update mechanisms are halted.
       */
      _configureAutoUpdate() {
        if (this._autoUpdate && this._isSourcePlaying()) {
          if (!this._updateFPS && this.resource.requestVideoFrameCallback) {
            if (this._isConnectedToTicker) {
              Ticker.shared.remove(this.updateFrame, this);
              this._isConnectedToTicker = false;
              this._msToNextUpdate = 0;
            }
            if (this._videoFrameRequestCallbackHandle === null) {
              this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback(
                this._videoFrameRequestCallback
              );
            }
          } else {
            if (this._videoFrameRequestCallbackHandle !== null) {
              this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle);
              this._videoFrameRequestCallbackHandle = null;
            }
            if (!this._isConnectedToTicker) {
              Ticker.shared.add(this.updateFrame, this);
              this._isConnectedToTicker = true;
              this._msToNextUpdate = 0;
            }
          }
        } else {
          if (this._videoFrameRequestCallbackHandle !== null) {
            this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle);
            this._videoFrameRequestCallbackHandle = null;
          }
          if (this._isConnectedToTicker) {
            Ticker.shared.remove(this.updateFrame, this);
            this._isConnectedToTicker = false;
            this._msToNextUpdate = 0;
          }
        }
      }
      static test(resource) {
        return globalThis.HTMLVideoElement && resource instanceof HTMLVideoElement;
      }
    };
    _VideoSource.extension = ExtensionType.TextureSource;
    /** The default options for video sources. */
    _VideoSource.defaultOptions = __spreadProps$q(__spreadValues$14({}, TextureSource.defaultOptions), {
      /** If true, the video will start loading immediately. */
      autoLoad: true,
      /** If true, the video will start playing as soon as it is loaded. */
      autoPlay: true,
      /** The number of times a second to update the texture from the video. Leave at 0 to update at every render. */
      updateFPS: 0,
      /** If true, the video will be loaded with the `crossorigin` attribute. */
      crossorigin: true,
      /** If true, the video will loop when it ends. */
      loop: false,
      /** If true, the video will be muted. */
      muted: true,
      /** If true, the video will play inline. */
      playsinline: true,
      /** If true, the video will be preloaded. */
      preload: false
    });
    /**
     * Map of video MIME types that can't be directly derived from file extensions.
     * @readonly
     */
    _VideoSource.MIME_TYPES = {
      ogv: "video/ogg",
      mov: "video/quicktime",
      m4v: "video/mp4"
    };
    let VideoSource = _VideoSource;

    "use strict";
    class CacheClass {
      constructor() {
        this._parsers = [];
        this._cache = /* @__PURE__ */ new Map();
        this._cacheMap = /* @__PURE__ */ new Map();
      }
      /** Clear all entries. */
      reset() {
        this._cacheMap.clear();
        this._cache.clear();
      }
      /**
       * Check if the key exists
       * @param key - The key to check
       */
      has(key) {
        return this._cache.has(key);
      }
      /**
       * Fetch entry by key
       * @param key - The key of the entry to get
       */
      get(key) {
        const result = this._cache.get(key);
        if (!result) {
          warn(`[Assets] Asset id ${key} was not found in the Cache`);
        }
        return result;
      }
      /**
       * Set a value by key or keys name
       * @param key - The key or keys to set
       * @param value - The value to store in the cache or from which cacheable assets will be derived.
       */
      set(key, value) {
        const keys = convertToList(key);
        let cacheableAssets;
        for (let i = 0; i < this.parsers.length; i++) {
          const parser = this.parsers[i];
          if (parser.test(value)) {
            cacheableAssets = parser.getCacheableAssets(keys, value);
            break;
          }
        }
        const cacheableMap = new Map(Object.entries(cacheableAssets || {}));
        if (!cacheableAssets) {
          keys.forEach((key2) => {
            cacheableMap.set(key2, value);
          });
        }
        const cacheKeys = [...cacheableMap.keys()];
        const cachedAssets = {
          cacheKeys,
          keys
        };
        keys.forEach((key2) => {
          this._cacheMap.set(key2, cachedAssets);
        });
        cacheKeys.forEach((key2) => {
          const val = cacheableAssets ? cacheableAssets[key2] : value;
          if (this._cache.has(key2) && this._cache.get(key2) !== val) {
            warn("[Cache] already has key:", key2);
          }
          this._cache.set(key2, cacheableMap.get(key2));
        });
      }
      /**
       * Remove entry by key
       *
       * This function will also remove any associated alias from the cache also.
       * @param key - The key of the entry to remove
       */
      remove(key) {
        if (!this._cacheMap.has(key)) {
          warn(`[Assets] Asset id ${key} was not found in the Cache`);
          return;
        }
        const cacheMap = this._cacheMap.get(key);
        const cacheKeys = cacheMap.cacheKeys;
        cacheKeys.forEach((key2) => {
          this._cache.delete(key2);
        });
        cacheMap.keys.forEach((key2) => {
          this._cacheMap.delete(key2);
        });
      }
      /**
       * All loader parsers registered
       * @advanced
       */
      get parsers() {
        return this._parsers;
      }
    }
    const Cache = new CacheClass();

    "use strict";
    const sources = [];
    extensions.handleByList(ExtensionType.TextureSource, sources);
    function autoDetectSource(options = {}) {
      return textureSourceFrom(options);
    }
    function textureSourceFrom(options = {}) {
      const hasResource = options && options.resource;
      const res = hasResource ? options.resource : options;
      const opts = hasResource ? options : { resource: options };
      for (let i = 0; i < sources.length; i++) {
        const Source = sources[i];
        if (Source.test(res)) {
          return new Source(opts);
        }
      }
      throw new Error(`Could not find a source type for resource: ${opts.resource}`);
    }
    function resourceToTexture(options = {}, skipCache = false) {
      const hasResource = options && options.resource;
      const resource = hasResource ? options.resource : options;
      const opts = hasResource ? options : { resource: options };
      if (!skipCache && Cache.has(resource)) {
        return Cache.get(resource);
      }
      const texture = new Texture({ source: textureSourceFrom(opts) });
      texture.on("destroy", () => {
        if (Cache.has(resource)) {
          Cache.remove(resource);
        }
      });
      if (!skipCache) {
        Cache.set(resource, texture);
      }
      return texture;
    }
    function textureFrom(id, skipCache = false) {
      if (typeof id === "string") {
        return Cache.get(id);
      } else if (id instanceof TextureSource) {
        return new Texture({ source: id });
      }
      return resourceToTexture(id, skipCache);
    }
    Texture.from = textureFrom;
    TextureSource.from = textureSourceFrom;

    "use strict";
    extensions.add(AlphaMask, ColorMask, StencilMask, VideoSource, ImageSource, CanvasSource, BufferImageSource);

    "use strict";
    class BindGroup {
      /**
       * Create a new instance eof the Bind Group.
       * @param resources - The resources that are bound together for use by a shader.
       */
      constructor(resources) {
        /** The resources that are bound together for use by a shader. */
        this.resources = /* @__PURE__ */ Object.create(null);
        this._dirty = true;
        let index = 0;
        for (const i in resources) {
          const resource = resources[i];
          this.setResource(resource, index++);
        }
        this._updateKey();
      }
      /**
       * Updates the key if its flagged as dirty. This is used internally to
       * match this bind group to a WebGPU BindGroup.
       * @internal
       */
      _updateKey() {
        if (!this._dirty)
          return;
        this._dirty = false;
        const keyParts = [];
        let index = 0;
        for (const i in this.resources) {
          keyParts[index++] = this.resources[i]._resourceId;
        }
        this._key = keyParts.join("|");
      }
      /**
       * Set a resource at a given index. this function will
       * ensure that listeners will be removed from the current resource
       * and added to the new resource.
       * @param resource - The resource to set.
       * @param index - The index to set the resource at.
       */
      setResource(resource, index) {
        var _a, _b;
        const currentResource = this.resources[index];
        if (resource === currentResource)
          return;
        if (currentResource) {
          (_a = resource.off) == null ? void 0 : _a.call(resource, "change", this.onResourceChange, this);
        }
        (_b = resource.on) == null ? void 0 : _b.call(resource, "change", this.onResourceChange, this);
        this.resources[index] = resource;
        this._dirty = true;
      }
      /**
       * Returns the resource at the current specified index.
       * @param index - The index of the resource to get.
       * @returns - The resource at the specified index.
       */
      getResource(index) {
        return this.resources[index];
      }
      /**
       * Used internally to 'touch' each resource, to ensure that the GC
       * knows that all resources in this bind group are still being used.
       * @param now - The current time in milliseconds.
       * @param tick - The current tick.
       * @internal
       */
      _touch(now, tick) {
        const resources = this.resources;
        for (const i in resources) {
          resources[i]._gcLastUsed = now;
          resources[i]._touched = tick;
        }
      }
      /** Destroys this bind group and removes all listeners. */
      destroy() {
        var _a;
        const resources = this.resources;
        for (const i in resources) {
          const resource = resources[i];
          (_a = resource == null ? void 0 : resource.off) == null ? void 0 : _a.call(resource, "change", this.onResourceChange, this);
        }
        this.resources = null;
      }
      onResourceChange(resource) {
        this._dirty = true;
        if (resource.destroyed) {
          const resources = this.resources;
          for (const i in resources) {
            if (resources[i] === resource) {
              resources[i] = null;
            }
          }
        } else {
          this._updateKey();
        }
      }
    }

    "use strict";
    const cachedGroups = {};
    function getTextureBatchBindGroup(textures, size, maxTextures) {
      let uid = 2166136261;
      for (let i = 0; i < size; i++) {
        uid ^= textures[i].uid;
        uid = Math.imul(uid, 16777619);
        uid >>>= 0;
      }
      return cachedGroups[uid] || generateTextureBatchBindGroup(textures, size, uid, maxTextures);
    }
    function generateTextureBatchBindGroup(textures, size, key, maxTextures) {
      const bindGroupResources = {};
      let bindIndex = 0;
      for (let i = 0; i < maxTextures; i++) {
        const texture = i < size ? textures[i] : Texture.EMPTY.source;
        bindGroupResources[bindIndex++] = texture.source;
        bindGroupResources[bindIndex++] = texture.style;
      }
      const bindGroup = new BindGroup(bindGroupResources);
      cachedGroups[key] = bindGroup;
      return bindGroup;
    }

    "use strict";
    class ViewableBuffer {
      constructor(sizeOrBuffer) {
        if (typeof sizeOrBuffer === "number") {
          this.rawBinaryData = new ArrayBuffer(sizeOrBuffer);
        } else if (sizeOrBuffer instanceof Uint8Array) {
          this.rawBinaryData = sizeOrBuffer.buffer;
        } else {
          this.rawBinaryData = sizeOrBuffer;
        }
        this.uint32View = new Uint32Array(this.rawBinaryData);
        this.float32View = new Float32Array(this.rawBinaryData);
        this.size = this.rawBinaryData.byteLength;
      }
      /** View on the raw binary data as a `Int8Array`. */
      get int8View() {
        if (!this._int8View) {
          this._int8View = new Int8Array(this.rawBinaryData);
        }
        return this._int8View;
      }
      /** View on the raw binary data as a `Uint8Array`. */
      get uint8View() {
        if (!this._uint8View) {
          this._uint8View = new Uint8Array(this.rawBinaryData);
        }
        return this._uint8View;
      }
      /**  View on the raw binary data as a `Int16Array`. */
      get int16View() {
        if (!this._int16View) {
          this._int16View = new Int16Array(this.rawBinaryData);
        }
        return this._int16View;
      }
      /** View on the raw binary data as a `Int32Array`. */
      get int32View() {
        if (!this._int32View) {
          this._int32View = new Int32Array(this.rawBinaryData);
        }
        return this._int32View;
      }
      /** View on the raw binary data as a `Float64Array`. */
      get float64View() {
        if (!this._float64Array) {
          this._float64Array = new Float64Array(this.rawBinaryData);
        }
        return this._float64Array;
      }
      /** View on the raw binary data as a `BigUint64Array`. */
      get bigUint64View() {
        if (!this._bigUint64Array) {
          this._bigUint64Array = new BigUint64Array(this.rawBinaryData);
        }
        return this._bigUint64Array;
      }
      /**
       * Returns the view of the given type.
       * @param type - One of `int8`, `uint8`, `int16`,
       *    `uint16`, `int32`, `uint32`, and `float32`.
       * @returns - typed array of given type
       */
      view(type) {
        return this[`${type}View`];
      }
      /** Destroys all buffer references. Do not use after calling this. */
      destroy() {
        this.rawBinaryData = null;
        this.uint32View = null;
        this.float32View = null;
        this.uint16View = null;
        this._int8View = null;
        this._uint8View = null;
        this._int16View = null;
        this._int32View = null;
        this._float64Array = null;
        this._bigUint64Array = null;
      }
      /**
       * Returns the size of the given type in bytes.
       * @param type - One of `int8`, `uint8`, `int16`,
       *   `uint16`, `int32`, `uint32`, and `float32`.
       * @returns - size of the type in bytes
       */
      static sizeOf(type) {
        switch (type) {
          case "int8":
          case "uint8":
            return 1;
          case "int16":
          case "uint16":
            return 2;
          case "int32":
          case "uint32":
          case "float32":
            return 4;
          default:
            throw new Error(`${type} isn't a valid view type`);
        }
      }
    }

    "use strict";
    function fastCopy(sourceBuffer, destinationBuffer) {
      const lengthDouble = sourceBuffer.byteLength / 8 | 0;
      const sourceFloat64View = new Float64Array(sourceBuffer, 0, lengthDouble);
      const destinationFloat64View = new Float64Array(destinationBuffer, 0, lengthDouble);
      destinationFloat64View.set(sourceFloat64View);
      const remainingBytes = sourceBuffer.byteLength - lengthDouble * 8;
      if (remainingBytes > 0) {
        const sourceUint8View = new Uint8Array(sourceBuffer, lengthDouble * 8, remainingBytes);
        const destinationUint8View = new Uint8Array(destinationBuffer, lengthDouble * 8, remainingBytes);
        destinationUint8View.set(sourceUint8View);
      }
    }

    "use strict";
    const BLEND_TO_NPM = {
      normal: "normal-npm",
      add: "add-npm",
      screen: "screen-npm"
    };
    var STENCIL_MODES = /* @__PURE__ */ ((STENCIL_MODES2) => {
      STENCIL_MODES2[STENCIL_MODES2["DISABLED"] = 0] = "DISABLED";
      STENCIL_MODES2[STENCIL_MODES2["RENDERING_MASK_ADD"] = 1] = "RENDERING_MASK_ADD";
      STENCIL_MODES2[STENCIL_MODES2["MASK_ACTIVE"] = 2] = "MASK_ACTIVE";
      STENCIL_MODES2[STENCIL_MODES2["INVERSE_MASK_ACTIVE"] = 3] = "INVERSE_MASK_ACTIVE";
      STENCIL_MODES2[STENCIL_MODES2["RENDERING_MASK_REMOVE"] = 4] = "RENDERING_MASK_REMOVE";
      STENCIL_MODES2[STENCIL_MODES2["NONE"] = 5] = "NONE";
      return STENCIL_MODES2;
    })(STENCIL_MODES || {});

    "use strict";
    function getAdjustedBlendModeBlend(blendMode, textureSource) {
      if (textureSource.alphaMode === "no-premultiply-alpha") {
        return BLEND_TO_NPM[blendMode] || blendMode;
      }
      return blendMode;
    }

    "use strict";
    let context;
    function getTestContext() {
      if (!context || (context == null ? void 0 : context.isContextLost())) {
        const canvas = DOMAdapter.get().createCanvas();
        context = canvas.getContext("webgl", {});
      }
      return context;
    }

    "use strict";
    const fragTemplate$1 = [
      "precision mediump float;",
      "void main(void){",
      "float test = 0.1;",
      "%forloop%",
      "gl_FragColor = vec4(0.0);",
      "}"
    ].join("\n");
    function generateIfTestSrc(maxIfs) {
      let src = "";
      for (let i = 0; i < maxIfs; ++i) {
        if (i > 0) {
          src += "\nelse ";
        }
        if (i < maxIfs - 1) {
          src += `if(test == ${i}.0){}`;
        }
      }
      return src;
    }
    function checkMaxIfStatementsInShader(maxIfs, gl) {
      if (maxIfs === 0) {
        throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`");
      }
      const shader = gl.createShader(gl.FRAGMENT_SHADER);
      try {
        while (true) {
          const fragmentSrc = fragTemplate$1.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));
          gl.shaderSource(shader, fragmentSrc);
          gl.compileShader(shader);
          if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            maxIfs = maxIfs / 2 | 0;
          } else {
            break;
          }
        }
      } finally {
        gl.deleteShader(shader);
      }
      return maxIfs;
    }

    "use strict";
    let maxTexturesPerBatchCache = null;
    function getMaxTexturesPerBatch() {
      var _a;
      if (maxTexturesPerBatchCache)
        return maxTexturesPerBatchCache;
      const gl = getTestContext();
      maxTexturesPerBatchCache = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
      maxTexturesPerBatchCache = checkMaxIfStatementsInShader(
        maxTexturesPerBatchCache,
        gl
      );
      (_a = gl.getExtension("WEBGL_lose_context")) == null ? void 0 : _a.loseContext();
      return maxTexturesPerBatchCache;
    }

    "use strict";
    class BatchTextureArray {
      constructor() {
        /** Respective locations for textures. */
        this.ids = /* @__PURE__ */ Object.create(null);
        this.textures = [];
        this.count = 0;
      }
      /** Clear the textures and their locations. */
      clear() {
        for (let i = 0; i < this.count; i++) {
          const t = this.textures[i];
          this.textures[i] = null;
          this.ids[t.uid] = null;
        }
        this.count = 0;
      }
    }

    "use strict";
    var __defProp$13 = Object.defineProperty;
    var __getOwnPropSymbols$15 = Object.getOwnPropertySymbols;
    var __hasOwnProp$15 = Object.prototype.hasOwnProperty;
    var __propIsEnum$15 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$13 = (obj, key, value) => key in obj ? __defProp$13(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$13 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$15.call(b, prop))
          __defNormalProp$13(a, prop, b[prop]);
      if (__getOwnPropSymbols$15)
        for (var prop of __getOwnPropSymbols$15(b)) {
          if (__propIsEnum$15.call(b, prop))
            __defNormalProp$13(a, prop, b[prop]);
        }
      return a;
    };
    class Batch {
      constructor() {
        this.renderPipeId = "batch";
        this.action = "startBatch";
        // TODO - eventually this could be useful for flagging batches as dirty and then only rebuilding those ones
        // public elementStart = 0;
        // public elementSize = 0;
        // for drawing..
        this.start = 0;
        this.size = 0;
        this.textures = new BatchTextureArray();
        this.blendMode = "normal";
        this.topology = "triangle-strip";
        this.canBundle = true;
      }
      destroy() {
        this.textures = null;
        this.gpuBindGroup = null;
        this.bindGroup = null;
        this.batcher = null;
      }
    }
    const batchPool = [];
    let batchPoolIndex = 0;
    GlobalResourceRegistry.register({
      clear: () => {
        if (batchPool.length > 0) {
          for (const item of batchPool) {
            if (item)
              item.destroy();
          }
        }
        batchPool.length = 0;
        batchPoolIndex = 0;
      }
    });
    function getBatchFromPool() {
      return batchPoolIndex > 0 ? batchPool[--batchPoolIndex] : new Batch();
    }
    function returnBatchToPool(batch) {
      batchPool[batchPoolIndex++] = batch;
    }
    let BATCH_TICK = 0;
    const _Batcher = class _Batcher {
      constructor(options) {
        /** unique id for this batcher */
        this.uid = uid$1("batcher");
        /** Indicates whether the batch data has been modified and needs updating. */
        this.dirty = true;
        /** The current index of the batch being processed. */
        this.batchIndex = 0;
        /** An array of all batches created during the current rendering process. */
        this.batches = [];
        this._elements = [];
        options = __spreadValues$13(__spreadValues$13({}, _Batcher.defaultOptions), options);
        if (!options.maxTextures) {
          deprecation("v8.8.0", "maxTextures is a required option for Batcher now, please pass it in the options");
          options.maxTextures = getMaxTexturesPerBatch();
        }
        const { maxTextures, attributesInitialSize, indicesInitialSize } = options;
        this.attributeBuffer = new ViewableBuffer(attributesInitialSize * 4);
        this.indexBuffer = new Uint16Array(indicesInitialSize);
        this.maxTextures = maxTextures;
      }
      begin() {
        this.elementSize = 0;
        this.elementStart = 0;
        this.indexSize = 0;
        this.attributeSize = 0;
        for (let i = 0; i < this.batchIndex; i++) {
          returnBatchToPool(this.batches[i]);
        }
        this.batchIndex = 0;
        this._batchIndexStart = 0;
        this._batchIndexSize = 0;
        this.dirty = true;
      }
      add(batchableObject) {
        this._elements[this.elementSize++] = batchableObject;
        batchableObject._indexStart = this.indexSize;
        batchableObject._attributeStart = this.attributeSize;
        batchableObject._batcher = this;
        this.indexSize += batchableObject.indexSize;
        this.attributeSize += batchableObject.attributeSize * this.vertexSize;
      }
      checkAndUpdateTexture(batchableObject, texture) {
        const textureId = batchableObject._batch.textures.ids[texture._source.uid];
        if (!textureId && textureId !== 0)
          return false;
        batchableObject._textureId = textureId;
        batchableObject.texture = texture;
        return true;
      }
      updateElement(batchableObject) {
        this.dirty = true;
        const attributeBuffer = this.attributeBuffer;
        if (batchableObject.packAsQuad) {
          this.packQuadAttributes(
            batchableObject,
            attributeBuffer.float32View,
            attributeBuffer.uint32View,
            batchableObject._attributeStart,
            batchableObject._textureId
          );
        } else {
          this.packAttributes(
            batchableObject,
            attributeBuffer.float32View,
            attributeBuffer.uint32View,
            batchableObject._attributeStart,
            batchableObject._textureId
          );
        }
      }
      /**
       * breaks the batcher. This happens when a batch gets too big,
       * or we need to switch to a different type of rendering (a filter for example)
       * @param instructionSet
       */
      break(instructionSet) {
        const elements = this._elements;
        if (!elements[this.elementStart])
          return;
        let batch = getBatchFromPool();
        let textureBatch = batch.textures;
        textureBatch.clear();
        const firstElement = elements[this.elementStart];
        let blendMode = getAdjustedBlendModeBlend(firstElement.blendMode, firstElement.texture._source);
        let topology = firstElement.topology;
        if (this.attributeSize * 4 > this.attributeBuffer.size) {
          this._resizeAttributeBuffer(this.attributeSize * 4);
        }
        if (this.indexSize > this.indexBuffer.length) {
          this._resizeIndexBuffer(this.indexSize);
        }
        const f32 = this.attributeBuffer.float32View;
        const u32 = this.attributeBuffer.uint32View;
        const indexBuffer = this.indexBuffer;
        let size = this._batchIndexSize;
        let start = this._batchIndexStart;
        let action = "startBatch";
        const maxTextures = this.maxTextures;
        for (let i = this.elementStart; i < this.elementSize; ++i) {
          const element = elements[i];
          elements[i] = null;
          const texture = element.texture;
          const source = texture._source;
          const adjustedBlendMode = getAdjustedBlendModeBlend(element.blendMode, source);
          const breakRequired = blendMode !== adjustedBlendMode || topology !== element.topology;
          if (source._batchTick === BATCH_TICK && !breakRequired) {
            element._textureId = source._textureBindLocation;
            size += element.indexSize;
            if (element.packAsQuad) {
              this.packQuadAttributes(
                element,
                f32,
                u32,
                element._attributeStart,
                element._textureId
              );
              this.packQuadIndex(
                indexBuffer,
                element._indexStart,
                element._attributeStart / this.vertexSize
              );
            } else {
              this.packAttributes(
                element,
                f32,
                u32,
                element._attributeStart,
                element._textureId
              );
              this.packIndex(
                element,
                indexBuffer,
                element._indexStart,
                element._attributeStart / this.vertexSize
              );
            }
            element._batch = batch;
            continue;
          }
          source._batchTick = BATCH_TICK;
          if (textureBatch.count >= maxTextures || breakRequired) {
            this._finishBatch(
              batch,
              start,
              size - start,
              textureBatch,
              blendMode,
              topology,
              instructionSet,
              action
            );
            action = "renderBatch";
            start = size;
            blendMode = adjustedBlendMode;
            topology = element.topology;
            batch = getBatchFromPool();
            textureBatch = batch.textures;
            textureBatch.clear();
            ++BATCH_TICK;
          }
          element._textureId = source._textureBindLocation = textureBatch.count;
          textureBatch.ids[source.uid] = textureBatch.count;
          textureBatch.textures[textureBatch.count++] = source;
          element._batch = batch;
          size += element.indexSize;
          if (element.packAsQuad) {
            this.packQuadAttributes(
              element,
              f32,
              u32,
              element._attributeStart,
              element._textureId
            );
            this.packQuadIndex(
              indexBuffer,
              element._indexStart,
              element._attributeStart / this.vertexSize
            );
          } else {
            this.packAttributes(
              element,
              f32,
              u32,
              element._attributeStart,
              element._textureId
            );
            this.packIndex(
              element,
              indexBuffer,
              element._indexStart,
              element._attributeStart / this.vertexSize
            );
          }
        }
        if (textureBatch.count > 0) {
          this._finishBatch(
            batch,
            start,
            size - start,
            textureBatch,
            blendMode,
            topology,
            instructionSet,
            action
          );
          start = size;
          ++BATCH_TICK;
        }
        this.elementStart = this.elementSize;
        this._batchIndexStart = start;
        this._batchIndexSize = size;
      }
      _finishBatch(batch, indexStart, indexSize, textureBatch, blendMode, topology, instructionSet, action) {
        batch.gpuBindGroup = null;
        batch.bindGroup = null;
        batch.action = action;
        batch.batcher = this;
        batch.textures = textureBatch;
        batch.blendMode = blendMode;
        batch.topology = topology;
        batch.start = indexStart;
        batch.size = indexSize;
        ++BATCH_TICK;
        this.batches[this.batchIndex++] = batch;
        instructionSet.add(batch);
      }
      finish(instructionSet) {
        this.break(instructionSet);
      }
      /**
       * Resizes the attribute buffer to the given size (1 = 1 float32)
       * @param size - the size in vertices to ensure (not bytes!)
       */
      ensureAttributeBuffer(size) {
        if (size * 4 <= this.attributeBuffer.size)
          return;
        this._resizeAttributeBuffer(size * 4);
      }
      /**
       * Resizes the index buffer to the given size (1 = 1 float32)
       * @param size - the size in vertices to ensure (not bytes!)
       */
      ensureIndexBuffer(size) {
        if (size <= this.indexBuffer.length)
          return;
        this._resizeIndexBuffer(size);
      }
      _resizeAttributeBuffer(size) {
        const newSize = Math.max(size, this.attributeBuffer.size * 2);
        const newArrayBuffer = new ViewableBuffer(newSize);
        fastCopy(this.attributeBuffer.rawBinaryData, newArrayBuffer.rawBinaryData);
        this.attributeBuffer = newArrayBuffer;
      }
      _resizeIndexBuffer(size) {
        const indexBuffer = this.indexBuffer;
        let newSize = Math.max(size, indexBuffer.length * 1.5);
        newSize += newSize % 2;
        const newIndexBuffer = newSize > 65535 ? new Uint32Array(newSize) : new Uint16Array(newSize);
        if (newIndexBuffer.BYTES_PER_ELEMENT !== indexBuffer.BYTES_PER_ELEMENT) {
          for (let i = 0; i < indexBuffer.length; i++) {
            newIndexBuffer[i] = indexBuffer[i];
          }
        } else {
          fastCopy(indexBuffer.buffer, newIndexBuffer.buffer);
        }
        this.indexBuffer = newIndexBuffer;
      }
      packQuadIndex(indexBuffer, index, indicesOffset) {
        indexBuffer[index] = indicesOffset + 0;
        indexBuffer[index + 1] = indicesOffset + 1;
        indexBuffer[index + 2] = indicesOffset + 2;
        indexBuffer[index + 3] = indicesOffset + 0;
        indexBuffer[index + 4] = indicesOffset + 2;
        indexBuffer[index + 5] = indicesOffset + 3;
      }
      packIndex(element, indexBuffer, index, indicesOffset) {
        const indices = element.indices;
        const size = element.indexSize;
        const indexOffset = element.indexOffset;
        const attributeOffset = element.attributeOffset;
        for (let i = 0; i < size; i++) {
          indexBuffer[index++] = indicesOffset + indices[i + indexOffset] - attributeOffset;
        }
      }
      /**
       * Destroys the batch and its resources.
       * @param options - destruction options
       * @param options.shader - whether to destroy the associated shader
       */
      destroy(options = {}) {
        var _a;
        if (this.batches === null)
          return;
        for (let i = 0; i < this.batchIndex; i++) {
          returnBatchToPool(this.batches[i]);
        }
        this.batches = null;
        this.geometry.destroy(true);
        this.geometry = null;
        if (options.shader) {
          (_a = this.shader) == null ? void 0 : _a.destroy();
          this.shader = null;
        }
        for (let i = 0; i < this._elements.length; i++) {
          if (this._elements[i])
            this._elements[i]._batch = null;
        }
        this._elements = null;
        this.indexBuffer = null;
        this.attributeBuffer.destroy();
        this.attributeBuffer = null;
      }
    };
    _Batcher.defaultOptions = {
      maxTextures: null,
      attributesInitialSize: 4,
      indicesInitialSize: 6
    };
    let Batcher = _Batcher;

    "use strict";
    var BufferUsage = /* @__PURE__ */ ((BufferUsage2) => {
      BufferUsage2[BufferUsage2["MAP_READ"] = 1] = "MAP_READ";
      BufferUsage2[BufferUsage2["MAP_WRITE"] = 2] = "MAP_WRITE";
      BufferUsage2[BufferUsage2["COPY_SRC"] = 4] = "COPY_SRC";
      BufferUsage2[BufferUsage2["COPY_DST"] = 8] = "COPY_DST";
      BufferUsage2[BufferUsage2["INDEX"] = 16] = "INDEX";
      BufferUsage2[BufferUsage2["VERTEX"] = 32] = "VERTEX";
      BufferUsage2[BufferUsage2["UNIFORM"] = 64] = "UNIFORM";
      BufferUsage2[BufferUsage2["STORAGE"] = 128] = "STORAGE";
      BufferUsage2[BufferUsage2["INDIRECT"] = 256] = "INDIRECT";
      BufferUsage2[BufferUsage2["QUERY_RESOLVE"] = 512] = "QUERY_RESOLVE";
      BufferUsage2[BufferUsage2["STATIC"] = 1024] = "STATIC";
      return BufferUsage2;
    })(BufferUsage || {});

    "use strict";
    class Buffer extends EventEmitter {
      /**
       * Creates a new Buffer with the given options
       * @param options - the options for the buffer
       */
      constructor(options) {
        let { data, size } = options;
        const { usage, label, shrinkToFit } = options;
        super();
        /**
         * emits when the underlying buffer has changed shape (i.e. resized)
         * letting the renderer know that it needs to discard the old buffer on the GPU and create a new one
         * @event change
         */
        /**
         * emits when the underlying buffer data has been updated. letting the renderer know
         * that it needs to update the buffer on the GPU
         * @event update
         */
        /**
         * emits when the buffer is destroyed. letting the renderer know that it needs to destroy the buffer on the GPU
         * @event destroy
         */
        /** @internal */
        this._gpuData = /* @__PURE__ */ Object.create(null);
        /** @internal */
        this._gcLastUsed = -1;
        /** If set to true, the buffer will be garbage collected automatically when it is not used. */
        this.autoGarbageCollect = true;
        /** a unique id for this uniform group used through the renderer */
        this.uid = uid$1("buffer");
        /**
         * a resource type, used to identify how to handle it when its in a bind group / shader resource
         * @internal
         */
        this._resourceType = "buffer";
        /**
         * the resource id used internally by the renderer to build bind group keys
         * @internal
         */
        this._resourceId = uid$1("resource");
        /**
         * used internally to know if a uniform group was used in the last render pass
         * @internal
         */
        this._touched = 0;
        /** @internal */
        this._updateID = 1;
        this._dataInt32 = null;
        /**
         * should the GPU buffer be shrunk when the data becomes smaller?
         * changing this will cause the buffer to be destroyed and a new one created on the GPU
         * this can be expensive, especially if the buffer is already big enough!
         * setting this to false will prevent the buffer from being shrunk. This will yield better performance
         * if you are constantly setting data that is changing size often.
         * @default true
         */
        this.shrinkToFit = true;
        /**
         * Has the buffer been destroyed?
         * @readonly
         */
        this.destroyed = false;
        if (data instanceof Array) {
          data = new Float32Array(data);
        }
        this._data = data;
        size != null ? size : size = data == null ? void 0 : data.byteLength;
        const mappedAtCreation = !!data;
        this.descriptor = {
          size,
          usage,
          mappedAtCreation,
          label
        };
        this.shrinkToFit = shrinkToFit != null ? shrinkToFit : true;
      }
      /** the data in the buffer */
      get data() {
        return this._data;
      }
      set data(value) {
        this.setDataWithSize(value, value.length, true);
      }
      get dataInt32() {
        if (!this._dataInt32) {
          this._dataInt32 = new Int32Array(this.data.buffer);
        }
        return this._dataInt32;
      }
      /** whether the buffer is static or not */
      get static() {
        return !!(this.descriptor.usage & BufferUsage.STATIC);
      }
      set static(value) {
        if (value) {
          this.descriptor.usage |= BufferUsage.STATIC;
        } else {
          this.descriptor.usage &= ~BufferUsage.STATIC;
        }
      }
      /**
       * Sets the data in the buffer to the given value. This will immediately update the buffer on the GPU.
       * If you only want to update a subset of the buffer, you can pass in the size of the data.
       * @param value - the data to set
       * @param size - the size of the data in bytes
       * @param syncGPU - should the buffer be updated on the GPU immediately?
       */
      setDataWithSize(value, size, syncGPU) {
        this._updateID++;
        this._updateSize = size * value.BYTES_PER_ELEMENT;
        if (this._data === value) {
          if (syncGPU)
            this.emit("update", this);
          return;
        }
        const oldData = this._data;
        this._data = value;
        this._dataInt32 = null;
        if (!oldData || oldData.length !== value.length) {
          if (!this.shrinkToFit && oldData && value.byteLength < oldData.byteLength) {
            if (syncGPU)
              this.emit("update", this);
          } else {
            this.descriptor.size = value.byteLength;
            this._resourceId = uid$1("resource");
            this.emit("change", this);
          }
          return;
        }
        if (syncGPU)
          this.emit("update", this);
      }
      /**
       * updates the buffer on the GPU to reflect the data in the buffer.
       * By default it will update the entire buffer. If you only want to update a subset of the buffer,
       * you can pass in the size of the buffer to update.
       * @param sizeInBytes - the new size of the buffer in bytes
       */
      update(sizeInBytes) {
        this._updateSize = sizeInBytes != null ? sizeInBytes : this._updateSize;
        this._updateID++;
        this.emit("update", this);
      }
      /** Unloads the buffer from the GPU */
      unload() {
        var _a;
        this.emit("unload", this);
        for (const key in this._gpuData) {
          (_a = this._gpuData[key]) == null ? void 0 : _a.destroy();
        }
        this._gpuData = /* @__PURE__ */ Object.create(null);
      }
      /** Destroys the buffer */
      destroy() {
        this.destroyed = true;
        this.unload();
        this.emit("destroy", this);
        this.emit("change", this);
        this._data = null;
        this.descriptor = null;
        this.removeAllListeners();
      }
    }

    "use strict";
    function ensureIsBuffer(buffer, index) {
      if (!(buffer instanceof Buffer)) {
        let usage = index ? BufferUsage.INDEX : BufferUsage.VERTEX;
        if (buffer instanceof Array) {
          if (index) {
            buffer = new Uint32Array(buffer);
            usage = BufferUsage.INDEX | BufferUsage.COPY_DST;
          } else {
            buffer = new Float32Array(buffer);
            usage = BufferUsage.VERTEX | BufferUsage.COPY_DST;
          }
        }
        buffer = new Buffer({
          data: buffer,
          label: index ? "index-mesh-buffer" : "vertex-mesh-buffer",
          usage
        });
      }
      return buffer;
    }

    "use strict";
    function getGeometryBounds(geometry, attributeId, bounds) {
      const attribute = geometry.getAttribute(attributeId);
      if (!attribute) {
        bounds.minX = 0;
        bounds.minY = 0;
        bounds.maxX = 0;
        bounds.maxY = 0;
        return bounds;
      }
      const data = attribute.buffer.data;
      let minX = Infinity;
      let minY = Infinity;
      let maxX = -Infinity;
      let maxY = -Infinity;
      const byteSize = data.BYTES_PER_ELEMENT;
      const offset = (attribute.offset || 0) / byteSize;
      const stride = (attribute.stride || 2 * 4) / byteSize;
      for (let i = offset; i < data.length; i += stride) {
        const x = data[i];
        const y = data[i + 1];
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
      }
      bounds.minX = minX;
      bounds.minY = minY;
      bounds.maxX = maxX;
      bounds.maxY = maxY;
      return bounds;
    }

    "use strict";
    function ensureIsAttribute(attribute) {
      if (attribute instanceof Buffer || Array.isArray(attribute) || attribute.BYTES_PER_ELEMENT) {
        attribute = {
          buffer: attribute
        };
      }
      attribute.buffer = ensureIsBuffer(attribute.buffer, false);
      return attribute;
    }
    class Geometry extends EventEmitter {
      /**
       * Create a new instance of a geometry
       * @param options - The options for the geometry.
       */
      constructor(options = {}) {
        var _a;
        super();
        /** @internal */
        this._gpuData = /* @__PURE__ */ Object.create(null);
        /** If set to true, the resource will be garbage collected automatically when it is not used. */
        this.autoGarbageCollect = true;
        /** @internal */
        this._gcLastUsed = -1;
        /** The unique id of the geometry. */
        this.uid = uid$1("geometry");
        /**
         * the layout key will be generated by WebGPU all geometries that have the same structure
         * will have the same layout key. This is used to cache the pipeline layout
         * @internal
         */
        this._layoutKey = 0;
        /** the instance count of the geometry to draw */
        this.instanceCount = 1;
        this._bounds = new Bounds();
        this._boundsDirty = true;
        const { attributes, indexBuffer, topology } = options;
        this.buffers = [];
        this.attributes = {};
        if (attributes) {
          for (const i in attributes) {
            this.addAttribute(i, attributes[i]);
          }
        }
        this.instanceCount = (_a = options.instanceCount) != null ? _a : 1;
        if (indexBuffer) {
          this.addIndex(indexBuffer);
        }
        this.topology = topology || "triangle-list";
      }
      onBufferUpdate() {
        this._boundsDirty = true;
        this.emit("update", this);
      }
      /**
       * Returns the requested attribute.
       * @param id - The name of the attribute required
       * @returns - The attribute requested.
       */
      getAttribute(id) {
        return this.attributes[id];
      }
      /**
       * Returns the index buffer
       * @returns - The index buffer.
       */
      getIndex() {
        return this.indexBuffer;
      }
      /**
       * Returns the requested buffer.
       * @param id - The name of the buffer required.
       * @returns - The buffer requested.
       */
      getBuffer(id) {
        return this.getAttribute(id).buffer;
      }
      /**
       * Used to figure out how many vertices there are in this geometry
       * @returns the number of vertices in the geometry
       */
      getSize() {
        for (const i in this.attributes) {
          const attribute = this.attributes[i];
          const buffer = attribute.buffer;
          return buffer.data.length / (attribute.stride / 4 || attribute.size);
        }
        return 0;
      }
      /**
       * Adds an attribute to the geometry.
       * @param name - The name of the attribute to add.
       * @param attributeOption - The attribute option to add.
       */
      addAttribute(name, attributeOption) {
        const attribute = ensureIsAttribute(attributeOption);
        const bufferIndex = this.buffers.indexOf(attribute.buffer);
        if (bufferIndex === -1) {
          this.buffers.push(attribute.buffer);
          attribute.buffer.on("update", this.onBufferUpdate, this);
          attribute.buffer.on("change", this.onBufferUpdate, this);
        }
        this.attributes[name] = attribute;
      }
      /**
       * Adds an index buffer to the geometry.
       * @param indexBuffer - The index buffer to add. Can be a Buffer, TypedArray, or an array of numbers.
       */
      addIndex(indexBuffer) {
        this.indexBuffer = ensureIsBuffer(indexBuffer, true);
        this.buffers.push(this.indexBuffer);
      }
      /** Returns the bounds of the geometry. */
      get bounds() {
        if (!this._boundsDirty)
          return this._bounds;
        this._boundsDirty = false;
        return getGeometryBounds(this, "aPosition", this._bounds);
      }
      /** Unloads the geometry from the GPU. */
      unload() {
        var _a;
        this.emit("unload", this);
        for (const key in this._gpuData) {
          (_a = this._gpuData[key]) == null ? void 0 : _a.destroy();
        }
        this._gpuData = /* @__PURE__ */ Object.create(null);
      }
      /**
       * destroys the geometry.
       * @param destroyBuffers - destroy the buffers associated with this geometry
       */
      destroy(destroyBuffers = false) {
        var _a;
        this.emit("destroy", this);
        this.removeAllListeners();
        if (destroyBuffers) {
          this.buffers.forEach((buffer) => buffer.destroy());
        }
        this.unload();
        (_a = this.indexBuffer) == null ? void 0 : _a.destroy();
        this.attributes = null;
        this.buffers = null;
        this.indexBuffer = null;
        this._bounds = null;
      }
    }

    "use strict";
    const placeHolderBufferData = new Float32Array(1);
    const placeHolderIndexData = new Uint32Array(1);
    class BatchGeometry extends Geometry {
      constructor() {
        const vertexSize = 6;
        const attributeBuffer = new Buffer({
          data: placeHolderBufferData,
          label: "attribute-batch-buffer",
          usage: BufferUsage.VERTEX | BufferUsage.COPY_DST,
          shrinkToFit: false
        });
        const indexBuffer = new Buffer({
          data: placeHolderIndexData,
          label: "index-batch-buffer",
          usage: BufferUsage.INDEX | BufferUsage.COPY_DST,
          // | BufferUsage.STATIC,
          shrinkToFit: false
        });
        const stride = vertexSize * 4;
        super({
          attributes: {
            aPosition: {
              buffer: attributeBuffer,
              format: "float32x2",
              stride,
              offset: 0
            },
            aUV: {
              buffer: attributeBuffer,
              format: "float32x2",
              stride,
              offset: 2 * 4
            },
            aColor: {
              buffer: attributeBuffer,
              format: "unorm8x4",
              stride,
              offset: 4 * 4
            },
            aTextureIdAndRound: {
              buffer: attributeBuffer,
              format: "uint16x2",
              stride,
              offset: 5 * 4
            }
          },
          indexBuffer
        });
      }
    }

    "use strict";
    const idCounts = /* @__PURE__ */ Object.create(null);
    const idHash = /* @__PURE__ */ Object.create(null);
    function createIdFromString(value, groupId) {
      let id = idHash[value];
      if (id === void 0) {
        if (idCounts[groupId] === void 0) {
          idCounts[groupId] = 1;
        }
        idHash[value] = id = idCounts[groupId]++;
      }
      return id;
    }

    "use strict";
    let maxFragmentPrecision;
    function getMaxFragmentPrecision() {
      if (!maxFragmentPrecision) {
        maxFragmentPrecision = "mediump";
        const gl = getTestContext();
        if (gl) {
          if (gl.getShaderPrecisionFormat) {
            const shaderFragment = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
            maxFragmentPrecision = shaderFragment.precision ? "highp" : "mediump";
          }
        }
      }
      return maxFragmentPrecision;
    }

    "use strict";
    function addProgramDefines(src, isES300, isFragment) {
      if (isES300)
        return src;
      if (isFragment) {
        src = src.replace("out vec4 finalColor;", "");
        return `

        #ifdef GL_ES // This checks if it is WebGL1
        #define in varying
        #define finalColor gl_FragColor
        #define texture texture2D
        #endif
        ${src}
        `;
      }
      return `

        #ifdef GL_ES // This checks if it is WebGL1
        #define in attribute
        #define out varying
        #endif
        ${src}
        `;
    }

    "use strict";
    function ensurePrecision(src, options, isFragment) {
      const maxSupportedPrecision = isFragment ? options.maxSupportedFragmentPrecision : options.maxSupportedVertexPrecision;
      if (src.substring(0, 9) !== "precision") {
        let precision = isFragment ? options.requestedFragmentPrecision : options.requestedVertexPrecision;
        if (precision === "highp" && maxSupportedPrecision !== "highp") {
          precision = "mediump";
        }
        return `precision ${precision} float;
${src}`;
      } else if (maxSupportedPrecision !== "highp" && src.substring(0, 15) === "precision highp") {
        return src.replace("precision highp", "precision mediump");
      }
      return src;
    }

    "use strict";
    function insertVersion(src, isES300) {
      if (!isES300)
        return src;
      return `#version 300 es
${src}`;
    }

    "use strict";
    const fragmentNameCache = {};
    const VertexNameCache = {};
    function setProgramName(src, { name = `pixi-program` }, isFragment = true) {
      name = name.replace(/\s+/g, "-");
      name += isFragment ? "-fragment" : "-vertex";
      const nameCache = isFragment ? fragmentNameCache : VertexNameCache;
      if (nameCache[name]) {
        nameCache[name]++;
        name += `-${nameCache[name]}`;
      } else {
        nameCache[name] = 1;
      }
      if (src.indexOf("#define SHADER_NAME") !== -1)
        return src;
      const shaderName = `#define SHADER_NAME ${name}`;
      return `${shaderName}
${src}`;
    }

    "use strict";
    function stripVersion(src, isES300) {
      if (!isES300)
        return src;
      return src.replace("#version 300 es", "");
    }

    "use strict";
    var __defProp$12 = Object.defineProperty;
    var __getOwnPropSymbols$14 = Object.getOwnPropertySymbols;
    var __hasOwnProp$14 = Object.prototype.hasOwnProperty;
    var __propIsEnum$14 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$12 = (obj, key, value) => key in obj ? __defProp$12(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$12 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$14.call(b, prop))
          __defNormalProp$12(a, prop, b[prop]);
      if (__getOwnPropSymbols$14)
        for (var prop of __getOwnPropSymbols$14(b)) {
          if (__propIsEnum$14.call(b, prop))
            __defNormalProp$12(a, prop, b[prop]);
        }
      return a;
    };
    const processes = {
      // strips any version headers..
      stripVersion,
      // adds precision string if not already present
      ensurePrecision,
      // add some defines if WebGL1 to make it more compatible with WebGL2 shaders
      addProgramDefines,
      // add the program name to the shader
      setProgramName,
      // add the version string to the shader header
      insertVersion
    };
    const programCache$1 = /* @__PURE__ */ Object.create(null);
    const _GlProgram = class _GlProgram {
      /**
       * Creates a shiny new GlProgram. Used by WebGL renderer.
       * @param options - The options for the program.
       */
      constructor(options) {
        options = __spreadValues$12(__spreadValues$12({}, _GlProgram.defaultOptions), options);
        const isES300 = options.fragment.indexOf("#version 300 es") !== -1;
        const preprocessorOptions = {
          stripVersion: isES300,
          ensurePrecision: {
            requestedFragmentPrecision: options.preferredFragmentPrecision,
            requestedVertexPrecision: options.preferredVertexPrecision,
            maxSupportedVertexPrecision: "highp",
            maxSupportedFragmentPrecision: getMaxFragmentPrecision()
          },
          setProgramName: {
            name: options.name
          },
          addProgramDefines: isES300,
          insertVersion: isES300
        };
        let fragment = options.fragment;
        let vertex = options.vertex;
        Object.keys(processes).forEach((processKey) => {
          const processOptions = preprocessorOptions[processKey];
          fragment = processes[processKey](fragment, processOptions, true);
          vertex = processes[processKey](vertex, processOptions, false);
        });
        this.fragment = fragment;
        this.vertex = vertex;
        this.transformFeedbackVaryings = options.transformFeedbackVaryings;
        this._key = createIdFromString(`${this.vertex}:${this.fragment}`, "gl-program");
      }
      /** destroys the program */
      destroy() {
        this.fragment = null;
        this.vertex = null;
        this._attributeData = null;
        this._uniformData = null;
        this._uniformBlockData = null;
        this.transformFeedbackVaryings = null;
        programCache$1[this._cacheKey] = null;
      }
      /**
       * Helper function that creates a program for a given source.
       * It will check the program cache if the program has already been created.
       * If it has that one will be returned, if not a new one will be created and cached.
       * @param options - The options for the program.
       * @returns A program using the same source
       */
      static from(options) {
        const key = `${options.vertex}:${options.fragment}`;
        if (!programCache$1[key]) {
          programCache$1[key] = new _GlProgram(options);
          programCache$1[key]._cacheKey = key;
        }
        return programCache$1[key];
      }
    };
    /** The default options used by the program. */
    _GlProgram.defaultOptions = {
      preferredVertexPrecision: "highp",
      preferredFragmentPrecision: "mediump"
    };
    let GlProgram = _GlProgram;

    "use strict";
    const attributeFormatData = {
      uint8x2: { size: 2, stride: 2, normalised: false },
      uint8x4: { size: 4, stride: 4, normalised: false },
      sint8x2: { size: 2, stride: 2, normalised: false },
      sint8x4: { size: 4, stride: 4, normalised: false },
      unorm8x2: { size: 2, stride: 2, normalised: true },
      unorm8x4: { size: 4, stride: 4, normalised: true },
      snorm8x2: { size: 2, stride: 2, normalised: true },
      snorm8x4: { size: 4, stride: 4, normalised: true },
      uint16x2: { size: 2, stride: 4, normalised: false },
      uint16x4: { size: 4, stride: 8, normalised: false },
      sint16x2: { size: 2, stride: 4, normalised: false },
      sint16x4: { size: 4, stride: 8, normalised: false },
      unorm16x2: { size: 2, stride: 4, normalised: true },
      unorm16x4: { size: 4, stride: 8, normalised: true },
      snorm16x2: { size: 2, stride: 4, normalised: true },
      snorm16x4: { size: 4, stride: 8, normalised: true },
      float16x2: { size: 2, stride: 4, normalised: false },
      float16x4: { size: 4, stride: 8, normalised: false },
      float32: { size: 1, stride: 4, normalised: false },
      float32x2: { size: 2, stride: 8, normalised: false },
      float32x3: { size: 3, stride: 12, normalised: false },
      float32x4: { size: 4, stride: 16, normalised: false },
      uint32: { size: 1, stride: 4, normalised: false },
      uint32x2: { size: 2, stride: 8, normalised: false },
      uint32x3: { size: 3, stride: 12, normalised: false },
      uint32x4: { size: 4, stride: 16, normalised: false },
      sint32: { size: 1, stride: 4, normalised: false },
      sint32x2: { size: 2, stride: 8, normalised: false },
      sint32x3: { size: 3, stride: 12, normalised: false },
      sint32x4: { size: 4, stride: 16, normalised: false }
    };
    function getAttributeInfoFromFormat(format) {
      var _a;
      return (_a = attributeFormatData[format]) != null ? _a : attributeFormatData.float32;
    }

    "use strict";
    const WGSL_TO_VERTEX_TYPES = {
      f32: "float32",
      "vec2<f32>": "float32x2",
      "vec3<f32>": "float32x3",
      "vec4<f32>": "float32x4",
      vec2f: "float32x2",
      vec3f: "float32x3",
      vec4f: "float32x4",
      i32: "sint32",
      "vec2<i32>": "sint32x2",
      "vec3<i32>": "sint32x3",
      "vec4<i32>": "sint32x4",
      u32: "uint32",
      "vec2<u32>": "uint32x2",
      "vec3<u32>": "uint32x3",
      "vec4<u32>": "uint32x4",
      bool: "uint32",
      "vec2<bool>": "uint32x2",
      "vec3<bool>": "uint32x3",
      "vec4<bool>": "uint32x4"
    };
    function extractAttributesFromGpuProgram({ source, entryPoint }) {
      var _a;
      const results = {};
      const mainVertStart = source.indexOf(`fn ${entryPoint}`);
      if (mainVertStart !== -1) {
        const arrowFunctionStart = source.indexOf("->", mainVertStart);
        if (arrowFunctionStart !== -1) {
          const functionArgsSubstring = source.substring(mainVertStart, arrowFunctionStart);
          const inputsRegex = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g;
          let match;
          while ((match = inputsRegex.exec(functionArgsSubstring)) !== null) {
            const format = (_a = WGSL_TO_VERTEX_TYPES[match[3]]) != null ? _a : "float32";
            results[match[2]] = {
              location: parseInt(match[1], 10),
              format,
              stride: getAttributeInfoFromFormat(format).stride,
              offset: 0,
              instance: false,
              start: 0
            };
          }
        }
      }
      return results;
    }

    "use strict";
    function extractStructAndGroups(wgsl) {
      var _a, _b, _c;
      const linePattern = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g;
      const groupPattern = /@group\((\d+)\)/;
      const bindingPattern = /@binding\((\d+)\)/;
      const namePattern = /var(<[^>]+>)? (\w+)/;
      const typePattern = /:\s*(\w+)/;
      const structPattern = /struct\s+(\w+)\s*{([^}]+)}/g;
      const structMemberPattern = /(\w+)\s*:\s*([\w\<\>]+)/g;
      const structName = /struct\s+(\w+)/;
      const groups = (_a = wgsl.match(linePattern)) == null ? void 0 : _a.map((item) => ({
        group: parseInt(item.match(groupPattern)[1], 10),
        binding: parseInt(item.match(bindingPattern)[1], 10),
        name: item.match(namePattern)[2],
        isUniform: item.match(namePattern)[1] === "<uniform>",
        type: item.match(typePattern)[1]
      }));
      if (!groups) {
        return {
          groups: [],
          structs: []
        };
      }
      const structs = (_c = (_b = wgsl.match(structPattern)) == null ? void 0 : _b.map((struct) => {
        const name = struct.match(structName)[1];
        const members = struct.match(structMemberPattern).reduce((acc, member) => {
          const [name2, type] = member.split(":");
          acc[name2.trim()] = type.trim();
          return acc;
        }, {});
        if (!members) {
          return null;
        }
        return { name, members };
      }).filter(({ name }) => groups.some((group) => group.type === name))) != null ? _c : [];
      return {
        groups,
        structs
      };
    }

    "use strict";
    var ShaderStage = /* @__PURE__ */ ((ShaderStage2) => {
      ShaderStage2[ShaderStage2["VERTEX"] = 1] = "VERTEX";
      ShaderStage2[ShaderStage2["FRAGMENT"] = 2] = "FRAGMENT";
      ShaderStage2[ShaderStage2["COMPUTE"] = 4] = "COMPUTE";
      return ShaderStage2;
    })(ShaderStage || {});

    "use strict";
    function generateGpuLayoutGroups({ groups }) {
      const layout = [];
      for (let i = 0; i < groups.length; i++) {
        const group = groups[i];
        if (!layout[group.group]) {
          layout[group.group] = [];
        }
        if (group.isUniform) {
          layout[group.group].push({
            binding: group.binding,
            visibility: ShaderStage.VERTEX | ShaderStage.FRAGMENT,
            buffer: {
              type: "uniform"
            }
          });
        } else if (group.type === "sampler") {
          layout[group.group].push({
            binding: group.binding,
            visibility: ShaderStage.FRAGMENT,
            sampler: {
              type: "filtering"
            }
          });
        } else if (group.type === "texture_2d") {
          layout[group.group].push({
            binding: group.binding,
            visibility: ShaderStage.FRAGMENT,
            texture: {
              sampleType: "float",
              viewDimension: "2d",
              multisampled: false
            }
          });
        }
      }
      return layout;
    }

    "use strict";
    function generateLayoutHash({ groups }) {
      const layout = [];
      for (let i = 0; i < groups.length; i++) {
        const group = groups[i];
        if (!layout[group.group]) {
          layout[group.group] = {};
        }
        layout[group.group][group.name] = group.binding;
      }
      return layout;
    }

    "use strict";
    function removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups) {
      const structNameSet = /* @__PURE__ */ new Set();
      const dupeGroupKeySet = /* @__PURE__ */ new Set();
      const structs = [...vertexStructsAndGroups.structs, ...fragmentStructsAndGroups.structs].filter((struct) => {
        if (structNameSet.has(struct.name)) {
          return false;
        }
        structNameSet.add(struct.name);
        return true;
      });
      const groups = [...vertexStructsAndGroups.groups, ...fragmentStructsAndGroups.groups].filter((group) => {
        const key = `${group.name}-${group.binding}`;
        if (dupeGroupKeySet.has(key)) {
          return false;
        }
        dupeGroupKeySet.add(key);
        return true;
      });
      return { structs, groups };
    }

    "use strict";
    const programCache = /* @__PURE__ */ Object.create(null);
    class GpuProgram {
      /**
       * Create a new GpuProgram
       * @param options - The options for the gpu program
       */
      constructor(options) {
        /** @internal */
        this._layoutKey = 0;
        /** @internal */
        this._attributeLocationsKey = 0;
        var _a, _b;
        const { fragment, vertex, layout, gpuLayout, name } = options;
        this.name = name;
        this.fragment = fragment;
        this.vertex = vertex;
        if (fragment.source === vertex.source) {
          const structsAndGroups = extractStructAndGroups(fragment.source);
          this.structsAndGroups = structsAndGroups;
        } else {
          const vertexStructsAndGroups = extractStructAndGroups(vertex.source);
          const fragmentStructsAndGroups = extractStructAndGroups(fragment.source);
          this.structsAndGroups = removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups);
        }
        this.layout = layout != null ? layout : generateLayoutHash(this.structsAndGroups);
        this.gpuLayout = gpuLayout != null ? gpuLayout : generateGpuLayoutGroups(this.structsAndGroups);
        this.autoAssignGlobalUniforms = !!(((_a = this.layout[0]) == null ? void 0 : _a.globalUniforms) !== void 0);
        this.autoAssignLocalUniforms = !!(((_b = this.layout[1]) == null ? void 0 : _b.localUniforms) !== void 0);
        this._generateProgramKey();
      }
      // TODO maker this pure
      _generateProgramKey() {
        const { vertex, fragment } = this;
        const bigKey = vertex.source + fragment.source + vertex.entryPoint + fragment.entryPoint;
        this._layoutKey = createIdFromString(bigKey, "program");
      }
      get attributeData() {
        var _a;
        (_a = this._attributeData) != null ? _a : this._attributeData = extractAttributesFromGpuProgram(this.vertex);
        return this._attributeData;
      }
      /** destroys the program */
      destroy() {
        this.gpuLayout = null;
        this.layout = null;
        this.structsAndGroups = null;
        this.fragment = null;
        this.vertex = null;
        programCache[this._cacheKey] = null;
      }
      /**
       * Helper function that creates a program for a given source.
       * It will check the program cache if the program has already been created.
       * If it has that one will be returned, if not a new one will be created and cached.
       * @param options - The options for the program.
       * @returns A program using the same source
       */
      static from(options) {
        const key = `${options.vertex.source}:${options.fragment.source}:${options.fragment.entryPoint}:${options.vertex.entryPoint}`;
        if (!programCache[key]) {
          programCache[key] = new GpuProgram(options);
          programCache[key]._cacheKey = key;
        }
        return programCache[key];
      }
    }

    "use strict";
    function addBits(srcParts, parts, name) {
      if (srcParts) {
        for (const i in srcParts) {
          const id = i.toLocaleLowerCase();
          const part = parts[id];
          if (part) {
            let sanitisedPart = srcParts[i];
            if (i === "header") {
              sanitisedPart = sanitisedPart.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "");
            }
            if (name) {
              part.push(`//----${name}----//`);
            }
            part.push(sanitisedPart);
          } else {
            warn(`${i} placement hook does not exist in shader`);
          }
        }
      }
    }

    "use strict";
    const findHooksRx = /\{\{(.*?)\}\}/g;
    function compileHooks(programSrc) {
      var _a, _b;
      const parts = {};
      const partMatches = (_b = (_a = programSrc.match(findHooksRx)) == null ? void 0 : _a.map((hook) => hook.replace(/[{()}]/g, ""))) != null ? _b : [];
      partMatches.forEach((hook) => {
        parts[hook] = [];
      });
      return parts;
    }

    "use strict";
    function extractInputs(fragmentSource, out) {
      let match;
      const regex = /@in\s+([^;]+);/g;
      while ((match = regex.exec(fragmentSource)) !== null) {
        out.push(match[1]);
      }
    }
    function compileInputs(fragments, template, sort = false) {
      const results = [];
      extractInputs(template, results);
      fragments.forEach((fragment) => {
        if (fragment.header) {
          extractInputs(fragment.header, results);
        }
      });
      const mainInput = results;
      if (sort) {
        mainInput.sort();
      }
      const finalString = mainInput.map((inValue, i) => `       @location(${i}) ${inValue},`).join("\n");
      let cleanedString = template.replace(/@in\s+[^;]+;\s*/g, "");
      cleanedString = cleanedString.replace("{{in}}", `
${finalString}
`);
      return cleanedString;
    }

    "use strict";
    function extractOutputs(fragmentSource, out) {
      let match;
      const regex = /@out\s+([^;]+);/g;
      while ((match = regex.exec(fragmentSource)) !== null) {
        out.push(match[1]);
      }
    }
    function extractVariableName(value) {
      const regex = /\b(\w+)\s*:/g;
      const match = regex.exec(value);
      return match ? match[1] : "";
    }
    function stripVariable(value) {
      const regex = /@.*?\s+/g;
      return value.replace(regex, "");
    }
    function compileOutputs(fragments, template) {
      const results = [];
      extractOutputs(template, results);
      fragments.forEach((fragment) => {
        if (fragment.header) {
          extractOutputs(fragment.header, results);
        }
      });
      let index = 0;
      const mainStruct = results.sort().map((inValue) => {
        if (inValue.indexOf("builtin") > -1) {
          return inValue;
        }
        return `@location(${index++}) ${inValue}`;
      }).join(",\n");
      const mainStart = results.sort().map((inValue) => `       var ${stripVariable(inValue)};`).join("\n");
      const mainEnd = `return VSOutput(
            ${results.sort().map((inValue) => ` ${extractVariableName(inValue)}`).join(",\n")});`;
      let compiledCode = template.replace(/@out\s+[^;]+;\s*/g, "");
      compiledCode = compiledCode.replace("{{struct}}", `
${mainStruct}
`);
      compiledCode = compiledCode.replace("{{start}}", `
${mainStart}
`);
      compiledCode = compiledCode.replace("{{return}}", `
${mainEnd}
`);
      return compiledCode;
    }

    "use strict";
    function injectBits(templateSrc, fragmentParts) {
      let out = templateSrc;
      for (const i in fragmentParts) {
        const parts = fragmentParts[i];
        const toInject = parts.join("\n");
        if (toInject.length) {
          out = out.replace(`{{${i}}}`, `//-----${i} START-----//
${parts.join("\n")}
//----${i} FINISH----//`);
        } else {
          out = out.replace(`{{${i}}}`, "");
        }
      }
      return out;
    }

    "use strict";
    const cacheMap = /* @__PURE__ */ Object.create(null);
    const bitCacheMap = /* @__PURE__ */ new Map();
    let CACHE_UID = 0;
    function compileHighShader({
      template,
      bits
    }) {
      const cacheId = generateCacheId(template, bits);
      if (cacheMap[cacheId])
        return cacheMap[cacheId];
      const { vertex, fragment } = compileInputsAndOutputs(template, bits);
      cacheMap[cacheId] = compileBits(vertex, fragment, bits);
      return cacheMap[cacheId];
    }
    function compileHighShaderGl({
      template,
      bits
    }) {
      const cacheId = generateCacheId(template, bits);
      if (cacheMap[cacheId])
        return cacheMap[cacheId];
      cacheMap[cacheId] = compileBits(template.vertex, template.fragment, bits);
      return cacheMap[cacheId];
    }
    function compileInputsAndOutputs(template, bits) {
      const vertexFragments = bits.map((shaderBit) => shaderBit.vertex).filter((v) => !!v);
      const fragmentFragments = bits.map((shaderBit) => shaderBit.fragment).filter((v) => !!v);
      let compiledVertex = compileInputs(vertexFragments, template.vertex, true);
      compiledVertex = compileOutputs(vertexFragments, compiledVertex);
      const compiledFragment = compileInputs(fragmentFragments, template.fragment, true);
      return {
        vertex: compiledVertex,
        fragment: compiledFragment
      };
    }
    function generateCacheId(template, bits) {
      return bits.map((highFragment) => {
        if (!bitCacheMap.has(highFragment)) {
          bitCacheMap.set(highFragment, CACHE_UID++);
        }
        return bitCacheMap.get(highFragment);
      }).sort((a, b) => a - b).join("-") + template.vertex + template.fragment;
    }
    function compileBits(vertex, fragment, bits) {
      const vertexParts = compileHooks(vertex);
      const fragmentParts = compileHooks(fragment);
      bits.forEach((shaderBit) => {
        addBits(shaderBit.vertex, vertexParts, shaderBit.name);
        addBits(shaderBit.fragment, fragmentParts, shaderBit.name);
      });
      return {
        vertex: injectBits(vertex, vertexParts),
        fragment: injectBits(fragment, fragmentParts)
      };
    }

    "use strict";
    const vertexGPUTemplate = (
      /* wgsl */
      `
    @in aPosition: vec2<f32>;
    @in aUV: vec2<f32>;

    @out @builtin(position) vPosition: vec4<f32>;
    @out vUV : vec2<f32>;
    @out vColor : vec4<f32>;

    {{header}}

    struct VSOutput {
        {{struct}}
    };

    @vertex
    fn main( {{in}} ) -> VSOutput {

        var worldTransformMatrix = globalUniforms.uWorldTransformMatrix;
        var modelMatrix = mat3x3<f32>(
            1.0, 0.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 0.0, 1.0
          );
        var position = aPosition;
        var uv = aUV;

        {{start}}

        vColor = vec4<f32>(1., 1., 1., 1.);

        {{main}}

        vUV = uv;

        var modelViewProjectionMatrix = globalUniforms.uProjectionMatrix * worldTransformMatrix * modelMatrix;

        vPosition =  vec4<f32>((modelViewProjectionMatrix *  vec3<f32>(position, 1.0)).xy, 0.0, 1.0);

        vColor *= globalUniforms.uWorldColorAlpha;

        {{end}}

        {{return}}
    };
`
    );
    const fragmentGPUTemplate = (
      /* wgsl */
      `
    @in vUV : vec2<f32>;
    @in vColor : vec4<f32>;

    {{header}}

    @fragment
    fn main(
        {{in}}
      ) -> @location(0) vec4<f32> {

        {{start}}

        var outColor:vec4<f32>;

        {{main}}

        var finalColor:vec4<f32> = outColor * vColor;

        {{end}}

        return finalColor;
      };
`
    );
    const vertexGlTemplate = (
      /* glsl */
      `
    in vec2 aPosition;
    in vec2 aUV;

    out vec4 vColor;
    out vec2 vUV;

    {{header}}

    void main(void){

        mat3 worldTransformMatrix = uWorldTransformMatrix;
        mat3 modelMatrix = mat3(
            1.0, 0.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 0.0, 1.0
          );
        vec2 position = aPosition;
        vec2 uv = aUV;

        {{start}}

        vColor = vec4(1.);

        {{main}}

        vUV = uv;

        mat3 modelViewProjectionMatrix = uProjectionMatrix * worldTransformMatrix * modelMatrix;

        gl_Position = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);

        vColor *= uWorldColorAlpha;

        {{end}}
    }
`
    );
    const fragmentGlTemplate = (
      /* glsl */
      `

    in vec4 vColor;
    in vec2 vUV;

    out vec4 finalColor;

    {{header}}

    void main(void) {

        {{start}}

        vec4 outColor;

        {{main}}

        finalColor = outColor * vColor;

        {{end}}
    }
`
    );

    "use strict";
    const globalUniformsBit = {
      name: "global-uniforms-bit",
      vertex: {
        header: (
          /* wgsl */
          `
        struct GlobalUniforms {
            uProjectionMatrix:mat3x3<f32>,
            uWorldTransformMatrix:mat3x3<f32>,
            uWorldColorAlpha: vec4<f32>,
            uResolution: vec2<f32>,
        }

        @group(0) @binding(0) var<uniform> globalUniforms : GlobalUniforms;
        `
        )
      }
    };
    const globalUniformsUBOBitGl = {
      name: "global-uniforms-ubo-bit",
      vertex: {
        header: (
          /* glsl */
          `
          uniform globalUniforms {
            mat3 uProjectionMatrix;
            mat3 uWorldTransformMatrix;
            vec4 uWorldColorAlpha;
            vec2 uResolution;
          };
        `
        )
      }
    };
    const globalUniformsBitGl = {
      name: "global-uniforms-bit",
      vertex: {
        header: (
          /* glsl */
          `
          uniform mat3 uProjectionMatrix;
          uniform mat3 uWorldTransformMatrix;
          uniform vec4 uWorldColorAlpha;
          uniform vec2 uResolution;
        `
        )
      }
    };

    "use strict";
    var __defProp$11 = Object.defineProperty;
    var __getOwnPropSymbols$13 = Object.getOwnPropertySymbols;
    var __hasOwnProp$13 = Object.prototype.hasOwnProperty;
    var __propIsEnum$13 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$11 = (obj, key, value) => key in obj ? __defProp$11(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$11 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$13.call(b, prop))
          __defNormalProp$11(a, prop, b[prop]);
      if (__getOwnPropSymbols$13)
        for (var prop of __getOwnPropSymbols$13(b)) {
          if (__propIsEnum$13.call(b, prop))
            __defNormalProp$11(a, prop, b[prop]);
        }
      return a;
    };
    function compileHighShaderGpuProgram({ bits, name }) {
      const source = compileHighShader({
        template: {
          fragment: fragmentGPUTemplate,
          vertex: vertexGPUTemplate
        },
        bits: [
          globalUniformsBit,
          ...bits
        ]
      });
      return GpuProgram.from({
        name,
        vertex: {
          source: source.vertex,
          entryPoint: "main"
        },
        fragment: {
          source: source.fragment,
          entryPoint: "main"
        }
      });
    }
    function compileHighShaderGlProgram({ bits, name }) {
      return new GlProgram(__spreadValues$11({
        name
      }, compileHighShaderGl({
        template: {
          vertex: vertexGlTemplate,
          fragment: fragmentGlTemplate
        },
        bits: [
          globalUniformsBitGl,
          ...bits
        ]
      })));
    }

    "use strict";
    const colorBit = {
      name: "color-bit",
      vertex: {
        header: (
          /* wgsl */
          `
            @in aColor: vec4<f32>;
        `
        ),
        main: (
          /* wgsl */
          `
            vColor *= vec4<f32>(aColor.rgb * aColor.a, aColor.a);
        `
        )
      }
    };
    const colorBitGl = {
      name: "color-bit",
      vertex: {
        header: (
          /* glsl */
          `
            in vec4 aColor;
        `
        ),
        main: (
          /* glsl */
          `
            vColor *= vec4(aColor.rgb * aColor.a, aColor.a);
        `
        )
      }
    };

    "use strict";
    const textureBatchBitGpuCache = {};
    function generateBindingSrc(maxTextures) {
      const src = [];
      if (maxTextures === 1) {
        src.push("@group(1) @binding(0) var textureSource1: texture_2d<f32>;");
        src.push("@group(1) @binding(1) var textureSampler1: sampler;");
      } else {
        let bindingIndex = 0;
        for (let i = 0; i < maxTextures; i++) {
          src.push(`@group(1) @binding(${bindingIndex++}) var textureSource${i + 1}: texture_2d<f32>;`);
          src.push(`@group(1) @binding(${bindingIndex++}) var textureSampler${i + 1}: sampler;`);
        }
      }
      return src.join("\n");
    }
    function generateSampleSrc(maxTextures) {
      const src = [];
      if (maxTextures === 1) {
        src.push("outColor = textureSampleGrad(textureSource1, textureSampler1, vUV, uvDx, uvDy);");
      } else {
        src.push("switch vTextureId {");
        for (let i = 0; i < maxTextures; i++) {
          if (i === maxTextures - 1) {
            src.push(`  default:{`);
          } else {
            src.push(`  case ${i}:{`);
          }
          src.push(`      outColor = textureSampleGrad(textureSource${i + 1}, textureSampler${i + 1}, vUV, uvDx, uvDy);`);
          src.push(`      break;}`);
        }
        src.push(`}`);
      }
      return src.join("\n");
    }
    function generateTextureBatchBit(maxTextures) {
      if (!textureBatchBitGpuCache[maxTextures]) {
        textureBatchBitGpuCache[maxTextures] = {
          name: "texture-batch-bit",
          vertex: {
            header: `
                @in aTextureIdAndRound: vec2<u32>;
                @out @interpolate(flat) vTextureId : u32;
            `,
            main: `
                vTextureId = aTextureIdAndRound.y;
            `,
            end: `
                if(aTextureIdAndRound.x == 1)
                {
                    vPosition = vec4<f32>(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
                }
            `
          },
          fragment: {
            header: `
                @in @interpolate(flat) vTextureId: u32;

                ${generateBindingSrc(maxTextures)}
            `,
            main: `
                var uvDx = dpdx(vUV);
                var uvDy = dpdy(vUV);

                ${generateSampleSrc(maxTextures)}
            `
          }
        };
      }
      return textureBatchBitGpuCache[maxTextures];
    }
    const textureBatchBitGlCache = {};
    function generateSampleGlSrc(maxTextures) {
      const src = [];
      for (let i = 0; i < maxTextures; i++) {
        if (i > 0) {
          src.push("else");
        }
        if (i < maxTextures - 1) {
          src.push(`if(vTextureId < ${i}.5)`);
        }
        src.push("{");
        src.push(`	outColor = texture(uTextures[${i}], vUV);`);
        src.push("}");
      }
      return src.join("\n");
    }
    function generateTextureBatchBitGl(maxTextures) {
      if (!textureBatchBitGlCache[maxTextures]) {
        textureBatchBitGlCache[maxTextures] = {
          name: "texture-batch-bit",
          vertex: {
            header: `
                in vec2 aTextureIdAndRound;
                out float vTextureId;

            `,
            main: `
                vTextureId = aTextureIdAndRound.y;
            `,
            end: `
                if(aTextureIdAndRound.x == 1.)
                {
                    gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
                }
            `
          },
          fragment: {
            header: `
                in float vTextureId;

                uniform sampler2D uTextures[${maxTextures}];

            `,
            main: `

                ${generateSampleGlSrc(maxTextures)}
            `
          }
        };
      }
      return textureBatchBitGlCache[maxTextures];
    }

    "use strict";
    const roundPixelsBit = {
      name: "round-pixels-bit",
      vertex: {
        header: (
          /* wgsl */
          `
            fn roundPixels(position: vec2<f32>, targetSize: vec2<f32>) -> vec2<f32>
            {
                return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
            }
        `
        )
      }
    };
    const roundPixelsBitGl = {
      name: "round-pixels-bit",
      vertex: {
        header: (
          /* glsl */
          `
            vec2 roundPixels(vec2 position, vec2 targetSize)
            {
                return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
            }
        `
        )
      }
    };

    "use strict";
    const UNIFORM_TYPES_VALUES = [
      "f32",
      "i32",
      "vec2<f32>",
      "vec3<f32>",
      "vec4<f32>",
      "mat2x2<f32>",
      "mat3x3<f32>",
      "mat4x4<f32>",
      "mat3x2<f32>",
      "mat4x2<f32>",
      "mat2x3<f32>",
      "mat4x3<f32>",
      "mat2x4<f32>",
      "mat3x4<f32>",
      "vec2<i32>",
      "vec3<i32>",
      "vec4<i32>"
    ];
    const UNIFORM_TYPES_MAP = UNIFORM_TYPES_VALUES.reduce((acc, type) => {
      acc[type] = true;
      return acc;
    }, {});

    "use strict";
    function getDefaultUniformValue(type, size) {
      switch (type) {
        case "f32":
          return 0;
        case "vec2<f32>":
          return new Float32Array(2 * size);
        case "vec3<f32>":
          return new Float32Array(3 * size);
        case "vec4<f32>":
          return new Float32Array(4 * size);
        case "mat2x2<f32>":
          return new Float32Array([
            1,
            0,
            0,
            1
          ]);
        case "mat3x3<f32>":
          return new Float32Array([
            1,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            1
          ]);
        case "mat4x4<f32>":
          return new Float32Array([
            1,
            0,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            0,
            1
          ]);
      }
      return null;
    }

    "use strict";
    var __defProp$10 = Object.defineProperty;
    var __getOwnPropSymbols$12 = Object.getOwnPropertySymbols;
    var __hasOwnProp$12 = Object.prototype.hasOwnProperty;
    var __propIsEnum$12 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$10 = (obj, key, value) => key in obj ? __defProp$10(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$10 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$12.call(b, prop))
          __defNormalProp$10(a, prop, b[prop]);
      if (__getOwnPropSymbols$12)
        for (var prop of __getOwnPropSymbols$12(b)) {
          if (__propIsEnum$12.call(b, prop))
            __defNormalProp$10(a, prop, b[prop]);
        }
      return a;
    };
    const _UniformGroup = class _UniformGroup {
      /**
       * Create a new Uniform group
       * @param uniformStructures - The structures of the uniform group
       * @param options - The optional parameters of this uniform group
       */
      constructor(uniformStructures, options) {
        /**
         * used internally to know if a uniform group was used in the last render pass
         * @internal
         */
        this._touched = 0;
        /** a unique id for this uniform group used through the renderer */
        this.uid = uid$1("uniform");
        /**
         * a resource type, used to identify how to handle it when its in a bind group / shader resource
         * @internal
         */
        this._resourceType = "uniformGroup";
        /**
         * the resource id used internally by the renderer to build bind group keys
         * @internal
         */
        this._resourceId = uid$1("resource");
        /** used ito identify if this is a uniform group */
        this.isUniformGroup = true;
        /**
         * used to flag if this Uniform groups data is different from what it has stored in its buffer / on the GPU
         * @internal
         */
        this._dirtyId = 0;
        // implementing the interface - UniformGroup are not destroyed
        this.destroyed = false;
        var _a, _b;
        options = __spreadValues$10(__spreadValues$10({}, _UniformGroup.defaultOptions), options);
        this.uniformStructures = uniformStructures;
        const uniforms = {};
        for (const i in uniformStructures) {
          const uniformData = uniformStructures[i];
          uniformData.name = i;
          uniformData.size = (_a = uniformData.size) != null ? _a : 1;
          if (!UNIFORM_TYPES_MAP[uniformData.type]) {
            const arrayMatch = uniformData.type.match(/^array<(\w+(?:<\w+>)?),\s*(\d+)>$/);
            if (arrayMatch) {
              const [, innerType, size] = arrayMatch;
              throw new Error(
                `Uniform type ${uniformData.type} is not supported. Use type: '${innerType}', size: ${size} instead.`
              );
            }
            throw new Error(`Uniform type ${uniformData.type} is not supported. Supported uniform types are: ${UNIFORM_TYPES_VALUES.join(", ")}`);
          }
          (_b = uniformData.value) != null ? _b : uniformData.value = getDefaultUniformValue(uniformData.type, uniformData.size);
          uniforms[i] = uniformData.value;
        }
        this.uniforms = uniforms;
        this._dirtyId = 1;
        this.ubo = options.ubo;
        this.isStatic = options.isStatic;
        this._signature = createIdFromString(Object.keys(uniforms).map(
          (i) => `${i}-${uniformStructures[i].type}`
        ).join("-"), "uniform-group");
      }
      /** Call this if you want the uniform groups data to be uploaded to the GPU only useful if `isStatic` is true. */
      update() {
        this._dirtyId++;
      }
    };
    /** The default options used by the uniform group. */
    _UniformGroup.defaultOptions = {
      /** if true the UniformGroup is handled as an Uniform buffer object. */
      ubo: false,
      /** if true, then you are responsible for when the data is uploaded to the GPU by calling `update()` */
      isStatic: false
    };
    let UniformGroup = _UniformGroup;

    "use strict";
    const batchSamplersUniformGroupHash = {};
    function getBatchSamplersUniformGroup(maxTextures) {
      let batchSamplersUniformGroup = batchSamplersUniformGroupHash[maxTextures];
      if (batchSamplersUniformGroup)
        return batchSamplersUniformGroup;
      const sampleValues = new Int32Array(maxTextures);
      for (let i = 0; i < maxTextures; i++) {
        sampleValues[i] = i;
      }
      batchSamplersUniformGroup = batchSamplersUniformGroupHash[maxTextures] = new UniformGroup({
        uTextures: { value: sampleValues, type: `i32`, size: maxTextures }
      }, { isStatic: true });
      return batchSamplersUniformGroup;
    }

    "use strict";
    var RendererType = /* @__PURE__ */ ((RendererType2) => {
      RendererType2[RendererType2["WEBGL"] = 1] = "WEBGL";
      RendererType2[RendererType2["WEBGPU"] = 2] = "WEBGPU";
      RendererType2[RendererType2["BOTH"] = 3] = "BOTH";
      return RendererType2;
    })(RendererType || {});

    "use strict";
    var __defProp$$ = Object.defineProperty;
    var __getOwnPropSymbols$11 = Object.getOwnPropertySymbols;
    var __hasOwnProp$11 = Object.prototype.hasOwnProperty;
    var __propIsEnum$11 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$$ = (obj, key, value) => key in obj ? __defProp$$(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$$ = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$11.call(b, prop))
          __defNormalProp$$(a, prop, b[prop]);
      if (__getOwnPropSymbols$11)
        for (var prop of __getOwnPropSymbols$11(b)) {
          if (__propIsEnum$11.call(b, prop))
            __defNormalProp$$(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$m = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$11.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$11)
        for (var prop of __getOwnPropSymbols$11(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$11.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class Shader extends EventEmitter {
      constructor(options) {
        super();
        /** A unique identifier for the shader */
        this.uid = uid$1("shader");
        /**
         * A record of the uniform groups and resources used by the shader.
         * This is used by WebGL renderer to sync uniform data.
         * @internal
         */
        this._uniformBindMap = /* @__PURE__ */ Object.create(null);
        this._ownedBindGroups = [];
        /** @internal */
        this._destroyed = false;
        let {
          gpuProgram,
          glProgram,
          groups,
          resources,
          compatibleRenderers,
          groupMap
        } = options;
        this.gpuProgram = gpuProgram;
        this.glProgram = glProgram;
        if (compatibleRenderers === void 0) {
          compatibleRenderers = 0;
          if (gpuProgram)
            compatibleRenderers |= RendererType.WEBGPU;
          if (glProgram)
            compatibleRenderers |= RendererType.WEBGL;
        }
        this.compatibleRenderers = compatibleRenderers;
        const nameHash = {};
        if (!resources && !groups) {
          resources = {};
        }
        if (resources && groups) {
          throw new Error("[Shader] Cannot have both resources and groups");
        } else if (!gpuProgram && groups && !groupMap) {
          throw new Error("[Shader] No group map or WebGPU shader provided - consider using resources instead.");
        } else if (!gpuProgram && groups && groupMap) {
          for (const i in groupMap) {
            for (const j in groupMap[i]) {
              const uniformName = groupMap[i][j];
              nameHash[uniformName] = {
                group: i,
                binding: j,
                name: uniformName
              };
            }
          }
        } else if (gpuProgram && groups && !groupMap) {
          const groupData = gpuProgram.structsAndGroups.groups;
          groupMap = {};
          groupData.forEach((data) => {
            groupMap[data.group] = groupMap[data.group] || {};
            groupMap[data.group][data.binding] = data.name;
            nameHash[data.name] = data;
          });
        } else if (resources) {
          groups = {};
          groupMap = {};
          if (gpuProgram) {
            const groupData = gpuProgram.structsAndGroups.groups;
            groupData.forEach((data) => {
              groupMap[data.group] = groupMap[data.group] || {};
              groupMap[data.group][data.binding] = data.name;
              nameHash[data.name] = data;
            });
          }
          let bindTick = 0;
          for (const i in resources) {
            if (nameHash[i])
              continue;
            if (!groups[99]) {
              groups[99] = new BindGroup();
              this._ownedBindGroups.push(groups[99]);
            }
            nameHash[i] = { group: 99, binding: bindTick, name: i };
            groupMap[99] = groupMap[99] || {};
            groupMap[99][bindTick] = i;
            bindTick++;
          }
          for (const i in resources) {
            const name = i;
            let value = resources[i];
            if (!value.source && !value._resourceType) {
              value = new UniformGroup(value);
            }
            const data = nameHash[name];
            if (data) {
              if (!groups[data.group]) {
                groups[data.group] = new BindGroup();
                this._ownedBindGroups.push(groups[data.group]);
              }
              groups[data.group].setResource(value, data.binding);
            }
          }
        }
        this.groups = groups;
        this._uniformBindMap = groupMap;
        this.resources = this._buildResourceAccessor(groups, nameHash);
      }
      /**
       * Sometimes a resource group will be provided later (for example global uniforms)
       * In such cases, this method can be used to let the shader know about the group.
       * @param name - the name of the resource group
       * @param groupIndex - the index of the group (should match the webGPU shader group location)
       * @param bindIndex - the index of the bind point (should match the webGPU shader bind point)
       */
      addResource(name, groupIndex, bindIndex) {
        var _a, _b;
        (_a = this._uniformBindMap)[groupIndex] || (_a[groupIndex] = {});
        (_b = this._uniformBindMap[groupIndex])[bindIndex] || (_b[bindIndex] = name);
        if (!this.groups[groupIndex]) {
          this.groups[groupIndex] = new BindGroup();
          this._ownedBindGroups.push(this.groups[groupIndex]);
        }
      }
      _buildResourceAccessor(groups, nameHash) {
        const uniformsOut = {};
        for (const i in nameHash) {
          const data = nameHash[i];
          Object.defineProperty(uniformsOut, data.name, {
            get() {
              return groups[data.group].getResource(data.binding);
            },
            set(value) {
              groups[data.group].setResource(value, data.binding);
            }
          });
        }
        return uniformsOut;
      }
      /**
       * Use to destroy the shader when its not longer needed.
       * It will destroy the resources and remove listeners.
       * @param destroyPrograms - if the programs should be destroyed as well.
       * Make sure its not being used by other shaders!
       */
      destroy(destroyPrograms = false) {
        var _a, _b;
        if (this._destroyed)
          return;
        this._destroyed = true;
        this.emit("destroy", this);
        if (destroyPrograms) {
          (_a = this.gpuProgram) == null ? void 0 : _a.destroy();
          (_b = this.glProgram) == null ? void 0 : _b.destroy();
        }
        this.gpuProgram = null;
        this.glProgram = null;
        this.removeAllListeners();
        this._uniformBindMap = null;
        this._ownedBindGroups.forEach((bindGroup) => {
          bindGroup.destroy();
        });
        this._ownedBindGroups = null;
        this.resources = null;
        this.groups = null;
      }
      static from(options) {
        const _a = options, { gpu, gl } = _a, rest = __objRest$m(_a, ["gpu", "gl"]);
        let gpuProgram;
        let glProgram;
        if (gpu) {
          gpuProgram = GpuProgram.from(gpu);
        }
        if (gl) {
          glProgram = GlProgram.from(gl);
        }
        return new Shader(__spreadValues$$({
          gpuProgram,
          glProgram
        }, rest));
      }
    }

    "use strict";
    class DefaultShader extends Shader {
      constructor(maxTextures) {
        const glProgram = compileHighShaderGlProgram({
          name: "batch",
          bits: [
            colorBitGl,
            generateTextureBatchBitGl(maxTextures),
            roundPixelsBitGl
          ]
        });
        const gpuProgram = compileHighShaderGpuProgram({
          name: "batch",
          bits: [
            colorBit,
            generateTextureBatchBit(maxTextures),
            roundPixelsBit
          ]
        });
        super({
          glProgram,
          gpuProgram,
          resources: {
            batchSamplers: getBatchSamplersUniformGroup(maxTextures)
          }
        });
        this.maxTextures = maxTextures;
      }
    }

    "use strict";
    let defaultShader = null;
    const _DefaultBatcher = class _DefaultBatcher extends Batcher {
      constructor(options) {
        super(options);
        this.geometry = new BatchGeometry();
        this.name = _DefaultBatcher.extension.name;
        /** The size of one attribute. 1 = 32 bit. x, y, u, v, color, textureIdAndRound -> total = 6 */
        this.vertexSize = 6;
        defaultShader != null ? defaultShader : defaultShader = new DefaultShader(options.maxTextures);
        this.shader = defaultShader;
      }
      /**
       * Packs the attributes of a DefaultBatchableMeshElement into the provided views.
       * @param element - The DefaultBatchableMeshElement to pack.
       * @param float32View - The Float32Array view to pack into.
       * @param uint32View - The Uint32Array view to pack into.
       * @param index - The starting index in the views.
       * @param textureId - The texture ID to use.
       */
      packAttributes(element, float32View, uint32View, index, textureId) {
        const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
        const wt = element.transform;
        const a = wt.a;
        const b = wt.b;
        const c = wt.c;
        const d = wt.d;
        const tx = wt.tx;
        const ty = wt.ty;
        const { positions, uvs } = element;
        const argb = element.color;
        const offset = element.attributeOffset;
        const end = offset + element.attributeSize;
        for (let i = offset; i < end; i++) {
          const i2 = i * 2;
          const x = positions[i2];
          const y = positions[i2 + 1];
          float32View[index++] = a * x + c * y + tx;
          float32View[index++] = d * y + b * x + ty;
          float32View[index++] = uvs[i2];
          float32View[index++] = uvs[i2 + 1];
          uint32View[index++] = argb;
          uint32View[index++] = textureIdAndRound;
        }
      }
      /**
       * Packs the attributes of a DefaultBatchableQuadElement into the provided views.
       * @param element - The DefaultBatchableQuadElement to pack.
       * @param float32View - The Float32Array view to pack into.
       * @param uint32View - The Uint32Array view to pack into.
       * @param index - The starting index in the views.
       * @param textureId - The texture ID to use.
       */
      packQuadAttributes(element, float32View, uint32View, index, textureId) {
        const texture = element.texture;
        const wt = element.transform;
        const a = wt.a;
        const b = wt.b;
        const c = wt.c;
        const d = wt.d;
        const tx = wt.tx;
        const ty = wt.ty;
        const bounds = element.bounds;
        const w0 = bounds.maxX;
        const w1 = bounds.minX;
        const h0 = bounds.maxY;
        const h1 = bounds.minY;
        const uvs = texture.uvs;
        const argb = element.color;
        const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
        float32View[index + 0] = a * w1 + c * h1 + tx;
        float32View[index + 1] = d * h1 + b * w1 + ty;
        float32View[index + 2] = uvs.x0;
        float32View[index + 3] = uvs.y0;
        uint32View[index + 4] = argb;
        uint32View[index + 5] = textureIdAndRound;
        float32View[index + 6] = a * w0 + c * h1 + tx;
        float32View[index + 7] = d * h1 + b * w0 + ty;
        float32View[index + 8] = uvs.x1;
        float32View[index + 9] = uvs.y1;
        uint32View[index + 10] = argb;
        uint32View[index + 11] = textureIdAndRound;
        float32View[index + 12] = a * w0 + c * h0 + tx;
        float32View[index + 13] = d * h0 + b * w0 + ty;
        float32View[index + 14] = uvs.x2;
        float32View[index + 15] = uvs.y2;
        uint32View[index + 16] = argb;
        uint32View[index + 17] = textureIdAndRound;
        float32View[index + 18] = a * w1 + c * h0 + tx;
        float32View[index + 19] = d * h0 + b * w1 + ty;
        float32View[index + 20] = uvs.x3;
        float32View[index + 21] = uvs.y3;
        uint32View[index + 22] = argb;
        uint32View[index + 23] = textureIdAndRound;
      }
      /**
       * Updates the maximum number of textures that can be used in the shader.
       * @param maxTextures - The maximum number of textures that can be used in the shader.
       * @internal
       */
      _updateMaxTextures(maxTextures) {
        if (this.shader.maxTextures === maxTextures)
          return;
        defaultShader = new DefaultShader(maxTextures);
        this.shader = defaultShader;
      }
      destroy() {
        this.shader = null;
        super.destroy();
      }
    };
    /** @ignore */
    _DefaultBatcher.extension = {
      type: [
        ExtensionType.Batcher
      ],
      name: "default"
    };
    let DefaultBatcher = _DefaultBatcher;

    "use strict";
    class GCManagedHash {
      constructor(options) {
        // Exposed directly for GC system access
        this.items = /* @__PURE__ */ Object.create(null);
        const { renderer, type, onUnload, priority, name } = options;
        this._renderer = renderer;
        renderer.gc.addResourceHash(this, "items", type, priority != null ? priority : 0);
        this._onUnload = onUnload;
        this.name = name;
      }
      /**
       * Add an item to the hash. No-op if already added.
       * @param item
       * @returns true if the item was added, false if it was already in the hash
       */
      add(item) {
        if (this.items[item.uid])
          return false;
        this.items[item.uid] = item;
        item.once("unload", this.remove, this);
        item._gcLastUsed = this._renderer.gc.now;
        return true;
      }
      remove(item, ...args) {
        var _a;
        if (!this.items[item.uid])
          return;
        const gpuData = item._gpuData[this._renderer.uid];
        if (!gpuData)
          return;
        (_a = this._onUnload) == null ? void 0 : _a.call(this, item, ...args);
        gpuData.destroy();
        item._gpuData[this._renderer.uid] = null;
        this.items[item.uid] = null;
      }
      removeAll(...args) {
        Object.values(this.items).forEach((item) => item && this.remove(item, ...args));
      }
      destroy(...args) {
        this.removeAll(...args);
        this.items = /* @__PURE__ */ Object.create(null);
        this._renderer = null;
        this._onUnload = null;
      }
    }

    "use strict";
    function buildUvs(vertices, verticesStride, verticesOffset, uvs, uvsOffset, uvsStride, size, matrix = null) {
      let index = 0;
      verticesOffset *= verticesStride;
      uvsOffset *= uvsStride;
      const a = matrix.a;
      const b = matrix.b;
      const c = matrix.c;
      const d = matrix.d;
      const tx = matrix.tx;
      const ty = matrix.ty;
      while (index < size) {
        const x = vertices[verticesOffset];
        const y = vertices[verticesOffset + 1];
        uvs[uvsOffset] = a * x + c * y + tx;
        uvs[uvsOffset + 1] = b * x + d * y + ty;
        uvsOffset += uvsStride;
        verticesOffset += verticesStride;
        index++;
      }
    }
    function buildSimpleUvs(uvs, uvsOffset, uvsStride, size) {
      let index = 0;
      uvsOffset *= uvsStride;
      while (index < size) {
        uvs[uvsOffset] = 0;
        uvs[uvsOffset + 1] = 0;
        uvsOffset += uvsStride;
        index++;
      }
    }

    "use strict";
    function transformVertices(vertices, m, offset, stride, size) {
      const a = m.a;
      const b = m.b;
      const c = m.c;
      const d = m.d;
      const tx = m.tx;
      const ty = m.ty;
      offset || (offset = 0);
      stride || (stride = 2);
      size || (size = vertices.length / stride - offset);
      let index = offset * stride;
      for (let i = 0; i < size; i++) {
        const x = vertices[index];
        const y = vertices[index + 1];
        vertices[index] = a * x + c * y + tx;
        vertices[index + 1] = b * x + d * y + ty;
        index += stride;
      }
    }

    "use strict";
    const identityMatrix = new Matrix();
    class BatchableGraphics {
      constructor() {
        this.packAsQuad = false;
        this.batcherName = "default";
        this.topology = "triangle-list";
        this.applyTransform = true;
        this.roundPixels = 0;
        this._batcher = null;
        this._batch = null;
      }
      get uvs() {
        return this.geometryData.uvs;
      }
      get positions() {
        return this.geometryData.vertices;
      }
      get indices() {
        return this.geometryData.indices;
      }
      get blendMode() {
        if (this.renderable && this.applyTransform) {
          return this.renderable.groupBlendMode;
        }
        return "normal";
      }
      get color() {
        const rgb = this.baseColor;
        const bgr = rgb >> 16 | rgb & 65280 | (rgb & 255) << 16;
        const renderable = this.renderable;
        if (renderable) {
          return multiplyHexColors(bgr, renderable.groupColor) + (this.alpha * renderable.groupAlpha * 255 << 24);
        }
        return bgr + (this.alpha * 255 << 24);
      }
      get transform() {
        var _a;
        return ((_a = this.renderable) == null ? void 0 : _a.groupTransform) || identityMatrix;
      }
      copyTo(gpuBuffer) {
        gpuBuffer.indexOffset = this.indexOffset;
        gpuBuffer.indexSize = this.indexSize;
        gpuBuffer.attributeOffset = this.attributeOffset;
        gpuBuffer.attributeSize = this.attributeSize;
        gpuBuffer.baseColor = this.baseColor;
        gpuBuffer.alpha = this.alpha;
        gpuBuffer.texture = this.texture;
        gpuBuffer.geometryData = this.geometryData;
        gpuBuffer.topology = this.topology;
      }
      reset() {
        this.applyTransform = true;
        this.renderable = null;
        this.topology = "triangle-list";
      }
      destroy() {
        this.renderable = null;
        this.texture = null;
        this.geometryData = null;
        this._batcher = null;
        this._batch = null;
      }
    }

    "use strict";
    var __defProp$_ = Object.defineProperty;
    var __defProps$p = Object.defineProperties;
    var __getOwnPropDescs$p = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$10 = Object.getOwnPropertySymbols;
    var __hasOwnProp$10 = Object.prototype.hasOwnProperty;
    var __propIsEnum$10 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$_ = (obj, key, value) => key in obj ? __defProp$_(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$_ = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$10.call(b, prop))
          __defNormalProp$_(a, prop, b[prop]);
      if (__getOwnPropSymbols$10)
        for (var prop of __getOwnPropSymbols$10(b)) {
          if (__propIsEnum$10.call(b, prop))
            __defNormalProp$_(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$p = (a, b) => __defProps$p(a, __getOwnPropDescs$p(b));
    const buildCircle = {
      extension: {
        type: ExtensionType.ShapeBuilder,
        name: "circle"
      },
      build(shape, points) {
        let x;
        let y;
        let dx;
        let dy;
        let rx;
        let ry;
        if (shape.type === "circle") {
          const circle = shape;
          rx = ry = circle.radius;
          if (rx <= 0) {
            return false;
          }
          x = circle.x;
          y = circle.y;
          dx = dy = 0;
        } else if (shape.type === "ellipse") {
          const ellipse = shape;
          rx = ellipse.halfWidth;
          ry = ellipse.halfHeight;
          if (rx <= 0 || ry <= 0) {
            return false;
          }
          x = ellipse.x;
          y = ellipse.y;
          dx = dy = 0;
        } else {
          const roundedRect = shape;
          const halfWidth = roundedRect.width / 2;
          const halfHeight = roundedRect.height / 2;
          x = roundedRect.x + halfWidth;
          y = roundedRect.y + halfHeight;
          rx = ry = Math.max(0, Math.min(roundedRect.radius, Math.min(halfWidth, halfHeight)));
          dx = halfWidth - rx;
          dy = halfHeight - ry;
        }
        if (dx < 0 || dy < 0) {
          return false;
        }
        const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
        const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
        if (m === 0) {
          return false;
        }
        if (n === 0) {
          points[0] = points[6] = x + dx;
          points[1] = points[3] = y + dy;
          points[2] = points[4] = x - dx;
          points[5] = points[7] = y - dy;
          return true;
        }
        let j1 = 0;
        let j2 = n * 4 + (dx ? 2 : 0) + 2;
        let j3 = j2;
        let j4 = m;
        let x0 = dx + rx;
        let y0 = dy;
        let x1 = x + x0;
        let x2 = x - x0;
        let y1 = y + y0;
        points[j1++] = x1;
        points[j1++] = y1;
        points[--j2] = y1;
        points[--j2] = x2;
        if (dy) {
          const y22 = y - y0;
          points[j3++] = x2;
          points[j3++] = y22;
          points[--j4] = y22;
          points[--j4] = x1;
        }
        for (let i = 1; i < n; i++) {
          const a = Math.PI / 2 * (i / n);
          const x02 = dx + Math.cos(a) * rx;
          const y02 = dy + Math.sin(a) * ry;
          const x12 = x + x02;
          const x22 = x - x02;
          const y12 = y + y02;
          const y22 = y - y02;
          points[j1++] = x12;
          points[j1++] = y12;
          points[--j2] = y12;
          points[--j2] = x22;
          points[j3++] = x22;
          points[j3++] = y22;
          points[--j4] = y22;
          points[--j4] = x12;
        }
        x0 = dx;
        y0 = dy + ry;
        x1 = x + x0;
        x2 = x - x0;
        y1 = y + y0;
        const y2 = y - y0;
        points[j1++] = x1;
        points[j1++] = y1;
        points[--j4] = y2;
        points[--j4] = x1;
        if (dx) {
          points[j1++] = x2;
          points[j1++] = y1;
          points[--j4] = y2;
          points[--j4] = x2;
        }
        return true;
      },
      triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
        if (points.length === 0) {
          return;
        }
        let centerX = 0;
        let centerY = 0;
        for (let i = 0; i < points.length; i += 2) {
          centerX += points[i];
          centerY += points[i + 1];
        }
        centerX /= points.length / 2;
        centerY /= points.length / 2;
        let count = verticesOffset;
        vertices[count * verticesStride] = centerX;
        vertices[count * verticesStride + 1] = centerY;
        const centerIndex = count++;
        for (let i = 0; i < points.length; i += 2) {
          vertices[count * verticesStride] = points[i];
          vertices[count * verticesStride + 1] = points[i + 1];
          if (i > 0) {
            indices[indicesOffset++] = count;
            indices[indicesOffset++] = centerIndex;
            indices[indicesOffset++] = count - 1;
          }
          count++;
        }
        indices[indicesOffset++] = centerIndex + 1;
        indices[indicesOffset++] = centerIndex;
        indices[indicesOffset++] = count - 1;
      }
    };
    const buildEllipse = __spreadProps$p(__spreadValues$_({}, buildCircle), { extension: __spreadProps$p(__spreadValues$_({}, buildCircle.extension), { name: "ellipse" }) });
    const buildRoundedRectangle = __spreadProps$p(__spreadValues$_({}, buildCircle), { extension: __spreadProps$p(__spreadValues$_({}, buildCircle.extension), { name: "roundedRectangle" }) });

    "use strict";
    const closePointEps = 1e-4;
    const curveEps = 1e-4;

    "use strict";
    function getOrientationOfPoints(points) {
      const m = points.length;
      if (m < 6) {
        return 1;
      }
      let area = 0;
      for (let i = 0, x1 = points[m - 2], y1 = points[m - 1]; i < m; i += 2) {
        const x2 = points[i];
        const y2 = points[i + 1];
        area += (x2 - x1) * (y2 + y1);
        x1 = x2;
        y1 = y2;
      }
      if (area < 0) {
        return -1;
      }
      return 1;
    }

    "use strict";
    function square(x, y, nx, ny, innerWeight, outerWeight, clockwise, verts) {
      const ix = x - nx * innerWeight;
      const iy = y - ny * innerWeight;
      const ox = x + nx * outerWeight;
      const oy = y + ny * outerWeight;
      let exx;
      let eyy;
      if (clockwise) {
        exx = ny;
        eyy = -nx;
      } else {
        exx = -ny;
        eyy = nx;
      }
      const eix = ix + exx;
      const eiy = iy + eyy;
      const eox = ox + exx;
      const eoy = oy + eyy;
      verts.push(eix, eiy);
      verts.push(eox, eoy);
      return 2;
    }
    function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
      const cx2p0x = sx - cx;
      const cy2p0y = sy - cy;
      let angle0 = Math.atan2(cx2p0x, cy2p0y);
      let angle1 = Math.atan2(ex - cx, ey - cy);
      if (clockwise && angle0 < angle1) {
        angle0 += Math.PI * 2;
      } else if (!clockwise && angle0 > angle1) {
        angle1 += Math.PI * 2;
      }
      let startAngle = angle0;
      const angleDiff = angle1 - angle0;
      const absAngleDiff = Math.abs(angleDiff);
      const radius = Math.sqrt(cx2p0x * cx2p0x + cy2p0y * cy2p0y);
      const segCount = (15 * absAngleDiff * Math.sqrt(radius) / Math.PI >> 0) + 1;
      const angleInc = angleDiff / segCount;
      startAngle += angleInc;
      if (clockwise) {
        verts.push(cx, cy);
        verts.push(sx, sy);
        for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
          verts.push(cx, cy);
          verts.push(
            cx + Math.sin(angle) * radius,
            cy + Math.cos(angle) * radius
          );
        }
        verts.push(cx, cy);
        verts.push(ex, ey);
      } else {
        verts.push(sx, sy);
        verts.push(cx, cy);
        for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
          verts.push(
            cx + Math.sin(angle) * radius,
            cy + Math.cos(angle) * radius
          );
          verts.push(cx, cy);
        }
        verts.push(ex, ey);
        verts.push(cx, cy);
      }
      return segCount * 2;
    }
    function buildLine(points, lineStyle, flipAlignment, closed, vertices, indices) {
      const eps = closePointEps;
      if (points.length === 0) {
        return;
      }
      const style = lineStyle;
      let alignment = style.alignment;
      if (lineStyle.alignment !== 0.5) {
        let orientation = getOrientationOfPoints(points);
        if (flipAlignment)
          orientation *= -1;
        alignment = (alignment - 0.5) * orientation + 0.5;
      }
      const firstPoint = new Point(points[0], points[1]);
      const lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
      const closedShape = closed;
      const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
      if (closedShape) {
        points = points.slice();
        if (closedPath) {
          points.pop();
          points.pop();
          lastPoint.set(points[points.length - 2], points[points.length - 1]);
        }
        const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
        const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
        points.unshift(midPointX, midPointY);
        points.push(midPointX, midPointY);
      }
      const verts = vertices;
      const length = points.length / 2;
      let indexCount = points.length;
      const indexStart = verts.length / 2;
      const width = style.width / 2;
      const widthSquared = width * width;
      const miterLimitSquared = style.miterLimit * style.miterLimit;
      let x0 = points[0];
      let y0 = points[1];
      let x1 = points[2];
      let y1 = points[3];
      let x2 = 0;
      let y2 = 0;
      let perpX = -(y0 - y1);
      let perpY = x0 - x1;
      let perp1x = 0;
      let perp1y = 0;
      let dist = Math.sqrt(perpX * perpX + perpY * perpY);
      perpX /= dist;
      perpY /= dist;
      perpX *= width;
      perpY *= width;
      const ratio = alignment;
      const innerWeight = (1 - ratio) * 2;
      const outerWeight = ratio * 2;
      if (!closedShape) {
        if (style.cap === "round") {
          indexCount += round(
            x0 - perpX * (innerWeight - outerWeight) * 0.5,
            y0 - perpY * (innerWeight - outerWeight) * 0.5,
            x0 - perpX * innerWeight,
            y0 - perpY * innerWeight,
            x0 + perpX * outerWeight,
            y0 + perpY * outerWeight,
            verts,
            true
          ) + 2;
        } else if (style.cap === "square") {
          indexCount += square(x0, y0, perpX, perpY, innerWeight, outerWeight, true, verts);
        }
      }
      verts.push(
        x0 - perpX * innerWeight,
        y0 - perpY * innerWeight
      );
      verts.push(
        x0 + perpX * outerWeight,
        y0 + perpY * outerWeight
      );
      for (let i = 1; i < length - 1; ++i) {
        x0 = points[(i - 1) * 2];
        y0 = points[(i - 1) * 2 + 1];
        x1 = points[i * 2];
        y1 = points[i * 2 + 1];
        x2 = points[(i + 1) * 2];
        y2 = points[(i + 1) * 2 + 1];
        perpX = -(y0 - y1);
        perpY = x0 - x1;
        dist = Math.sqrt(perpX * perpX + perpY * perpY);
        perpX /= dist;
        perpY /= dist;
        perpX *= width;
        perpY *= width;
        perp1x = -(y1 - y2);
        perp1y = x1 - x2;
        dist = Math.sqrt(perp1x * perp1x + perp1y * perp1y);
        perp1x /= dist;
        perp1y /= dist;
        perp1x *= width;
        perp1y *= width;
        const dx0 = x1 - x0;
        const dy0 = y0 - y1;
        const dx1 = x1 - x2;
        const dy1 = y2 - y1;
        const dot = dx0 * dx1 + dy0 * dy1;
        const cross = dy0 * dx1 - dy1 * dx0;
        const clockwise = cross < 0;
        if (Math.abs(cross) < 1e-3 * Math.abs(dot)) {
          verts.push(
            x1 - perpX * innerWeight,
            y1 - perpY * innerWeight
          );
          verts.push(
            x1 + perpX * outerWeight,
            y1 + perpY * outerWeight
          );
          if (dot >= 0) {
            if (style.join === "round") {
              indexCount += round(
                x1,
                y1,
                x1 - perpX * innerWeight,
                y1 - perpY * innerWeight,
                x1 - perp1x * innerWeight,
                y1 - perp1y * innerWeight,
                verts,
                false
              ) + 4;
            } else {
              indexCount += 2;
            }
            verts.push(
              x1 - perp1x * outerWeight,
              y1 - perp1y * outerWeight
            );
            verts.push(
              x1 + perp1x * innerWeight,
              y1 + perp1y * innerWeight
            );
          }
          continue;
        }
        const c1 = (-perpX + x0) * (-perpY + y1) - (-perpX + x1) * (-perpY + y0);
        const c2 = (-perp1x + x2) * (-perp1y + y1) - (-perp1x + x1) * (-perp1y + y2);
        const px = (dx0 * c2 - dx1 * c1) / cross;
        const py = (dy1 * c1 - dy0 * c2) / cross;
        const pDist = (px - x1) * (px - x1) + (py - y1) * (py - y1);
        const imx = x1 + (px - x1) * innerWeight;
        const imy = y1 + (py - y1) * innerWeight;
        const omx = x1 - (px - x1) * outerWeight;
        const omy = y1 - (py - y1) * outerWeight;
        const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
        const insideWeight = clockwise ? innerWeight : outerWeight;
        const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
        const insideMiterOk = pDist <= smallerInsideDiagonalSq;
        if (insideMiterOk) {
          if (style.join === "bevel" || pDist / widthSquared > miterLimitSquared) {
            if (clockwise) {
              verts.push(imx, imy);
              verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
              verts.push(imx, imy);
              verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
            } else {
              verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
              verts.push(omx, omy);
              verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
              verts.push(omx, omy);
            }
            indexCount += 2;
          } else if (style.join === "round") {
            if (clockwise) {
              verts.push(imx, imy);
              verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
              indexCount += round(
                x1,
                y1,
                x1 + perpX * outerWeight,
                y1 + perpY * outerWeight,
                x1 + perp1x * outerWeight,
                y1 + perp1y * outerWeight,
                verts,
                true
              ) + 4;
              verts.push(imx, imy);
              verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
            } else {
              verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
              verts.push(omx, omy);
              indexCount += round(
                x1,
                y1,
                x1 - perpX * innerWeight,
                y1 - perpY * innerWeight,
                x1 - perp1x * innerWeight,
                y1 - perp1y * innerWeight,
                verts,
                false
              ) + 4;
              verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
              verts.push(omx, omy);
            }
          } else {
            verts.push(imx, imy);
            verts.push(omx, omy);
          }
        } else {
          verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
          verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
          if (style.join === "round") {
            if (clockwise) {
              indexCount += round(
                x1,
                y1,
                x1 + perpX * outerWeight,
                y1 + perpY * outerWeight,
                x1 + perp1x * outerWeight,
                y1 + perp1y * outerWeight,
                verts,
                true
              ) + 2;
            } else {
              indexCount += round(
                x1,
                y1,
                x1 - perpX * innerWeight,
                y1 - perpY * innerWeight,
                x1 - perp1x * innerWeight,
                y1 - perp1y * innerWeight,
                verts,
                false
              ) + 2;
            }
          } else if (style.join === "miter" && pDist / widthSquared <= miterLimitSquared) {
            if (clockwise) {
              verts.push(omx, omy);
              verts.push(omx, omy);
            } else {
              verts.push(imx, imy);
              verts.push(imx, imy);
            }
            indexCount += 2;
          }
          verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
          verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
          indexCount += 2;
        }
      }
      x0 = points[(length - 2) * 2];
      y0 = points[(length - 2) * 2 + 1];
      x1 = points[(length - 1) * 2];
      y1 = points[(length - 1) * 2 + 1];
      perpX = -(y0 - y1);
      perpY = x0 - x1;
      dist = Math.sqrt(perpX * perpX + perpY * perpY);
      perpX /= dist;
      perpY /= dist;
      perpX *= width;
      perpY *= width;
      verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
      verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
      if (!closedShape) {
        if (style.cap === "round") {
          indexCount += round(
            x1 - perpX * (innerWeight - outerWeight) * 0.5,
            y1 - perpY * (innerWeight - outerWeight) * 0.5,
            x1 - perpX * innerWeight,
            y1 - perpY * innerWeight,
            x1 + perpX * outerWeight,
            y1 + perpY * outerWeight,
            verts,
            false
          ) + 2;
        } else if (style.cap === "square") {
          indexCount += square(x1, y1, perpX, perpY, innerWeight, outerWeight, false, verts);
        }
      }
      const eps2 = curveEps * curveEps;
      for (let i = indexStart; i < indexCount + indexStart - 2; ++i) {
        x0 = verts[i * 2];
        y0 = verts[i * 2 + 1];
        x1 = verts[(i + 1) * 2];
        y1 = verts[(i + 1) * 2 + 1];
        x2 = verts[(i + 2) * 2];
        y2 = verts[(i + 2) * 2 + 1];
        if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
          continue;
        }
        indices.push(i, i + 1, i + 2);
      }
    }

    "use strict";
    function buildPixelLine(points, closed, vertices, indices) {
      const eps = closePointEps;
      if (points.length === 0) {
        return;
      }
      const fx = points[0];
      const fy = points[1];
      const lx = points[points.length - 2];
      const ly = points[points.length - 1];
      const closePath = closed || Math.abs(fx - lx) < eps && Math.abs(fy - ly) < eps;
      const verts = vertices;
      const length = points.length / 2;
      const indexStart = verts.length / 2;
      for (let i = 0; i < length; i++) {
        verts.push(points[i * 2]);
        verts.push(points[i * 2 + 1]);
      }
      for (let i = 0; i < length - 1; i++) {
        indices.push(indexStart + i, indexStart + i + 1);
      }
      if (closePath) {
        indices.push(indexStart + length - 1, indexStart);
      }
    }

    function earcut$1(data, holeIndices, dim = 2) {

        const hasHoles = holeIndices && holeIndices.length;
        const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
        let outerNode = linkedList(data, 0, outerLen, dim, true);
        const triangles = [];

        if (!outerNode || outerNode.next === outerNode.prev) return triangles;

        let minX, minY, invSize;

        if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);

        // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
        if (data.length > 80 * dim) {
            minX = data[0];
            minY = data[1];
            let maxX = minX;
            let maxY = minY;

            for (let i = dim; i < outerLen; i += dim) {
                const x = data[i];
                const y = data[i + 1];
                if (x < minX) minX = x;
                if (y < minY) minY = y;
                if (x > maxX) maxX = x;
                if (y > maxY) maxY = y;
            }

            // minX, minY and invSize are later used to transform coords into integers for z-order calculation
            invSize = Math.max(maxX - minX, maxY - minY);
            invSize = invSize !== 0 ? 32767 / invSize : 0;
        }

        earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);

        return triangles;
    }

    // create a circular doubly linked list from polygon points in the specified winding order
    function linkedList(data, start, end, dim, clockwise) {
        let last;

        if (clockwise === (signedArea(data, start, end, dim) > 0)) {
            for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
        } else {
            for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
        }

        if (last && equals(last, last.next)) {
            removeNode(last);
            last = last.next;
        }

        return last;
    }

    // eliminate colinear or duplicate points
    function filterPoints(start, end) {
        if (!start) return start;
        if (!end) end = start;

        let p = start,
            again;
        do {
            again = false;

            if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
                removeNode(p);
                p = end = p.prev;
                if (p === p.next) break;
                again = true;

            } else {
                p = p.next;
            }
        } while (again || p !== end);

        return end;
    }

    // main ear slicing loop which triangulates a polygon (given as a linked list)
    function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
        if (!ear) return;

        // interlink polygon nodes in z-order
        if (!pass && invSize) indexCurve(ear, minX, minY, invSize);

        let stop = ear;

        // iterate through ears, slicing them one by one
        while (ear.prev !== ear.next) {
            const prev = ear.prev;
            const next = ear.next;

            if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
                triangles.push(prev.i, ear.i, next.i); // cut off the triangle

                removeNode(ear);

                // skipping the next vertex leads to less sliver triangles
                ear = next.next;
                stop = next.next;

                continue;
            }

            ear = next;

            // if we looped through the whole remaining polygon and can't find any more ears
            if (ear === stop) {
                // try filtering points and slicing again
                if (!pass) {
                    earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);

                // if this didn't work, try curing all small self-intersections locally
                } else if (pass === 1) {
                    ear = cureLocalIntersections(filterPoints(ear), triangles);
                    earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);

                // as a last resort, try splitting the remaining polygon into two
                } else if (pass === 2) {
                    splitEarcut(ear, triangles, dim, minX, minY, invSize);
                }

                break;
            }
        }
    }

    // check whether a polygon node forms a valid ear with adjacent nodes
    function isEar(ear) {
        const a = ear.prev,
            b = ear,
            c = ear.next;

        if (area(a, b, c) >= 0) return false; // reflex, can't be an ear

        // now make sure we don't have other points inside the potential ear
        const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;

        // triangle bbox
        const x0 = Math.min(ax, bx, cx),
            y0 = Math.min(ay, by, cy),
            x1 = Math.max(ax, bx, cx),
            y1 = Math.max(ay, by, cy);

        let p = c.next;
        while (p !== a) {
            if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
                pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&
                area(p.prev, p, p.next) >= 0) return false;
            p = p.next;
        }

        return true;
    }

    function isEarHashed(ear, minX, minY, invSize) {
        const a = ear.prev,
            b = ear,
            c = ear.next;

        if (area(a, b, c) >= 0) return false; // reflex, can't be an ear

        const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;

        // triangle bbox
        const x0 = Math.min(ax, bx, cx),
            y0 = Math.min(ay, by, cy),
            x1 = Math.max(ax, bx, cx),
            y1 = Math.max(ay, by, cy);

        // z-order range for the current triangle bbox;
        const minZ = zOrder(x0, y0, minX, minY, invSize),
            maxZ = zOrder(x1, y1, minX, minY, invSize);

        let p = ear.prevZ,
            n = ear.nextZ;

        // look for points inside the triangle in both directions
        while (p && p.z >= minZ && n && n.z <= maxZ) {
            if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
                pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
            p = p.prevZ;

            if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
                pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
            n = n.nextZ;
        }

        // look for remaining points in decreasing z-order
        while (p && p.z >= minZ) {
            if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
                pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
            p = p.prevZ;
        }

        // look for remaining points in increasing z-order
        while (n && n.z <= maxZ) {
            if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
                pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
            n = n.nextZ;
        }

        return true;
    }

    // go through all polygon nodes and cure small local self-intersections
    function cureLocalIntersections(start, triangles) {
        let p = start;
        do {
            const a = p.prev,
                b = p.next.next;

            if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {

                triangles.push(a.i, p.i, b.i);

                // remove two nodes involved
                removeNode(p);
                removeNode(p.next);

                p = start = b;
            }
            p = p.next;
        } while (p !== start);

        return filterPoints(p);
    }

    // try splitting polygon into two and triangulate them independently
    function splitEarcut(start, triangles, dim, minX, minY, invSize) {
        // look for a valid diagonal that divides the polygon into two
        let a = start;
        do {
            let b = a.next.next;
            while (b !== a.prev) {
                if (a.i !== b.i && isValidDiagonal(a, b)) {
                    // split the polygon in two by the diagonal
                    let c = splitPolygon(a, b);

                    // filter colinear points around the cuts
                    a = filterPoints(a, a.next);
                    c = filterPoints(c, c.next);

                    // run earcut on each half
                    earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
                    earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
                    return;
                }
                b = b.next;
            }
            a = a.next;
        } while (a !== start);
    }

    // link every hole into the outer loop, producing a single-ring polygon without holes
    function eliminateHoles(data, holeIndices, outerNode, dim) {
        const queue = [];

        for (let i = 0, len = holeIndices.length; i < len; i++) {
            const start = holeIndices[i] * dim;
            const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
            const list = linkedList(data, start, end, dim, false);
            if (list === list.next) list.steiner = true;
            queue.push(getLeftmost(list));
        }

        queue.sort(compareXYSlope);

        // process holes from left to right
        for (let i = 0; i < queue.length; i++) {
            outerNode = eliminateHole(queue[i], outerNode);
        }

        return outerNode;
    }

    function compareXYSlope(a, b) {
        let result = a.x - b.x;
        // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find
        // the bridge to the outer shell is always the point that they meet at.
        if (result === 0) {
            result = a.y - b.y;
            if (result === 0) {
                const aSlope = (a.next.y - a.y) / (a.next.x - a.x);
                const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
                result = aSlope - bSlope;
            }
        }
        return result;
    }

    // find a bridge between vertices that connects hole with an outer ring and link it
    function eliminateHole(hole, outerNode) {
        const bridge = findHoleBridge(hole, outerNode);
        if (!bridge) {
            return outerNode;
        }

        const bridgeReverse = splitPolygon(bridge, hole);

        // filter collinear points around the cuts
        filterPoints(bridgeReverse, bridgeReverse.next);
        return filterPoints(bridge, bridge.next);
    }

    // David Eberly's algorithm for finding a bridge between hole and outer polygon
    function findHoleBridge(hole, outerNode) {
        let p = outerNode;
        const hx = hole.x;
        const hy = hole.y;
        let qx = -Infinity;
        let m;

        // find a segment intersected by a ray from the hole's leftmost point to the left;
        // segment's endpoint with lesser x will be potential connection point
        // unless they intersect at a vertex, then choose the vertex
        if (equals(hole, p)) return p;
        do {
            if (equals(hole, p.next)) return p.next;
            else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
                const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
                if (x <= hx && x > qx) {
                    qx = x;
                    m = p.x < p.next.x ? p : p.next;
                    if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
                }
            }
            p = p.next;
        } while (p !== outerNode);

        if (!m) return null;

        // look for points inside the triangle of hole point, segment intersection and endpoint;
        // if there are no points found, we have a valid connection;
        // otherwise choose the point of the minimum angle with the ray as connection point

        const stop = m;
        const mx = m.x;
        const my = m.y;
        let tanMin = Infinity;

        p = m;

        do {
            if (hx >= p.x && p.x >= mx && hx !== p.x &&
                    pointInTriangle$1(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {

                const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential

                if (locallyInside(p, hole) &&
                    (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
                    m = p;
                    tanMin = tan;
                }
            }

            p = p.next;
        } while (p !== stop);

        return m;
    }

    // whether sector in vertex m contains sector in vertex p in the same coordinates
    function sectorContainsSector(m, p) {
        return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
    }

    // interlink polygon nodes in z-order
    function indexCurve(start, minX, minY, invSize) {
        let p = start;
        do {
            if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
            p.prevZ = p.prev;
            p.nextZ = p.next;
            p = p.next;
        } while (p !== start);

        p.prevZ.nextZ = null;
        p.prevZ = null;

        sortLinked(p);
    }

    // Simon Tatham's linked list merge sort algorithm
    // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
    function sortLinked(list) {
        let numMerges;
        let inSize = 1;

        do {
            let p = list;
            let e;
            list = null;
            let tail = null;
            numMerges = 0;

            while (p) {
                numMerges++;
                let q = p;
                let pSize = 0;
                for (let i = 0; i < inSize; i++) {
                    pSize++;
                    q = q.nextZ;
                    if (!q) break;
                }
                let qSize = inSize;

                while (pSize > 0 || (qSize > 0 && q)) {

                    if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
                        e = p;
                        p = p.nextZ;
                        pSize--;
                    } else {
                        e = q;
                        q = q.nextZ;
                        qSize--;
                    }

                    if (tail) tail.nextZ = e;
                    else list = e;

                    e.prevZ = tail;
                    tail = e;
                }

                p = q;
            }

            tail.nextZ = null;
            inSize *= 2;

        } while (numMerges > 1);

        return list;
    }

    // z-order of a point given coords and inverse of the longer side of data bbox
    function zOrder(x, y, minX, minY, invSize) {
        // coords are transformed into non-negative 15-bit integer range
        x = (x - minX) * invSize | 0;
        y = (y - minY) * invSize | 0;

        x = (x | (x << 8)) & 0x00FF00FF;
        x = (x | (x << 4)) & 0x0F0F0F0F;
        x = (x | (x << 2)) & 0x33333333;
        x = (x | (x << 1)) & 0x55555555;

        y = (y | (y << 8)) & 0x00FF00FF;
        y = (y | (y << 4)) & 0x0F0F0F0F;
        y = (y | (y << 2)) & 0x33333333;
        y = (y | (y << 1)) & 0x55555555;

        return x | (y << 1);
    }

    // find the leftmost node of a polygon ring
    function getLeftmost(start) {
        let p = start,
            leftmost = start;
        do {
            if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
            p = p.next;
        } while (p !== start);

        return leftmost;
    }

    // check if a point lies within a convex triangle
    function pointInTriangle$1(ax, ay, bx, by, cx, cy, px, py) {
        return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
               (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
               (bx - px) * (cy - py) >= (cx - px) * (by - py);
    }

    // check if a point lies within a convex triangle but false if its equal to the first point of the triangle
    function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
        return !(ax === px && ay === py) && pointInTriangle$1(ax, ay, bx, by, cx, cy, px, py);
    }

    // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
    function isValidDiagonal(a, b) {
        return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges
               (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
                (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
                equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
    }

    // signed area of a triangle
    function area(p, q, r) {
        return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
    }

    // check if two points are equal
    function equals(p1, p2) {
        return p1.x === p2.x && p1.y === p2.y;
    }

    // check if two segments intersect
    function intersects(p1, q1, p2, q2) {
        const o1 = sign(area(p1, q1, p2));
        const o2 = sign(area(p1, q1, q2));
        const o3 = sign(area(p2, q2, p1));
        const o4 = sign(area(p2, q2, q1));

        if (o1 !== o2 && o3 !== o4) return true; // general case

        if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
        if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
        if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
        if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2

        return false;
    }

    // for collinear points p, q, r, check if point q lies on segment pr
    function onSegment(p, q, r) {
        return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
    }

    function sign(num) {
        return num > 0 ? 1 : num < 0 ? -1 : 0;
    }

    // check if a polygon diagonal intersects any polygon segments
    function intersectsPolygon(a, b) {
        let p = a;
        do {
            if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
                    intersects(p, p.next, a, b)) return true;
            p = p.next;
        } while (p !== a);

        return false;
    }

    // check if a polygon diagonal is locally inside the polygon
    function locallyInside(a, b) {
        return area(a.prev, a, a.next) < 0 ?
            area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
            area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
    }

    // check if the middle point of a polygon diagonal is inside the polygon
    function middleInside(a, b) {
        let p = a;
        let inside = false;
        const px = (a.x + b.x) / 2;
        const py = (a.y + b.y) / 2;
        do {
            if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
                    (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
                inside = !inside;
            p = p.next;
        } while (p !== a);

        return inside;
    }

    // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
    // if one belongs to the outer ring and another to a hole, it merges it into a single ring
    function splitPolygon(a, b) {
        const a2 = createNode(a.i, a.x, a.y),
            b2 = createNode(b.i, b.x, b.y),
            an = a.next,
            bp = b.prev;

        a.next = b;
        b.prev = a;

        a2.next = an;
        an.prev = a2;

        b2.next = a2;
        a2.prev = b2;

        bp.next = b2;
        b2.prev = bp;

        return b2;
    }

    // create a node and optionally link it with previous one (in a circular doubly linked list)
    function insertNode(i, x, y, last) {
        const p = createNode(i, x, y);

        if (!last) {
            p.prev = p;
            p.next = p;

        } else {
            p.next = last.next;
            p.prev = last;
            last.next.prev = p;
            last.next = p;
        }
        return p;
    }

    function removeNode(p) {
        p.next.prev = p.prev;
        p.prev.next = p.next;

        if (p.prevZ) p.prevZ.nextZ = p.nextZ;
        if (p.nextZ) p.nextZ.prevZ = p.prevZ;
    }

    function createNode(i, x, y) {
        return {
            i, // vertex index in coordinates array
            x, y, // vertex coordinates
            prev: null, // previous and next vertex nodes in a polygon ring
            next: null,
            z: 0, // z-order curve value
            prevZ: null, // previous and next nodes in z-order
            nextZ: null,
            steiner: false // indicates whether this is a steiner point
        };
    }

    // return a percentage difference between the polygon area and its triangulation area;
    // used to verify correctness of triangulation
    function deviation(data, holeIndices, dim, triangles) {
        const hasHoles = holeIndices && holeIndices.length;
        const outerLen = hasHoles ? holeIndices[0] * dim : data.length;

        let polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
        if (hasHoles) {
            for (let i = 0, len = holeIndices.length; i < len; i++) {
                const start = holeIndices[i] * dim;
                const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
                polygonArea -= Math.abs(signedArea(data, start, end, dim));
            }
        }

        let trianglesArea = 0;
        for (let i = 0; i < triangles.length; i += 3) {
            const a = triangles[i] * dim;
            const b = triangles[i + 1] * dim;
            const c = triangles[i + 2] * dim;
            trianglesArea += Math.abs(
                (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
                (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
        }

        return polygonArea === 0 && trianglesArea === 0 ? 0 :
            Math.abs((trianglesArea - polygonArea) / polygonArea);
    }

    function signedArea(data, start, end, dim) {
        let sum = 0;
        for (let i = start, j = end - dim; i < end; i += dim) {
            sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
            j = i;
        }
        return sum;
    }

    // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
    function flatten(data) {
        const vertices = [];
        const holes = [];
        const dimensions = data[0][0].length;
        let holeIndex = 0;
        let prevLen = 0;

        for (const ring of data) {
            for (const p of ring) {
                for (let d = 0; d < dimensions; d++) vertices.push(p[d]);
            }
            if (prevLen) {
                holeIndex += prevLen;
                holes.push(holeIndex);
            }
            prevLen = ring.length;
        }
        return {vertices, holes, dimensions};
    }

    "use strict";
    const earcut = earcut$1.default || earcut$1;

    "use strict";
    function triangulateWithHoles(points, holes, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
      const triangles = earcut(points, holes, 2);
      if (!triangles) {
        return;
      }
      for (let i = 0; i < triangles.length; i += 3) {
        indices[indicesOffset++] = triangles[i] + verticesOffset;
        indices[indicesOffset++] = triangles[i + 1] + verticesOffset;
        indices[indicesOffset++] = triangles[i + 2] + verticesOffset;
      }
      let index = verticesOffset * verticesStride;
      for (let i = 0; i < points.length; i += 2) {
        vertices[index] = points[i];
        vertices[index + 1] = points[i + 1];
        index += verticesStride;
      }
    }

    "use strict";
    const emptyArray = [];
    const buildPolygon = {
      extension: {
        type: ExtensionType.ShapeBuilder,
        name: "polygon"
      },
      build(shape, points) {
        for (let i = 0; i < shape.points.length; i++) {
          points[i] = shape.points[i];
        }
        return true;
      },
      triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
        triangulateWithHoles(points, emptyArray, vertices, verticesStride, verticesOffset, indices, indicesOffset);
      }
    };

    "use strict";
    const buildRectangle = {
      extension: {
        type: ExtensionType.ShapeBuilder,
        name: "rectangle"
      },
      build(shape, points) {
        const rectData = shape;
        const x = rectData.x;
        const y = rectData.y;
        const width = rectData.width;
        const height = rectData.height;
        if (!(width > 0 && height > 0)) {
          return false;
        }
        points[0] = x;
        points[1] = y;
        points[2] = x + width;
        points[3] = y;
        points[4] = x + width;
        points[5] = y + height;
        points[6] = x;
        points[7] = y + height;
        return true;
      },
      triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
        let count = 0;
        verticesOffset *= verticesStride;
        vertices[verticesOffset + count] = points[0];
        vertices[verticesOffset + count + 1] = points[1];
        count += verticesStride;
        vertices[verticesOffset + count] = points[2];
        vertices[verticesOffset + count + 1] = points[3];
        count += verticesStride;
        vertices[verticesOffset + count] = points[6];
        vertices[verticesOffset + count + 1] = points[7];
        count += verticesStride;
        vertices[verticesOffset + count] = points[4];
        vertices[verticesOffset + count + 1] = points[5];
        count += verticesStride;
        const verticesIndex = verticesOffset / verticesStride;
        indices[indicesOffset++] = verticesIndex;
        indices[indicesOffset++] = verticesIndex + 1;
        indices[indicesOffset++] = verticesIndex + 2;
        indices[indicesOffset++] = verticesIndex + 1;
        indices[indicesOffset++] = verticesIndex + 3;
        indices[indicesOffset++] = verticesIndex + 2;
      }
    };

    "use strict";
    const buildTriangle = {
      extension: {
        type: ExtensionType.ShapeBuilder,
        name: "triangle"
      },
      build(shape, points) {
        points[0] = shape.x;
        points[1] = shape.y;
        points[2] = shape.x2;
        points[3] = shape.y2;
        points[4] = shape.x3;
        points[5] = shape.y3;
        return true;
      },
      triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
        let count = 0;
        verticesOffset *= verticesStride;
        vertices[verticesOffset + count] = points[0];
        vertices[verticesOffset + count + 1] = points[1];
        count += verticesStride;
        vertices[verticesOffset + count] = points[2];
        vertices[verticesOffset + count + 1] = points[3];
        count += verticesStride;
        vertices[verticesOffset + count] = points[4];
        vertices[verticesOffset + count + 1] = points[5];
        const verticesIndex = verticesOffset / verticesStride;
        indices[indicesOffset++] = verticesIndex;
        indices[indicesOffset++] = verticesIndex + 1;
        indices[indicesOffset++] = verticesIndex + 2;
      }
    };

    "use strict";
    var __defProp$Z = Object.defineProperty;
    var __getOwnPropSymbols$$ = Object.getOwnPropertySymbols;
    var __hasOwnProp$$ = Object.prototype.hasOwnProperty;
    var __propIsEnum$$ = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$Z = (obj, key, value) => key in obj ? __defProp$Z(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$Z = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$$.call(b, prop))
          __defNormalProp$Z(a, prop, b[prop]);
      if (__getOwnPropSymbols$$)
        for (var prop of __getOwnPropSymbols$$(b)) {
          if (__propIsEnum$$.call(b, prop))
            __defNormalProp$Z(a, prop, b[prop]);
        }
      return a;
    };
    const emptyColorStops = [{ offset: 0, color: "white" }, { offset: 1, color: "black" }];
    const _FillGradient = class _FillGradient {
      constructor(...args) {
        /**
         * Unique identifier for this gradient instance
         * @internal
         */
        this.uid = uid$1("fillGradient");
        /**
         * Internal tick counter to track changes in the gradient.
         * This is used to invalidate the gradient when the texture changes.
         * @internal
         */
        this._tick = 0;
        /** Type of gradient - currently only supports 'linear' */
        this.type = "linear";
        /** Array of color stops defining the gradient */
        this.colorStops = [];
        var _a;
        let options = ensureGradientOptions(args);
        const defaults = options.type === "radial" ? _FillGradient.defaultRadialOptions : _FillGradient.defaultLinearOptions;
        options = __spreadValues$Z(__spreadValues$Z({}, defaults), definedProps(options));
        this._textureSize = options.textureSize;
        this._wrapMode = options.wrapMode;
        if (options.type === "radial") {
          this.center = options.center;
          this.outerCenter = (_a = options.outerCenter) != null ? _a : this.center;
          this.innerRadius = options.innerRadius;
          this.outerRadius = options.outerRadius;
          this.scale = options.scale;
          this.rotation = options.rotation;
        } else {
          this.start = options.start;
          this.end = options.end;
        }
        this.textureSpace = options.textureSpace;
        this.type = options.type;
        options.colorStops.forEach((stop) => {
          this.addColorStop(stop.offset, stop.color);
        });
      }
      /**
       * Adds a color stop to the gradient
       * @param offset - Position of the stop (0-1)
       * @param color - Color of the stop
       * @returns This gradient instance for chaining
       */
      addColorStop(offset, color) {
        this.colorStops.push({ offset, color: Color.shared.setValue(color).toHexa() });
        return this;
      }
      /**
       * Builds the internal texture and transform for the gradient.
       * Called automatically when the gradient is first used.
       * @internal
       */
      buildLinearGradient() {
        if (this.texture)
          return;
        let { x: x0, y: y0 } = this.start;
        let { x: x1, y: y1 } = this.end;
        let dx = x1 - x0;
        let dy = y1 - y0;
        const flip = dx < 0 || dy < 0;
        if (this._wrapMode === "clamp-to-edge") {
          if (dx < 0) {
            const temp = x0;
            x0 = x1;
            x1 = temp;
            dx *= -1;
          }
          if (dy < 0) {
            const temp = y0;
            y0 = y1;
            y1 = temp;
            dy *= -1;
          }
        }
        const colorStops = this.colorStops.length ? this.colorStops : emptyColorStops;
        const defaultSize = this._textureSize;
        const { canvas, context } = getCanvas(defaultSize, 1);
        const gradient = !flip ? context.createLinearGradient(0, 0, this._textureSize, 0) : context.createLinearGradient(this._textureSize, 0, 0, 0);
        addColorStops(gradient, colorStops);
        context.fillStyle = gradient;
        context.fillRect(0, 0, defaultSize, 1);
        this.texture = new Texture({
          source: new ImageSource({
            resource: canvas,
            addressMode: this._wrapMode
          })
        });
        const dist = Math.sqrt(dx * dx + dy * dy);
        const angle = Math.atan2(dy, dx);
        const m = new Matrix();
        m.scale(dist / defaultSize, 1);
        m.rotate(angle);
        m.translate(x0, y0);
        if (this.textureSpace === "local") {
          m.scale(defaultSize, defaultSize);
        }
        this.transform = m;
      }
      /**
       * Builds the internal texture and transform for the gradient.
       * Called automatically when the gradient is first used.
       * @internal
       */
      buildGradient() {
        if (!this.texture)
          this._tick++;
        if (this.type === "linear") {
          this.buildLinearGradient();
        } else {
          this.buildRadialGradient();
        }
      }
      /**
       * Builds the internal texture and transform for the radial gradient.
       * Called automatically when the gradient is first used.
       * @internal
       */
      buildRadialGradient() {
        if (this.texture)
          return;
        const colorStops = this.colorStops.length ? this.colorStops : emptyColorStops;
        const defaultSize = this._textureSize;
        const { canvas, context } = getCanvas(defaultSize, defaultSize);
        const { x: x0, y: y0 } = this.center;
        const { x: x1, y: y1 } = this.outerCenter;
        const r0 = this.innerRadius;
        const r1 = this.outerRadius;
        const ox = x1 - r1;
        const oy = y1 - r1;
        const scale = defaultSize / (r1 * 2);
        const cx = (x0 - ox) * scale;
        const cy = (y0 - oy) * scale;
        const gradient = context.createRadialGradient(
          cx,
          cy,
          r0 * scale,
          (x1 - ox) * scale,
          (y1 - oy) * scale,
          r1 * scale
        );
        addColorStops(gradient, colorStops);
        context.fillStyle = colorStops[colorStops.length - 1].color;
        context.fillRect(0, 0, defaultSize, defaultSize);
        context.fillStyle = gradient;
        context.translate(cx, cy);
        context.rotate(this.rotation);
        context.scale(1, this.scale);
        context.translate(-cx, -cy);
        context.fillRect(0, 0, defaultSize, defaultSize);
        this.texture = new Texture({
          source: new ImageSource({
            resource: canvas,
            addressMode: this._wrapMode
          })
        });
        const m = new Matrix();
        m.scale(1 / scale, 1 / scale);
        m.translate(ox, oy);
        if (this.textureSpace === "local") {
          m.scale(defaultSize, defaultSize);
        }
        this.transform = m;
      }
      /** Destroys the gradient, releasing resources. This will also destroy the internal texture. */
      destroy() {
        var _a;
        (_a = this.texture) == null ? void 0 : _a.destroy(true);
        this.texture = null;
        this.transform = null;
        this.colorStops = [];
        this.start = null;
        this.end = null;
        this.center = null;
        this.outerCenter = null;
      }
      /**
       * Returns a unique key for this gradient instance.
       * This key is used for caching and texture management.
       * @returns {string} Unique key for the gradient
       */
      get styleKey() {
        return `fill-gradient-${this.uid}-${this._tick}`;
      }
    };
    /** Default options for creating a gradient fill */
    _FillGradient.defaultLinearOptions = {
      start: { x: 0, y: 0 },
      end: { x: 0, y: 1 },
      colorStops: [],
      textureSpace: "local",
      type: "linear",
      textureSize: 256,
      wrapMode: "clamp-to-edge"
    };
    /** Default options for creating a radial gradient fill */
    _FillGradient.defaultRadialOptions = {
      center: { x: 0.5, y: 0.5 },
      innerRadius: 0,
      outerRadius: 0.5,
      colorStops: [],
      scale: 1,
      textureSpace: "local",
      type: "radial",
      textureSize: 256,
      wrapMode: "clamp-to-edge"
    };
    let FillGradient = _FillGradient;
    function addColorStops(gradient, colorStops) {
      for (let i = 0; i < colorStops.length; i++) {
        const stop = colorStops[i];
        gradient.addColorStop(stop.offset, stop.color);
      }
    }
    function getCanvas(width, height) {
      const canvas = DOMAdapter.get().createCanvas(width, height);
      const context = canvas.getContext("2d");
      return { canvas, context };
    }
    function ensureGradientOptions(args) {
      var _a, _b;
      let options = (_a = args[0]) != null ? _a : {};
      if (typeof options === "number" || args[1]) {
        deprecation("8.5.2", `use options object instead`);
        options = {
          type: "linear",
          start: { x: args[0], y: args[1] },
          end: { x: args[2], y: args[3] },
          textureSpace: args[4],
          textureSize: (_b = args[5]) != null ? _b : FillGradient.defaultLinearOptions.textureSize
        };
      }
      return options;
    }

    "use strict";
    const tempTextureMatrix$1 = new Matrix();
    const tempRect$4 = new Rectangle();
    function generateTextureMatrix(out, style, shape, matrix) {
      const textureMatrix = style.matrix ? out.copyFrom(style.matrix).invert() : out.identity();
      if (style.textureSpace === "local") {
        const bounds = shape.getBounds(tempRect$4);
        if (style.width) {
          bounds.pad(style.width);
        }
        const { x: tx, y: ty } = bounds;
        const sx = 1 / bounds.width;
        const sy = 1 / bounds.height;
        const mTx = -tx * sx;
        const mTy = -ty * sy;
        const a1 = textureMatrix.a;
        const b1 = textureMatrix.b;
        const c1 = textureMatrix.c;
        const d1 = textureMatrix.d;
        textureMatrix.a *= sx;
        textureMatrix.b *= sx;
        textureMatrix.c *= sy;
        textureMatrix.d *= sy;
        textureMatrix.tx = mTx * a1 + mTy * c1 + textureMatrix.tx;
        textureMatrix.ty = mTx * b1 + mTy * d1 + textureMatrix.ty;
      } else {
        textureMatrix.translate(style.texture.frame.x, style.texture.frame.y);
        textureMatrix.scale(1 / style.texture.source.width, 1 / style.texture.source.height);
      }
      const sourceStyle = style.texture.source.style;
      if (!(style.fill instanceof FillGradient) && sourceStyle.addressMode === "clamp-to-edge") {
        sourceStyle.addressMode = "repeat";
        sourceStyle.update();
      }
      if (matrix) {
        textureMatrix.append(tempTextureMatrix$1.copyFrom(matrix).invert());
      }
      return textureMatrix;
    }

    "use strict";
    const shapeBuilders = {};
    extensions.handleByMap(ExtensionType.ShapeBuilder, shapeBuilders);
    extensions.add(buildRectangle, buildPolygon, buildTriangle, buildCircle, buildEllipse, buildRoundedRectangle);
    const tempRect$3 = new Rectangle();
    const tempTextureMatrix = new Matrix();
    function buildContextBatches(context, gpuContext) {
      const { geometryData, batches } = gpuContext;
      batches.length = 0;
      geometryData.indices.length = 0;
      geometryData.vertices.length = 0;
      geometryData.uvs.length = 0;
      for (let i = 0; i < context.instructions.length; i++) {
        const instruction = context.instructions[i];
        if (instruction.action === "texture") {
          addTextureToGeometryData(instruction.data, batches, geometryData);
        } else if (instruction.action === "fill" || instruction.action === "stroke") {
          const isStroke = instruction.action === "stroke";
          const shapePath = instruction.data.path.shapePath;
          const style = instruction.data.style;
          const hole = instruction.data.hole;
          if (isStroke && hole) {
            addShapePathToGeometryData(hole.shapePath, style, true, batches, geometryData);
          }
          if (hole) {
            shapePath.shapePrimitives[shapePath.shapePrimitives.length - 1].holes = hole.shapePath.shapePrimitives;
          }
          addShapePathToGeometryData(shapePath, style, isStroke, batches, geometryData);
        }
      }
    }
    function addTextureToGeometryData(data, batches, geometryData) {
      const points = [];
      const build = shapeBuilders.rectangle;
      const rect = tempRect$3;
      rect.x = data.dx;
      rect.y = data.dy;
      rect.width = data.dw;
      rect.height = data.dh;
      const matrix = data.transform;
      if (!build.build(rect, points)) {
        return;
      }
      const { vertices, uvs, indices } = geometryData;
      const indexOffset = indices.length;
      const vertOffset = vertices.length / 2;
      if (matrix) {
        transformVertices(points, matrix);
      }
      build.triangulate(points, vertices, 2, vertOffset, indices, indexOffset);
      const texture = data.image;
      const textureUvs = texture.uvs;
      uvs.push(
        textureUvs.x0,
        textureUvs.y0,
        textureUvs.x1,
        textureUvs.y1,
        textureUvs.x3,
        textureUvs.y3,
        textureUvs.x2,
        textureUvs.y2
      );
      const graphicsBatch = BigPool.get(BatchableGraphics);
      graphicsBatch.indexOffset = indexOffset;
      graphicsBatch.indexSize = indices.length - indexOffset;
      graphicsBatch.attributeOffset = vertOffset;
      graphicsBatch.attributeSize = vertices.length / 2 - vertOffset;
      graphicsBatch.baseColor = data.style;
      graphicsBatch.alpha = data.alpha;
      graphicsBatch.texture = texture;
      graphicsBatch.geometryData = geometryData;
      batches.push(graphicsBatch);
    }
    function addShapePathToGeometryData(shapePath, style, isStroke, batches, geometryData) {
      const { vertices, uvs, indices } = geometryData;
      shapePath.shapePrimitives.forEach(({ shape, transform: matrix, holes }) => {
        var _a;
        const points = [];
        const build = shapeBuilders[shape.type];
        if (!build.build(shape, points)) {
          return;
        }
        const indexOffset = indices.length;
        const vertOffset = vertices.length / 2;
        let topology = "triangle-list";
        if (matrix) {
          transformVertices(points, matrix);
        }
        if (!isStroke) {
          if (holes) {
            const holeIndices = [];
            const otherPoints = points.slice();
            const holeArrays = getHoleArrays(holes);
            holeArrays.forEach((holePoints) => {
              holeIndices.push(otherPoints.length / 2);
              otherPoints.push(...holePoints);
            });
            triangulateWithHoles(otherPoints, holeIndices, vertices, 2, vertOffset, indices, indexOffset);
          } else {
            build.triangulate(points, vertices, 2, vertOffset, indices, indexOffset);
          }
        } else {
          const close = (_a = shape.closePath) != null ? _a : true;
          const lineStyle = style;
          if (!lineStyle.pixelLine) {
            buildLine(points, lineStyle, false, close, vertices, indices);
          } else {
            buildPixelLine(points, close, vertices, indices);
            topology = "line-list";
          }
        }
        const uvsOffset = uvs.length / 2;
        const texture = style.texture;
        if (texture !== Texture.WHITE) {
          const textureMatrix = generateTextureMatrix(tempTextureMatrix, style, shape, matrix);
          buildUvs(vertices, 2, vertOffset, uvs, uvsOffset, 2, vertices.length / 2 - vertOffset, textureMatrix);
        } else {
          buildSimpleUvs(uvs, uvsOffset, 2, vertices.length / 2 - vertOffset);
        }
        const graphicsBatch = BigPool.get(BatchableGraphics);
        graphicsBatch.indexOffset = indexOffset;
        graphicsBatch.indexSize = indices.length - indexOffset;
        graphicsBatch.attributeOffset = vertOffset;
        graphicsBatch.attributeSize = vertices.length / 2 - vertOffset;
        graphicsBatch.baseColor = style.color;
        graphicsBatch.alpha = style.alpha;
        graphicsBatch.texture = texture;
        graphicsBatch.geometryData = geometryData;
        graphicsBatch.topology = topology;
        batches.push(graphicsBatch);
      });
    }
    function getHoleArrays(holePrimitives) {
      const holeArrays = [];
      for (let k = 0; k < holePrimitives.length; k++) {
        const holePrimitive = holePrimitives[k].shape;
        const holePoints = [];
        const holeBuilder = shapeBuilders[holePrimitive.type];
        if (holeBuilder.build(holePrimitive, holePoints)) {
          holeArrays.push(holePoints);
        }
      }
      return holeArrays;
    }

    "use strict";
    class GpuGraphicsContext {
      constructor() {
        this.batches = [];
        this.geometryData = {
          vertices: [],
          uvs: [],
          indices: []
        };
      }
      reset() {
        if (this.batches) {
          this.batches.forEach((batch) => {
            BigPool.return(batch);
          });
        }
        if (this.graphicsData) {
          BigPool.return(this.graphicsData);
        }
        this.isBatchable = false;
        this.context = null;
        this.batches.length = 0;
        this.geometryData.indices.length = 0;
        this.geometryData.vertices.length = 0;
        this.geometryData.uvs.length = 0;
        this.graphicsData = null;
      }
      destroy() {
        this.reset();
        this.batches = null;
        this.geometryData = null;
      }
    }
    class GraphicsContextRenderData {
      constructor() {
        this.instructions = new InstructionSet();
      }
      init(options) {
        const maxTextures = options.maxTextures;
        this.batcher ? this.batcher._updateMaxTextures(maxTextures) : this.batcher = new DefaultBatcher({ maxTextures });
        this.instructions.reset();
      }
      /**
       * @deprecated since version 8.0.0
       * Use `batcher.geometry` instead.
       * @see {Batcher#geometry}
       */
      get geometry() {
        deprecation(v8_3_4, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead.");
        return this.batcher.geometry;
      }
      destroy() {
        this.batcher.destroy();
        this.instructions.destroy();
        this.batcher = null;
        this.instructions = null;
      }
    }
    const _GraphicsContextSystem = class _GraphicsContextSystem {
      constructor(renderer) {
        this._renderer = renderer;
        this._managedContexts = new GCManagedHash({ renderer, type: "resource", name: "graphicsContext" });
      }
      /**
       * Runner init called, update the default options
       * @ignore
       */
      init(options) {
        var _a;
        _GraphicsContextSystem.defaultOptions.bezierSmoothness = (_a = options == null ? void 0 : options.bezierSmoothness) != null ? _a : _GraphicsContextSystem.defaultOptions.bezierSmoothness;
      }
      /**
       * Returns the render data for a given GraphicsContext.
       * @param context - The GraphicsContext to get the render data for.
       * @internal
       */
      getContextRenderData(context) {
        return context._gpuData[this._renderer.uid].graphicsData || this._initContextRenderData(context);
      }
      /**
       * Updates the GPU context for a given GraphicsContext.
       * If the context is dirty, it will rebuild the batches and geometry data.
       * @param context - The GraphicsContext to update.
       * @returns The updated GpuGraphicsContext.
       * @internal
       */
      updateGpuContext(context) {
        const hasContext = !!context._gpuData[this._renderer.uid];
        const gpuContext = context._gpuData[this._renderer.uid] || this._initContext(context);
        if (context.dirty || !hasContext) {
          if (hasContext) {
            gpuContext.reset();
          }
          buildContextBatches(context, gpuContext);
          const batchMode = context.batchMode;
          if (context.customShader || batchMode === "no-batch") {
            gpuContext.isBatchable = false;
          } else if (batchMode === "auto") {
            gpuContext.isBatchable = gpuContext.geometryData.vertices.length < 400;
          } else {
            gpuContext.isBatchable = true;
          }
          context.dirty = false;
        }
        return gpuContext;
      }
      /**
       * Returns the GpuGraphicsContext for a given GraphicsContext.
       * If it does not exist, it will initialize a new one.
       * @param context - The GraphicsContext to get the GpuGraphicsContext for.
       * @returns The GpuGraphicsContext for the given GraphicsContext.
       * @internal
       */
      getGpuContext(context) {
        return context._gpuData[this._renderer.uid] || this._initContext(context);
      }
      _initContextRenderData(context) {
        const graphicsData = BigPool.get(GraphicsContextRenderData, {
          maxTextures: this._renderer.limits.maxBatchableTextures
        });
        const gpuContext = context._gpuData[this._renderer.uid];
        const { batches, geometryData } = gpuContext;
        gpuContext.graphicsData = graphicsData;
        const vertexSize = geometryData.vertices.length;
        const indexSize = geometryData.indices.length;
        for (let i = 0; i < batches.length; i++) {
          batches[i].applyTransform = false;
        }
        const batcher = graphicsData.batcher;
        batcher.ensureAttributeBuffer(vertexSize);
        batcher.ensureIndexBuffer(indexSize);
        batcher.begin();
        for (let i = 0; i < batches.length; i++) {
          const batch = batches[i];
          batcher.add(batch);
        }
        batcher.finish(graphicsData.instructions);
        const geometry = batcher.geometry;
        geometry.indexBuffer.setDataWithSize(batcher.indexBuffer, batcher.indexSize, true);
        geometry.buffers[0].setDataWithSize(batcher.attributeBuffer.float32View, batcher.attributeSize, true);
        const drawBatches = batcher.batches;
        for (let i = 0; i < drawBatches.length; i++) {
          const batch = drawBatches[i];
          batch.bindGroup = getTextureBatchBindGroup(
            batch.textures.textures,
            batch.textures.count,
            this._renderer.limits.maxBatchableTextures
          );
        }
        return graphicsData;
      }
      _initContext(context) {
        const gpuContext = new GpuGraphicsContext();
        gpuContext.context = context;
        context._gpuData[this._renderer.uid] = gpuContext;
        this._managedContexts.add(context);
        return gpuContext;
      }
      destroy() {
        this._managedContexts.destroy();
        this._renderer = null;
      }
    };
    /** @ignore */
    _GraphicsContextSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "graphicsContext"
    };
    /** The default options for the GraphicsContextSystem. */
    _GraphicsContextSystem.defaultOptions = {
      /**
       * A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother)
       * @default 0.5
       */
      bezierSmoothness: 0.5
    };
    let GraphicsContextSystem = _GraphicsContextSystem;

    "use strict";
    const blendModeIds = {
      normal: 0,
      add: 1,
      multiply: 2,
      screen: 3,
      overlay: 4,
      erase: 5,
      "normal-npm": 6,
      "add-npm": 7,
      "screen-npm": 8,
      min: 9,
      max: 10
    };
    const BLEND$1 = 0;
    const OFFSET$1 = 1;
    const CULLING$1 = 2;
    const DEPTH_TEST$1 = 3;
    const WINDING$1 = 4;
    const DEPTH_MASK$1 = 5;
    const _State = class _State {
      constructor() {
        this.data = 0;
        this.blendMode = "normal";
        this.polygonOffset = 0;
        this.blend = true;
        this.depthMask = true;
      }
      /**
       * Activates blending of the computed fragment color values.
       * @default true
       */
      get blend() {
        return !!(this.data & 1 << BLEND$1);
      }
      set blend(value) {
        if (!!(this.data & 1 << BLEND$1) !== value) {
          this.data ^= 1 << BLEND$1;
        }
      }
      /**
       * Activates adding an offset to depth values of polygon's fragments
       * @default false
       */
      get offsets() {
        return !!(this.data & 1 << OFFSET$1);
      }
      set offsets(value) {
        if (!!(this.data & 1 << OFFSET$1) !== value) {
          this.data ^= 1 << OFFSET$1;
        }
      }
      /** The culling settings for this state none - No culling back - Back face culling front - Front face culling */
      set cullMode(value) {
        if (value === "none") {
          this.culling = false;
          return;
        }
        this.culling = true;
        this.clockwiseFrontFace = value === "front";
      }
      get cullMode() {
        if (!this.culling) {
          return "none";
        }
        return this.clockwiseFrontFace ? "front" : "back";
      }
      /**
       * Activates culling of polygons.
       * @default false
       */
      get culling() {
        return !!(this.data & 1 << CULLING$1);
      }
      set culling(value) {
        if (!!(this.data & 1 << CULLING$1) !== value) {
          this.data ^= 1 << CULLING$1;
        }
      }
      /**
       * Activates depth comparisons and updates to the depth buffer.
       * @default false
       */
      get depthTest() {
        return !!(this.data & 1 << DEPTH_TEST$1);
      }
      set depthTest(value) {
        if (!!(this.data & 1 << DEPTH_TEST$1) !== value) {
          this.data ^= 1 << DEPTH_TEST$1;
        }
      }
      /**
       * Enables or disables writing to the depth buffer.
       * @default true
       */
      get depthMask() {
        return !!(this.data & 1 << DEPTH_MASK$1);
      }
      set depthMask(value) {
        if (!!(this.data & 1 << DEPTH_MASK$1) !== value) {
          this.data ^= 1 << DEPTH_MASK$1;
        }
      }
      /**
       * Specifies whether or not front or back-facing polygons can be culled.
       * @default false
       */
      get clockwiseFrontFace() {
        return !!(this.data & 1 << WINDING$1);
      }
      set clockwiseFrontFace(value) {
        if (!!(this.data & 1 << WINDING$1) !== value) {
          this.data ^= 1 << WINDING$1;
        }
      }
      /**
       * The blend mode to be applied when this state is set. Apply a value of `normal` to reset the blend mode.
       * Setting this mode to anything other than NO_BLEND will automatically switch blending on.
       * @default 'normal'
       */
      get blendMode() {
        return this._blendMode;
      }
      set blendMode(value) {
        this.blend = value !== "none";
        this._blendMode = value;
        this._blendModeId = blendModeIds[value] || 0;
      }
      /**
       * The polygon offset. Setting this property to anything other than 0 will automatically enable polygon offset fill.
       * @default 0
       */
      get polygonOffset() {
        return this._polygonOffset;
      }
      set polygonOffset(value) {
        this.offsets = !!value;
        this._polygonOffset = value;
      }
      toString() {
        return `[pixi.js/core:State blendMode=${this.blendMode} clockwiseFrontFace=${this.clockwiseFrontFace} culling=${this.culling} depthMask=${this.depthMask} polygonOffset=${this.polygonOffset}]`;
      }
      /**
       * A quickly getting an instance of a State that is configured for 2d rendering.
       * @returns a new State with values set for 2d rendering
       */
      static for2d() {
        const state = new _State();
        state.depthTest = false;
        state.blend = true;
        return state;
      }
    };
    _State.default2d = _State.for2d();
    let State = _State;

    "use strict";
    function colorToUniform(rgb, alpha, out, offset) {
      out[offset++] = (rgb >> 16 & 255) / 255;
      out[offset++] = (rgb >> 8 & 255) / 255;
      out[offset++] = (rgb & 255) / 255;
      out[offset++] = alpha;
    }
    function color32BitToUniform(abgr, out, offset) {
      const alpha = (abgr >> 24 & 255) / 255;
      out[offset++] = (abgr & 255) / 255 * alpha;
      out[offset++] = (abgr >> 8 & 255) / 255 * alpha;
      out[offset++] = (abgr >> 16 & 255) / 255 * alpha;
      out[offset++] = alpha;
    }

    "use strict";
    class GraphicsGpuData {
      constructor() {
        this.batches = [];
        this.batched = false;
      }
      destroy() {
        this.batches.forEach((batch) => {
          BigPool.return(batch);
        });
        this.batches.length = 0;
      }
    }
    class GraphicsPipe {
      constructor(renderer, adaptor) {
        this.state = State.for2d();
        this.renderer = renderer;
        this._adaptor = adaptor;
        this.renderer.runners.contextChange.add(this);
        this._managedGraphics = new GCManagedHash({ renderer, type: "renderable", priority: -1, name: "graphics" });
      }
      contextChange() {
        this._adaptor.contextChange(this.renderer);
      }
      validateRenderable(graphics) {
        const context = graphics.context;
        const wasBatched = !!graphics._gpuData;
        const gpuContext = this.renderer.graphicsContext.updateGpuContext(context);
        if (gpuContext.isBatchable || wasBatched !== gpuContext.isBatchable) {
          return true;
        }
        return false;
      }
      addRenderable(graphics, instructionSet) {
        const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
        if (graphics.didViewUpdate) {
          this._rebuild(graphics);
        }
        if (gpuContext.isBatchable) {
          this._addToBatcher(graphics, instructionSet);
        } else {
          this.renderer.renderPipes.batch.break(instructionSet);
          instructionSet.add(graphics);
        }
      }
      updateRenderable(graphics) {
        const gpuData = this._getGpuDataForRenderable(graphics);
        const batches = gpuData.batches;
        for (let i = 0; i < batches.length; i++) {
          const batch = batches[i];
          batch._batcher.updateElement(batch);
        }
      }
      execute(graphics) {
        if (!graphics.isRenderable)
          return;
        const renderer = this.renderer;
        const context = graphics.context;
        const contextSystem = renderer.graphicsContext;
        if (!contextSystem.getGpuContext(context).batches.length) {
          return;
        }
        const shader = context.customShader || this._adaptor.shader;
        this.state.blendMode = graphics.groupBlendMode;
        const localUniforms = shader.resources.localUniforms.uniforms;
        localUniforms.uTransformMatrix = graphics.groupTransform;
        localUniforms.uRound = renderer._roundPixels | graphics._roundPixels;
        color32BitToUniform(
          graphics.groupColorAlpha,
          localUniforms.uColor,
          0
        );
        this._adaptor.execute(this, graphics);
      }
      _rebuild(graphics) {
        const gpuData = this._getGpuDataForRenderable(graphics);
        const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
        gpuData.destroy();
        if (gpuContext.isBatchable) {
          this._updateBatchesForRenderable(graphics, gpuData);
        }
      }
      _addToBatcher(graphics, instructionSet) {
        const batchPipe = this.renderer.renderPipes.batch;
        const batches = this._getGpuDataForRenderable(graphics).batches;
        for (let i = 0; i < batches.length; i++) {
          const batch = batches[i];
          batchPipe.addToBatch(batch, instructionSet);
        }
      }
      _getGpuDataForRenderable(graphics) {
        return graphics._gpuData[this.renderer.uid] || this._initGpuDataForRenderable(graphics);
      }
      _initGpuDataForRenderable(graphics) {
        const gpuData = new GraphicsGpuData();
        graphics._gpuData[this.renderer.uid] = gpuData;
        this._managedGraphics.add(graphics);
        return gpuData;
      }
      _updateBatchesForRenderable(graphics, gpuData) {
        const context = graphics.context;
        const gpuContext = this.renderer.graphicsContext.getGpuContext(context);
        const roundPixels = this.renderer._roundPixels | graphics._roundPixels;
        gpuData.batches = gpuContext.batches.map((batch) => {
          const batchClone = BigPool.get(BatchableGraphics);
          batch.copyTo(batchClone);
          batchClone.renderable = graphics;
          batchClone.roundPixels = roundPixels;
          return batchClone;
        });
      }
      destroy() {
        this._managedGraphics.destroy();
        this.renderer = null;
        this._adaptor.destroy();
        this._adaptor = null;
        this.state = null;
      }
    }
    /** @ignore */
    GraphicsPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "graphics"
    };

    "use strict";
    extensions.add(GraphicsPipe);
    extensions.add(GraphicsContextSystem);

    "use strict";
    class BatchableMesh {
      constructor() {
        this.batcherName = "default";
        this.packAsQuad = false;
        this.indexOffset = 0;
        this.attributeOffset = 0;
        this.roundPixels = 0;
        this._batcher = null;
        this._batch = null;
        this._textureMatrixUpdateId = -1;
        this._uvUpdateId = -1;
      }
      get blendMode() {
        return this.renderable.groupBlendMode;
      }
      get topology() {
        return this._topology || this.geometry.topology;
      }
      set topology(value) {
        this._topology = value;
      }
      reset() {
        this.renderable = null;
        this.texture = null;
        this._batcher = null;
        this._batch = null;
        this.geometry = null;
        this._uvUpdateId = -1;
        this._textureMatrixUpdateId = -1;
      }
      /**
       * Sets the texture for the batchable mesh.
       * As it does so, it resets the texture matrix update ID.
       * this is to ensure that the texture matrix is recalculated when the uvs are referenced
       * @param value - The texture to set.
       */
      setTexture(value) {
        if (this.texture === value)
          return;
        this.texture = value;
        this._textureMatrixUpdateId = -1;
      }
      get uvs() {
        const geometry = this.geometry;
        const uvBuffer = geometry.getBuffer("aUV");
        const uvs = uvBuffer.data;
        let transformedUvs = uvs;
        const textureMatrix = this.texture.textureMatrix;
        if (!textureMatrix.isSimple) {
          transformedUvs = this._transformedUvs;
          if (this._textureMatrixUpdateId !== textureMatrix._updateID || this._uvUpdateId !== uvBuffer._updateID) {
            if (!transformedUvs || transformedUvs.length < uvs.length) {
              transformedUvs = this._transformedUvs = new Float32Array(uvs.length);
            }
            this._textureMatrixUpdateId = textureMatrix._updateID;
            this._uvUpdateId = uvBuffer._updateID;
            textureMatrix.multiplyUvs(uvs, transformedUvs);
          }
        }
        return transformedUvs;
      }
      get positions() {
        return this.geometry.positions;
      }
      get indices() {
        return this.geometry.indices;
      }
      get color() {
        return this.renderable.groupColorAlpha;
      }
      get groupTransform() {
        return this.renderable.groupTransform;
      }
      get attributeSize() {
        return this.geometry.positions.length / 2;
      }
      get indexSize() {
        return this.geometry.indices.length;
      }
    }

    "use strict";
    class MeshGpuData {
      destroy() {
      }
    }
    class MeshPipe {
      constructor(renderer, adaptor) {
        this.localUniforms = new UniformGroup({
          uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
          uRound: { value: 0, type: "f32" }
        });
        this.localUniformsBindGroup = new BindGroup({
          0: this.localUniforms
        });
        this.renderer = renderer;
        this._adaptor = adaptor;
        this._adaptor.init();
      }
      validateRenderable(mesh) {
        const meshData = this._getMeshData(mesh);
        const wasBatched = meshData.batched;
        const isBatched = mesh.batched;
        meshData.batched = isBatched;
        if (wasBatched !== isBatched) {
          return true;
        } else if (isBatched) {
          const geometry = mesh._geometry;
          if (geometry.indices.length !== meshData.indexSize || geometry.positions.length !== meshData.vertexSize) {
            meshData.indexSize = geometry.indices.length;
            meshData.vertexSize = geometry.positions.length;
            return true;
          }
          const batchableMesh = this._getBatchableMesh(mesh);
          if (batchableMesh.texture.uid !== mesh._texture.uid) {
            batchableMesh._textureMatrixUpdateId = -1;
          }
          return !batchableMesh._batcher.checkAndUpdateTexture(
            batchableMesh,
            mesh._texture
          );
        }
        return false;
      }
      addRenderable(mesh, instructionSet) {
        var _a, _b;
        const batcher = this.renderer.renderPipes.batch;
        const meshData = this._getMeshData(mesh);
        if (mesh.didViewUpdate) {
          meshData.indexSize = (_a = mesh._geometry.indices) == null ? void 0 : _a.length;
          meshData.vertexSize = (_b = mesh._geometry.positions) == null ? void 0 : _b.length;
        }
        if (meshData.batched) {
          const gpuBatchableMesh = this._getBatchableMesh(mesh);
          gpuBatchableMesh.setTexture(mesh._texture);
          gpuBatchableMesh.geometry = mesh._geometry;
          batcher.addToBatch(gpuBatchableMesh, instructionSet);
        } else {
          batcher.break(instructionSet);
          instructionSet.add(mesh);
        }
      }
      updateRenderable(mesh) {
        if (mesh.batched) {
          const gpuBatchableMesh = this._getBatchableMesh(mesh);
          gpuBatchableMesh.setTexture(mesh._texture);
          gpuBatchableMesh.geometry = mesh._geometry;
          gpuBatchableMesh._batcher.updateElement(gpuBatchableMesh);
        }
      }
      execute(mesh) {
        if (!mesh.isRenderable)
          return;
        mesh.state.blendMode = getAdjustedBlendModeBlend(mesh.groupBlendMode, mesh.texture._source);
        const localUniforms = this.localUniforms;
        localUniforms.uniforms.uTransformMatrix = mesh.groupTransform;
        localUniforms.uniforms.uRound = this.renderer._roundPixels | mesh._roundPixels;
        localUniforms.update();
        color32BitToUniform(
          mesh.groupColorAlpha,
          localUniforms.uniforms.uColor,
          0
        );
        this._adaptor.execute(this, mesh);
      }
      _getMeshData(mesh) {
        var _a, _b;
        (_a = mesh._gpuData)[_b = this.renderer.uid] || (_a[_b] = new MeshGpuData());
        return mesh._gpuData[this.renderer.uid].meshData || this._initMeshData(mesh);
      }
      _initMeshData(mesh) {
        mesh._gpuData[this.renderer.uid].meshData = {
          batched: mesh.batched,
          indexSize: 0,
          vertexSize: 0
        };
        return mesh._gpuData[this.renderer.uid].meshData;
      }
      _getBatchableMesh(mesh) {
        var _a, _b;
        (_a = mesh._gpuData)[_b = this.renderer.uid] || (_a[_b] = new MeshGpuData());
        return mesh._gpuData[this.renderer.uid].batchableMesh || this._initBatchableMesh(mesh);
      }
      _initBatchableMesh(mesh) {
        const gpuMesh = new BatchableMesh();
        gpuMesh.renderable = mesh;
        gpuMesh.setTexture(mesh._texture);
        gpuMesh.transform = mesh.groupTransform;
        gpuMesh.roundPixels = this.renderer._roundPixels | mesh._roundPixels;
        mesh._gpuData[this.renderer.uid].batchableMesh = gpuMesh;
        return gpuMesh;
      }
      destroy() {
        this.localUniforms = null;
        this.localUniformsBindGroup = null;
        this._adaptor.destroy();
        this._adaptor = null;
        this.renderer = null;
      }
    }
    /** @ignore */
    MeshPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "mesh"
    };

    "use strict";
    extensions.add(MeshPipe);

    "use strict";
    class GlParticleContainerAdaptor {
      execute(particleContainerPipe, container) {
        const state = particleContainerPipe.state;
        const renderer = particleContainerPipe.renderer;
        const shader = container.shader || particleContainerPipe.defaultShader;
        shader.resources.uTexture = container.texture._source;
        shader.resources.uniforms = particleContainerPipe.localUniforms;
        const gl = renderer.gl;
        const buffer = particleContainerPipe.getBuffers(container);
        renderer.shader.bind(shader);
        renderer.state.set(state);
        renderer.geometry.bind(buffer.geometry, shader.glProgram);
        const byteSize = buffer.geometry.indexBuffer.data.BYTES_PER_ELEMENT;
        const glType = byteSize === 2 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
        gl.drawElements(gl.TRIANGLES, container.particleChildren.length * 6, glType, 0);
      }
    }

    "use strict";
    function createIndicesForQuads(size, outBuffer = null) {
      const totalIndices = size * 6;
      if (totalIndices > 65535) {
        outBuffer || (outBuffer = new Uint32Array(totalIndices));
      } else {
        outBuffer || (outBuffer = new Uint16Array(totalIndices));
      }
      if (outBuffer.length !== totalIndices) {
        throw new Error(`Out buffer length is incorrect, got ${outBuffer.length} and expected ${totalIndices}`);
      }
      for (let i = 0, j = 0; i < totalIndices; i += 6, j += 4) {
        outBuffer[i + 0] = j + 0;
        outBuffer[i + 1] = j + 1;
        outBuffer[i + 2] = j + 2;
        outBuffer[i + 3] = j + 0;
        outBuffer[i + 4] = j + 2;
        outBuffer[i + 5] = j + 3;
      }
      return outBuffer;
    }

    "use strict";
    function generateParticleUpdateFunction(properties) {
      return {
        dynamicUpdate: generateUpdateFunction(properties, true),
        staticUpdate: generateUpdateFunction(properties, false)
      };
    }
    function generateUpdateFunction(properties, dynamic) {
      const funcFragments = [];
      funcFragments.push(`

        var index = 0;

        for (let i = 0; i < ps.length; ++i)
        {
            const p = ps[i];

            `);
      let offset = 0;
      for (const i in properties) {
        const property = properties[i];
        if (dynamic !== property.dynamic)
          continue;
        funcFragments.push(`offset = index + ${offset}`);
        funcFragments.push(property.code);
        const attributeInfo = getAttributeInfoFromFormat(property.format);
        offset += attributeInfo.stride / 4;
      }
      funcFragments.push(`
            index += stride * 4;
        }
    `);
      funcFragments.unshift(`
        var stride = ${offset};
    `);
      const functionSource = funcFragments.join("\n");
      return new Function("ps", "f32v", "u32v", functionSource);
    }

    "use strict";
    class ParticleBuffer {
      constructor(options) {
        this._size = 0;
        this._generateParticleUpdateCache = {};
        var _a;
        const size = this._size = (_a = options.size) != null ? _a : 1e3;
        const properties = options.properties;
        let staticVertexSize = 0;
        let dynamicVertexSize = 0;
        for (const i in properties) {
          const property = properties[i];
          const attributeInfo = getAttributeInfoFromFormat(property.format);
          if (property.dynamic) {
            dynamicVertexSize += attributeInfo.stride;
          } else {
            staticVertexSize += attributeInfo.stride;
          }
        }
        this._dynamicStride = dynamicVertexSize / 4;
        this._staticStride = staticVertexSize / 4;
        this.staticAttributeBuffer = new ViewableBuffer(size * 4 * staticVertexSize);
        this.dynamicAttributeBuffer = new ViewableBuffer(size * 4 * dynamicVertexSize);
        this.indexBuffer = createIndicesForQuads(size);
        const geometry = new Geometry();
        let dynamicOffset = 0;
        let staticOffset = 0;
        this._staticBuffer = new Buffer({
          data: new Float32Array(1),
          label: "static-particle-buffer",
          shrinkToFit: false,
          usage: BufferUsage.VERTEX | BufferUsage.COPY_DST
        });
        this._dynamicBuffer = new Buffer({
          data: new Float32Array(1),
          label: "dynamic-particle-buffer",
          shrinkToFit: false,
          usage: BufferUsage.VERTEX | BufferUsage.COPY_DST
        });
        for (const i in properties) {
          const property = properties[i];
          const attributeInfo = getAttributeInfoFromFormat(property.format);
          if (property.dynamic) {
            geometry.addAttribute(property.attributeName, {
              buffer: this._dynamicBuffer,
              stride: this._dynamicStride * 4,
              offset: dynamicOffset * 4,
              format: property.format
            });
            dynamicOffset += attributeInfo.size;
          } else {
            geometry.addAttribute(property.attributeName, {
              buffer: this._staticBuffer,
              stride: this._staticStride * 4,
              offset: staticOffset * 4,
              format: property.format
            });
            staticOffset += attributeInfo.size;
          }
        }
        geometry.addIndex(this.indexBuffer);
        const uploadFunction = this.getParticleUpdate(properties);
        this._dynamicUpload = uploadFunction.dynamicUpdate;
        this._staticUpload = uploadFunction.staticUpdate;
        this.geometry = geometry;
      }
      getParticleUpdate(properties) {
        const key = getParticleSyncKey(properties);
        if (this._generateParticleUpdateCache[key]) {
          return this._generateParticleUpdateCache[key];
        }
        this._generateParticleUpdateCache[key] = this.generateParticleUpdate(properties);
        return this._generateParticleUpdateCache[key];
      }
      generateParticleUpdate(properties) {
        return generateParticleUpdateFunction(properties);
      }
      update(particles, uploadStatic) {
        if (particles.length > this._size) {
          uploadStatic = true;
          this._size = Math.max(particles.length, this._size * 1.5 | 0);
          this.staticAttributeBuffer = new ViewableBuffer(this._size * this._staticStride * 4 * 4);
          this.dynamicAttributeBuffer = new ViewableBuffer(this._size * this._dynamicStride * 4 * 4);
          this.indexBuffer = createIndicesForQuads(this._size);
          this.geometry.indexBuffer.setDataWithSize(
            this.indexBuffer,
            this.indexBuffer.byteLength,
            true
          );
        }
        const dynamicAttributeBuffer = this.dynamicAttributeBuffer;
        this._dynamicUpload(particles, dynamicAttributeBuffer.float32View, dynamicAttributeBuffer.uint32View);
        this._dynamicBuffer.setDataWithSize(
          this.dynamicAttributeBuffer.float32View,
          particles.length * this._dynamicStride * 4,
          true
        );
        if (uploadStatic) {
          const staticAttributeBuffer = this.staticAttributeBuffer;
          this._staticUpload(particles, staticAttributeBuffer.float32View, staticAttributeBuffer.uint32View);
          this._staticBuffer.setDataWithSize(
            staticAttributeBuffer.float32View,
            particles.length * this._staticStride * 4,
            true
          );
        }
      }
      destroy() {
        this._staticBuffer.destroy();
        this._dynamicBuffer.destroy();
        this.geometry.destroy();
      }
    }
    function getParticleSyncKey(properties) {
      const keyGen = [];
      for (const key in properties) {
        const property = properties[key];
        keyGen.push(key, property.code, property.dynamic ? "d" : "s");
      }
      return keyGen.join("_");
    }

    var fragment$6 = "varying vec2 vUV;\nvarying vec4 vColor;\n\nuniform sampler2D uTexture;\n\nvoid main(void){\n    vec4 color = texture2D(uTexture, vUV) * vColor;\n    gl_FragColor = color;\n}";

    var vertex$3 = "attribute vec2 aVertex;\nattribute vec2 aUV;\nattribute vec4 aColor;\n\nattribute vec2 aPosition;\nattribute float aRotation;\n\nuniform mat3 uTranslationMatrix;\nuniform float uRound;\nuniform vec2 uResolution;\nuniform vec4 uColor;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\n\nvec2 roundPixels(vec2 position, vec2 targetSize)\n{       \n    return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;\n}\n\nvoid main(void){\n    float cosRotation = cos(aRotation);\n    float sinRotation = sin(aRotation);\n    float x = aVertex.x * cosRotation - aVertex.y * sinRotation;\n    float y = aVertex.x * sinRotation + aVertex.y * cosRotation;\n\n    vec2 v = vec2(x, y);\n    v = v + aPosition;\n\n    gl_Position = vec4((uTranslationMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);\n\n    if(uRound == 1.0)\n    {\n        gl_Position.xy = roundPixels(gl_Position.xy, uResolution);\n    }\n\n    vUV = aUV;\n    vColor = vec4(aColor.rgb * aColor.a, aColor.a) * uColor;\n}\n";

    var wgsl = "\nstruct ParticleUniforms {\n  uTranslationMatrix:mat3x3<f32>,\n  uColor:vec4<f32>,\n  uRound:f32,\n  uResolution:vec2<f32>,\n};\n\nfn roundPixels(position: vec2<f32>, targetSize: vec2<f32>) -> vec2<f32>\n{\n  return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;\n}\n\n@group(0) @binding(0) var<uniform> uniforms: ParticleUniforms;\n\n@group(1) @binding(0) var uTexture: texture_2d<f32>;\n@group(1) @binding(1) var uSampler : sampler;\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>,\n    @location(1) color : vec4<f32>,\n  };\n@vertex\nfn mainVertex(\n  @location(0) aVertex: vec2<f32>,\n  @location(1) aPosition: vec2<f32>,\n  @location(2) aUV: vec2<f32>,\n  @location(3) aColor: vec4<f32>,\n  @location(4) aRotation: f32,\n) -> VSOutput {\n  \n   let v = vec2(\n       aVertex.x * cos(aRotation) - aVertex.y * sin(aRotation),\n       aVertex.x * sin(aRotation) + aVertex.y * cos(aRotation)\n   ) + aPosition;\n\n   var position = vec4((uniforms.uTranslationMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);\n\n   if(uniforms.uRound == 1.0) {\n       position = vec4(roundPixels(position.xy, uniforms.uResolution), position.zw);\n   }\n\n    let vColor = vec4(aColor.rgb * aColor.a, aColor.a) * uniforms.uColor;\n\n  return VSOutput(\n   position,\n   aUV,\n   vColor,\n  );\n}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n  @location(1) color: vec4<f32>,\n  @builtin(position) position: vec4<f32>,\n) -> @location(0) vec4<f32> {\n\n    var sample = textureSample(uTexture, uSampler, uv) * color;\n   \n    return sample;\n}";

    "use strict";
    class ParticleShader extends Shader {
      constructor() {
        const glProgram = GlProgram.from({
          vertex: vertex$3,
          fragment: fragment$6
        });
        const gpuProgram = GpuProgram.from({
          fragment: {
            source: wgsl,
            entryPoint: "mainFragment"
          },
          vertex: {
            source: wgsl,
            entryPoint: "mainVertex"
          }
        });
        super({
          glProgram,
          gpuProgram,
          resources: {
            // this will be replaced with the texture from the particle container
            uTexture: Texture.WHITE.source,
            // this will be replaced with the texture style from the particle container
            uSampler: new TextureStyle({}),
            // this will be replaced with the local uniforms from the particle container
            uniforms: {
              uTranslationMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
              uColor: { value: new Color(16777215), type: "vec4<f32>" },
              uRound: { value: 1, type: "f32" },
              uResolution: { value: [0, 0], type: "vec2<f32>" }
            }
          }
        });
      }
    }

    "use strict";
    class ParticleContainerPipe {
      /**
       * @param renderer - The renderer this sprite batch works for.
       * @param adaptor
       */
      constructor(renderer, adaptor) {
        /** @internal */
        this.state = State.for2d();
        /** Local uniforms that are used for rendering particles. */
        this.localUniforms = new UniformGroup({
          uTranslationMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uColor: { value: new Float32Array(4), type: "vec4<f32>" },
          uRound: { value: 1, type: "f32" },
          uResolution: { value: [0, 0], type: "vec2<f32>" }
        });
        this.renderer = renderer;
        this.adaptor = adaptor;
        this.defaultShader = new ParticleShader();
        this.state = State.for2d();
        this._managedContainers = new GCManagedHash({ renderer, type: "renderable", name: "particleContainer" });
      }
      validateRenderable(_renderable) {
        return false;
      }
      addRenderable(renderable, instructionSet) {
        this.renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add(renderable);
      }
      getBuffers(renderable) {
        return renderable._gpuData[this.renderer.uid] || this._initBuffer(renderable);
      }
      _initBuffer(renderable) {
        renderable._gpuData[this.renderer.uid] = new ParticleBuffer({
          size: renderable.particleChildren.length,
          properties: renderable._properties
        });
        this._managedContainers.add(renderable);
        return renderable._gpuData[this.renderer.uid];
      }
      updateRenderable(_renderable) {
      }
      execute(container) {
        const children = container.particleChildren;
        if (children.length === 0) {
          return;
        }
        const renderer = this.renderer;
        const buffer = this.getBuffers(container);
        container.texture || (container.texture = children[0].texture);
        const state = this.state;
        buffer.update(children, container._childrenDirty);
        container._childrenDirty = false;
        state.blendMode = getAdjustedBlendModeBlend(container.blendMode, container.texture._source);
        const uniforms = this.localUniforms.uniforms;
        const transformationMatrix = uniforms.uTranslationMatrix;
        container.worldTransform.copyTo(transformationMatrix);
        transformationMatrix.prepend(renderer.globalUniforms.globalUniformData.projectionMatrix);
        uniforms.uResolution = renderer.globalUniforms.globalUniformData.resolution;
        uniforms.uRound = renderer._roundPixels | container._roundPixels;
        color32BitToUniform(
          container.groupColorAlpha,
          uniforms.uColor,
          0
        );
        this.adaptor.execute(this, container);
      }
      /** Destroys the ParticleRenderer. */
      destroy() {
        this._managedContainers.destroy();
        this.renderer = null;
        if (this.defaultShader) {
          this.defaultShader.destroy();
          this.defaultShader = null;
        }
      }
    }

    "use strict";
    class GlParticleContainerPipe extends ParticleContainerPipe {
      constructor(renderer) {
        super(renderer, new GlParticleContainerAdaptor());
      }
    }
    /** @ignore */
    GlParticleContainerPipe.extension = {
      type: [
        ExtensionType.WebGLPipes
      ],
      name: "particle"
    };

    "use strict";
    class GpuParticleContainerAdaptor {
      execute(particleContainerPipe, container) {
        const renderer = particleContainerPipe.renderer;
        const shader = container.shader || particleContainerPipe.defaultShader;
        shader.groups[0] = renderer.renderPipes.uniformBatch.getUniformBindGroup(particleContainerPipe.localUniforms, true);
        shader.groups[1] = renderer.texture.getTextureBindGroup(container.texture);
        const state = particleContainerPipe.state;
        const buffer = particleContainerPipe.getBuffers(container);
        renderer.encoder.draw({
          geometry: buffer.geometry,
          shader: container.shader || particleContainerPipe.defaultShader,
          state,
          size: container.particleChildren.length * 6
        });
      }
    }

    "use strict";
    class GpuParticleContainerPipe extends ParticleContainerPipe {
      constructor(renderer) {
        super(renderer, new GpuParticleContainerAdaptor());
      }
    }
    /** @ignore */
    GpuParticleContainerPipe.extension = {
      type: [
        ExtensionType.WebGPUPipes
      ],
      name: "particle"
    };

    "use strict";
    extensions.add(GlParticleContainerPipe);
    extensions.add(GpuParticleContainerPipe);

    "use strict";
    function updateTextBounds(batchableSprite, text) {
      const { texture, bounds } = batchableSprite;
      const padding = text._style._getFinalPadding();
      updateQuadBounds(bounds, text._anchor, texture);
      const paddingOffset = text._anchor._x * padding * 2;
      const paddingOffsetY = text._anchor._y * padding * 2;
      bounds.minX -= padding - paddingOffset;
      bounds.minY -= padding - paddingOffsetY;
      bounds.maxX -= padding - paddingOffset;
      bounds.maxY -= padding - paddingOffsetY;
    }

    "use strict";
    class BatchableSprite {
      constructor() {
        this.batcherName = "default";
        this.topology = "triangle-list";
        // batch specific..
        this.attributeSize = 4;
        this.indexSize = 6;
        this.packAsQuad = true;
        this.roundPixels = 0;
        this._attributeStart = 0;
        // location in the buffer
        this._batcher = null;
        this._batch = null;
      }
      get blendMode() {
        return this.renderable.groupBlendMode;
      }
      get color() {
        return this.renderable.groupColorAlpha;
      }
      reset() {
        this.renderable = null;
        this.texture = null;
        this._batcher = null;
        this._batch = null;
        this.bounds = null;
      }
      destroy() {
        this.reset();
      }
    }

    "use strict";
    class BatchableText extends BatchableSprite {
    }

    "use strict";
    class CanvasTextPipe {
      constructor(renderer) {
        this._renderer = renderer;
        renderer.runners.resolutionChange.add(this);
        this._managedTexts = new GCManagedHash({
          renderer,
          type: "renderable",
          onUnload: this.onTextUnload.bind(this),
          name: "canvasText"
        });
      }
      resolutionChange() {
        for (const key in this._managedTexts.items) {
          const text = this._managedTexts.items[key];
          if (text == null ? void 0 : text._autoResolution)
            text.onViewUpdate();
        }
      }
      validateRenderable(text) {
        const gpuText = this._getGpuText(text);
        const newKey = text.styleKey;
        if (gpuText.currentKey !== newKey)
          return true;
        return text._didTextUpdate;
      }
      addRenderable(text, instructionSet) {
        const batchableText = this._getGpuText(text);
        if (text._didTextUpdate) {
          const resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
          if (batchableText.currentKey !== text.styleKey || text.resolution !== resolution) {
            this._updateGpuText(text);
          }
          text._didTextUpdate = false;
          updateTextBounds(batchableText, text);
        }
        this._renderer.renderPipes.batch.addToBatch(batchableText, instructionSet);
      }
      updateRenderable(text) {
        const batchableText = this._getGpuText(text);
        batchableText._batcher.updateElement(batchableText);
      }
      _updateGpuText(text) {
        const batchableText = this._getGpuText(text);
        if (batchableText.texture) {
          this._renderer.canvasText.decreaseReferenceCount(batchableText.currentKey);
        }
        text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
        batchableText.texture = this._renderer.canvasText.getManagedTexture(text);
        batchableText.currentKey = text.styleKey;
      }
      _getGpuText(text) {
        return text._gpuData[this._renderer.uid] || this.initGpuText(text);
      }
      initGpuText(text) {
        const batchableText = new BatchableText();
        batchableText.currentKey = "--";
        batchableText.renderable = text;
        batchableText.transform = text.groupTransform;
        batchableText.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
        batchableText.roundPixels = this._renderer._roundPixels | text._roundPixels;
        text._gpuData[this._renderer.uid] = batchableText;
        this._managedTexts.add(text);
        return batchableText;
      }
      onTextUnload(text) {
        const gpuData = text._gpuData[this._renderer.uid];
        if (!gpuData)
          return;
        const { canvasText } = this._renderer;
        const refCount = canvasText.getReferenceCount(gpuData.currentKey);
        if (refCount > 0) {
          canvasText.decreaseReferenceCount(gpuData.currentKey);
        } else if (gpuData.texture) {
          canvasText.returnTexture(gpuData.texture);
        }
      }
      destroy() {
        this._managedTexts.destroy();
        this._renderer = null;
      }
    }
    /** @ignore */
    CanvasTextPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "text"
    };

    "use strict";
    const repetitionMap = {
      repeat: {
        addressModeU: "repeat",
        addressModeV: "repeat"
      },
      "repeat-x": {
        addressModeU: "repeat",
        addressModeV: "clamp-to-edge"
      },
      "repeat-y": {
        addressModeU: "clamp-to-edge",
        addressModeV: "repeat"
      },
      "no-repeat": {
        addressModeU: "clamp-to-edge",
        addressModeV: "clamp-to-edge"
      }
    };
    class FillPattern {
      constructor(texture, repetition) {
        /**
         * unique id for this fill pattern
         * @internal
         */
        this.uid = uid$1("fillPattern");
        /**
         * Internal tick counter to track changes in the pattern.
         * This is used to invalidate the pattern when the texture or transform changes.
         * @internal
         */
        this._tick = 0;
        /** The transform matrix applied to the pattern */
        this.transform = new Matrix();
        this.texture = texture;
        this.transform.scale(
          1 / texture.frame.width,
          1 / texture.frame.height
        );
        if (repetition) {
          texture.source.style.addressModeU = repetitionMap[repetition].addressModeU;
          texture.source.style.addressModeV = repetitionMap[repetition].addressModeV;
        }
      }
      /**
       * Sets the transform for the pattern
       * @param transform - The transform matrix to apply to the pattern.
       * If not provided, the pattern will use the default transform.
       */
      setTransform(transform) {
        const texture = this.texture;
        this.transform.copyFrom(transform);
        this.transform.invert();
        this.transform.scale(
          1 / texture.frame.width,
          1 / texture.frame.height
        );
        this._tick++;
      }
      /** Internal texture used to render the gradient */
      get texture() {
        return this._texture;
      }
      set texture(value) {
        if (this._texture === value)
          return;
        this._texture = value;
        this._tick++;
      }
      /**
       * Returns a unique key for this instance.
       * This key is used for caching.
       * @returns {string} Unique key for the instance
       */
      get styleKey() {
        return `fill-pattern-${this.uid}-${this._tick}`;
      }
      /** Destroys the fill pattern, releasing resources. This will also destroy the internal texture. */
      destroy() {
        this.texture.destroy(true);
        this.texture = null;
      }
    }

    var parseSvgPath = parse;

    /**
     * expected argument lengths
     * @type {Object}
     */

    var length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0};

    /**
     * segment pattern
     * @type {RegExp}
     */

    var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig;

    /**
     * parse an svg path data string. Generates an Array
     * of commands where each command is an Array of the
     * form `[command, arg1, arg2, ...]`
     *
     * @param {String} path
     * @return {Array}
     */

    function parse(path) {
    	var data = [];
    	path.replace(segment, function(_, command, args){
    		var type = command.toLowerCase();
    		args = parseValues(args);

    		// overloaded moveTo
    		if (type == 'm' && args.length > 2) {
    			data.push([command].concat(args.splice(0, 2)));
    			type = 'l';
    			command = command == 'm' ? 'l' : 'L';
    		}

    		while (true) {
    			if (args.length == length[type]) {
    				args.unshift(command);
    				return data.push(args)
    			}
    			if (args.length < length[type]) throw new Error('malformed path data')
    			data.push([command].concat(args.splice(0, length[type])));
    		}
    	});
    	return data
    }

    var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig;

    function parseValues(args) {
    	var numbers = args.match(number);
    	return numbers ? numbers.map(Number) : []
    }

    var parse$1 = /*@__PURE__*/getDefaultExportFromCjs(parseSvgPath);

    "use strict";
    function parseSVGPath(svgPath, path) {
      const commands = parse$1(svgPath);
      const subpaths = [];
      let currentSubPath = null;
      let lastX = 0;
      let lastY = 0;
      for (let i = 0; i < commands.length; i++) {
        const command = commands[i];
        const type = command[0];
        const data = command;
        switch (type) {
          case "M":
            lastX = data[1];
            lastY = data[2];
            path.moveTo(lastX, lastY);
            break;
          case "m":
            lastX += data[1];
            lastY += data[2];
            path.moveTo(lastX, lastY);
            break;
          case "H":
            lastX = data[1];
            path.lineTo(lastX, lastY);
            break;
          case "h":
            lastX += data[1];
            path.lineTo(lastX, lastY);
            break;
          case "V":
            lastY = data[1];
            path.lineTo(lastX, lastY);
            break;
          case "v":
            lastY += data[1];
            path.lineTo(lastX, lastY);
            break;
          case "L":
            lastX = data[1];
            lastY = data[2];
            path.lineTo(lastX, lastY);
            break;
          case "l":
            lastX += data[1];
            lastY += data[2];
            path.lineTo(lastX, lastY);
            break;
          case "C":
            lastX = data[5];
            lastY = data[6];
            path.bezierCurveTo(
              data[1],
              data[2],
              // First control point
              data[3],
              data[4],
              // Second control point
              lastX,
              lastY
              // End point
            );
            break;
          case "c":
            path.bezierCurveTo(
              lastX + data[1],
              lastY + data[2],
              // First control point
              lastX + data[3],
              lastY + data[4],
              // Second control point
              lastX + data[5],
              lastY + data[6]
              // End point
            );
            lastX += data[5];
            lastY += data[6];
            break;
          case "S":
            lastX = data[3];
            lastY = data[4];
            path.bezierCurveToShort(
              data[1],
              data[2],
              // Control point
              lastX,
              lastY
              // End point
            );
            break;
          case "s":
            path.bezierCurveToShort(
              lastX + data[1],
              lastY + data[2],
              // Control point
              lastX + data[3],
              lastY + data[4]
              // End point
            );
            lastX += data[3];
            lastY += data[4];
            break;
          case "Q":
            lastX = data[3];
            lastY = data[4];
            path.quadraticCurveTo(
              data[1],
              data[2],
              // Control point
              lastX,
              lastY
              // End point
            );
            break;
          case "q":
            path.quadraticCurveTo(
              lastX + data[1],
              lastY + data[2],
              // Control point
              lastX + data[3],
              lastY + data[4]
              // End point
            );
            lastX += data[3];
            lastY += data[4];
            break;
          case "T":
            lastX = data[1];
            lastY = data[2];
            path.quadraticCurveToShort(
              lastX,
              lastY
              // End point
            );
            break;
          case "t":
            lastX += data[1];
            lastY += data[2];
            path.quadraticCurveToShort(
              lastX,
              lastY
              // End point
            );
            break;
          case "A":
            lastX = data[6];
            lastY = data[7];
            path.arcToSvg(
              data[1],
              // rx
              data[2],
              // ry
              data[3],
              // x-axis-rotation
              data[4],
              // large-arc-flag
              data[5],
              // sweep-flag
              lastX,
              lastY
              // End point
            );
            break;
          case "a":
            lastX += data[6];
            lastY += data[7];
            path.arcToSvg(
              data[1],
              // rx
              data[2],
              // ry
              data[3],
              // x-axis-rotation
              data[4],
              // large-arc-flag
              data[5],
              // sweep-flag
              lastX,
              lastY
              // End point
            );
            break;
          case "Z":
          case "z":
            path.closePath();
            if (subpaths.length > 0) {
              currentSubPath = subpaths.pop();
              if (currentSubPath) {
                lastX = currentSubPath.startX;
                lastY = currentSubPath.startY;
              } else {
                lastX = 0;
                lastY = 0;
              }
            }
            currentSubPath = null;
            break;
          default:
            warn(`Unknown SVG path command: ${type}`);
        }
        if (type !== "Z" && type !== "z") {
          if (currentSubPath === null) {
            currentSubPath = { startX: lastX, startY: lastY };
            subpaths.push(currentSubPath);
          }
        }
      }
      return path;
    }

    "use strict";
    class Circle {
      /**
       * @param x - The X coordinate of the center of this circle
       * @param y - The Y coordinate of the center of this circle
       * @param radius - The radius of the circle
       */
      constructor(x = 0, y = 0, radius = 0) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks.
         * @example
         * ```ts
         * // Check shape type
         * const shape = new Circle(0, 0, 50);
         * console.log(shape.type); // 'circle'
         *
         * // Use in type guards
         * if (shape.type === 'circle') {
         *     console.log(shape.radius);
         * }
         * ```
         * @remarks
         * - Used for shape type checking
         * - More efficient than instanceof
         * - Read-only property
         * @readonly
         * @default 'circle'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         * @see {@link ShapePrimitive} For shape interface
         */
        this.type = "circle";
        this.x = x;
        this.y = y;
        this.radius = radius;
      }
      /**
       * Creates a clone of this Circle instance.
       * @example
       * ```ts
       * // Basic circle cloning
       * const original = new Circle(100, 100, 50);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.radius = 75;
       *
       * // Verify independence
       * console.log(original.radius); // 50
       * console.log(modified.radius); // 75
       * ```
       * @returns A copy of the Circle
       * @see {@link Circle.copyFrom} For copying into existing circle
       * @see {@link Circle.copyTo} For copying to another circle
       */
      clone() {
        return new Circle(this.x, this.y, this.radius);
      }
      /**
       * Checks whether the x and y coordinates given are contained within this circle.
       *
       * Uses the distance formula to determine if a point is inside the circle's radius.
       *
       * Commonly used for hit testing in PixiJS events and graphics.
       * @example
       * ```ts
       * // Basic containment check
       * const circle = new Circle(100, 100, 50);
       * const isInside = circle.contains(120, 120);
       *
       * // Check mouse position
       * const circle = new Circle(0, 0, 100);
       * container.hitArea = circle;
       * container.on('pointermove', (e) => {
       *     // only called if pointer is within circle
       * });
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coordinates are within this Circle
       * @see {@link Circle.strokeContains} For checking stroke intersection
       * @see {@link Circle.getBounds} For getting bounding box
       */
      contains(x, y) {
        if (this.radius <= 0)
          return false;
        const r2 = this.radius * this.radius;
        let dx = this.x - x;
        let dy = this.y - y;
        dx *= dx;
        dy *= dy;
        return dx + dy <= r2;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this circle including the stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const circle = new Circle(100, 100, 50);
       * const isOnStroke = circle.strokeContains(150, 100, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = circle.strokeContains(150, 100, 4, 1);   // Inside
       * const centerStroke = circle.strokeContains(150, 100, 4, 0.5); // Centered
       * const outerStroke = circle.strokeContains(150, 100, 4, 0);   // Outside
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @param width - The width of the line to check
       * @param alignment - The alignment of the stroke, 0.5 by default
       * @returns Whether the x/y coordinates are within this Circle's stroke
       * @see {@link Circle.contains} For checking fill containment
       * @see {@link Circle.getBounds} For getting stroke bounds
       */
      strokeContains(x, y, width, alignment = 0.5) {
        if (this.radius === 0)
          return false;
        const dx = this.x - x;
        const dy = this.y - y;
        const radius = this.radius;
        const outerWidth = (1 - alignment) * width;
        const distance = Math.sqrt(dx * dx + dy * dy);
        return distance <= radius + outerWidth && distance > radius - (width - outerWidth);
      }
      /**
       * Returns the framing rectangle of the circle as a Rectangle object.
       * @example
       * ```ts
       * // Basic bounds calculation
       * const circle = new Circle(100, 100, 50);
       * const bounds = circle.getBounds();
       * // bounds: x=50, y=50, width=100, height=100
       *
       * // Reuse existing rectangle
       * const rect = new Rectangle();
       * circle.getBounds(rect);
       * ```
       * @param out - Optional Rectangle object to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle} For rectangle properties
       * @see {@link Circle.contains} For point containment
       */
      getBounds(out) {
        out || (out = new Rectangle());
        out.x = this.x - this.radius;
        out.y = this.y - this.radius;
        out.width = this.radius * 2;
        out.height = this.radius * 2;
        return out;
      }
      /**
       * Copies another circle to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Circle(100, 100, 50);
       * const target = new Circle();
       * target.copyFrom(source);
       * ```
       * @param circle - The circle to copy from
       * @returns Returns itself
       * @see {@link Circle.copyTo} For copying to another circle
       * @see {@link Circle.clone} For creating new circle copy
       */
      copyFrom(circle) {
        this.x = circle.x;
        this.y = circle.y;
        this.radius = circle.radius;
        return this;
      }
      /**
       * Copies this circle to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Circle(100, 100, 50);
       * const target = new Circle();
       * source.copyTo(target);
       * ```
       * @param circle - The circle to copy to
       * @returns Returns given parameter
       * @see {@link Circle.copyFrom} For copying from another circle
       * @see {@link Circle.clone} For creating new circle copy
       */
      copyTo(circle) {
        circle.copyFrom(this);
        return circle;
      }
      toString() {
        return `[pixi.js/math:Circle x=${this.x} y=${this.y} radius=${this.radius}]`;
      }
    }

    "use strict";
    class Ellipse {
      /**
       * @param x - The X coordinate of the center of this ellipse
       * @param y - The Y coordinate of the center of this ellipse
       * @param halfWidth - The half width of this ellipse
       * @param halfHeight - The half height of this ellipse
       */
      constructor(x = 0, y = 0, halfWidth = 0, halfHeight = 0) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks
         * @example
         * ```ts
         * // Check shape type
         * const shape = new Ellipse(0, 0, 50, 25);
         * console.log(shape.type); // 'ellipse'
         *
         * // Use in type guards
         * if (shape.type === 'ellipse') {
         *     console.log(shape.halfWidth, shape.halfHeight);
         * }
         * ```
         * @readonly
         * @default 'ellipse'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         */
        this.type = "ellipse";
        this.x = x;
        this.y = y;
        this.halfWidth = halfWidth;
        this.halfHeight = halfHeight;
      }
      /**
       * Creates a clone of this Ellipse instance.
       * @example
       * ```ts
       * // Basic cloning
       * const original = new Ellipse(100, 100, 50, 25);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.halfWidth *= 2;
       * modified.halfHeight *= 2;
       *
       * // Verify independence
       * console.log(original.halfWidth);  // 50
       * console.log(modified.halfWidth);  // 100
       * ```
       * @returns A copy of the ellipse
       * @see {@link Ellipse.copyFrom} For copying into existing ellipse
       * @see {@link Ellipse.copyTo} For copying to another ellipse
       */
      clone() {
        return new Ellipse(this.x, this.y, this.halfWidth, this.halfHeight);
      }
      /**
       * Checks whether the x and y coordinates given are contained within this ellipse.
       * Uses normalized coordinates and the ellipse equation to determine containment.
       * @example
       * ```ts
       * // Basic containment check
       * const ellipse = new Ellipse(100, 100, 50, 25);
       * const isInside = ellipse.contains(120, 110);
       * ```
       * @remarks
       * - Uses ellipse equation (x²/a² + y²/b² ≤ 1)
       * - Returns false if dimensions are 0 or negative
       * - Normalized to center (0,0) for calculation
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coords are within this ellipse
       * @see {@link Ellipse.strokeContains} For checking stroke intersection
       * @see {@link Ellipse.getBounds} For getting containing rectangle
       */
      contains(x, y) {
        if (this.halfWidth <= 0 || this.halfHeight <= 0) {
          return false;
        }
        let normx = (x - this.x) / this.halfWidth;
        let normy = (y - this.y) / this.halfHeight;
        normx *= normx;
        normy *= normy;
        return normx + normy <= 1;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this ellipse including stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const ellipse = new Ellipse(100, 100, 50, 25);
       * const isOnStroke = ellipse.strokeContains(150, 100, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = ellipse.strokeContains(150, 100, 4, 1);   // Inside
       * const centerStroke = ellipse.strokeContains(150, 100, 4, 0.5); // Centered
       * const outerStroke = ellipse.strokeContains(150, 100, 4, 0);   // Outside
       * ```
       * @remarks
       * - Uses normalized ellipse equations
       * - Considers stroke alignment
       * - Returns false if dimensions are 0
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @param strokeWidth - The width of the line to check
       * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
       * @returns Whether the x/y coords are within this ellipse's stroke
       * @see {@link Ellipse.contains} For checking fill containment
       * @see {@link Ellipse.getBounds} For getting stroke bounds
       */
      strokeContains(x, y, strokeWidth, alignment = 0.5) {
        const { halfWidth, halfHeight } = this;
        if (halfWidth <= 0 || halfHeight <= 0) {
          return false;
        }
        const strokeOuterWidth = strokeWidth * (1 - alignment);
        const strokeInnerWidth = strokeWidth - strokeOuterWidth;
        const innerHorizontal = halfWidth - strokeInnerWidth;
        const innerVertical = halfHeight - strokeInnerWidth;
        const outerHorizontal = halfWidth + strokeOuterWidth;
        const outerVertical = halfHeight + strokeOuterWidth;
        const normalizedX = x - this.x;
        const normalizedY = y - this.y;
        const innerEllipse = normalizedX * normalizedX / (innerHorizontal * innerHorizontal) + normalizedY * normalizedY / (innerVertical * innerVertical);
        const outerEllipse = normalizedX * normalizedX / (outerHorizontal * outerHorizontal) + normalizedY * normalizedY / (outerVertical * outerVertical);
        return innerEllipse > 1 && outerEllipse <= 1;
      }
      /**
       * Returns the framing rectangle of the ellipse as a Rectangle object.
       * @example
       * ```ts
       * // Basic bounds calculation
       * const ellipse = new Ellipse(100, 100, 50, 25);
       * const bounds = ellipse.getBounds();
       * // bounds: x=50, y=75, width=100, height=50
       *
       * // Reuse existing rectangle
       * const rect = new Rectangle();
       * ellipse.getBounds(rect);
       * ```
       * @remarks
       * - Creates Rectangle if none provided
       * - Top-left is (x-halfWidth, y-halfHeight)
       * - Width is halfWidth * 2
       * - Height is halfHeight * 2
       * @param out - Optional Rectangle object to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle} For rectangle properties
       * @see {@link Ellipse.contains} For checking if a point is inside
       */
      getBounds(out) {
        out || (out = new Rectangle());
        out.x = this.x - this.halfWidth;
        out.y = this.y - this.halfHeight;
        out.width = this.halfWidth * 2;
        out.height = this.halfHeight * 2;
        return out;
      }
      /**
       * Copies another ellipse to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Ellipse(100, 100, 50, 25);
       * const target = new Ellipse();
       * target.copyFrom(source);
       * ```
       * @param ellipse - The ellipse to copy from
       * @returns Returns itself
       * @see {@link Ellipse.copyTo} For copying to another ellipse
       * @see {@link Ellipse.clone} For creating new ellipse copy
       */
      copyFrom(ellipse) {
        this.x = ellipse.x;
        this.y = ellipse.y;
        this.halfWidth = ellipse.halfWidth;
        this.halfHeight = ellipse.halfHeight;
        return this;
      }
      /**
       * Copies this ellipse to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Ellipse(100, 100, 50, 25);
       * const target = new Ellipse();
       * source.copyTo(target);
       * ```
       * @param ellipse - The ellipse to copy to
       * @returns Returns given parameter
       * @see {@link Ellipse.copyFrom} For copying from another ellipse
       * @see {@link Ellipse.clone} For creating new ellipse copy
       */
      copyTo(ellipse) {
        ellipse.copyFrom(this);
        return ellipse;
      }
      toString() {
        return `[pixi.js/math:Ellipse x=${this.x} y=${this.y} halfWidth=${this.halfWidth} halfHeight=${this.halfHeight}]`;
      }
    }

    "use strict";
    function squaredDistanceToLineSegment(x, y, x1, y1, x2, y2) {
      const a = x - x1;
      const b = y - y1;
      const c = x2 - x1;
      const d = y2 - y1;
      const dot = a * c + b * d;
      const lenSq = c * c + d * d;
      let param = -1;
      if (lenSq !== 0) {
        param = dot / lenSq;
      }
      let xx;
      let yy;
      if (param < 0) {
        xx = x1;
        yy = y1;
      } else if (param > 1) {
        xx = x2;
        yy = y2;
      } else {
        xx = x1 + param * c;
        yy = y1 + param * d;
      }
      const dx = x - xx;
      const dy = y - yy;
      return dx * dx + dy * dy;
    }

    "use strict";
    let tempRect$2;
    let tempRect2;
    class Polygon {
      /**
       * @param points - This can be an array of Points
       *  that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...], or
       *  the arguments passed can be all the points of the polygon e.g.
       *  `new Polygon(new Point(), new Point(), ...)`, or the arguments passed can be flat
       *  x,y values e.g. `new Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are Numbers.
       */
      constructor(...points) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks
         * @example
         * ```ts
         * // Check shape type
         * const shape = new Polygon([0, 0, 100, 0, 50, 100]);
         * console.log(shape.type); // 'polygon'
         *
         * // Use in type guards
         * if (shape.type === 'polygon') {
         *     // TypeScript knows this is a Polygon
         *     console.log(shape.points.length);
         * }
         * ```
         * @readonly
         * @default 'polygon'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         */
        this.type = "polygon";
        let flat = Array.isArray(points[0]) ? points[0] : points;
        if (typeof flat[0] !== "number") {
          const p = [];
          for (let i = 0, il = flat.length; i < il; i++) {
            p.push(flat[i].x, flat[i].y);
          }
          flat = p;
        }
        this.points = flat;
        this.closePath = true;
      }
      /**
       * Determines whether the polygon's points are arranged in a clockwise direction.
       * Uses the shoelace formula (surveyor's formula) to calculate the signed area.
       *
       * A positive area indicates clockwise winding, while negative indicates counter-clockwise.
       *
       * The formula sums up the cross products of adjacent vertices:
       * For each pair of adjacent points (x1,y1) and (x2,y2), we calculate (x1*y2 - x2*y1)
       * The final sum divided by 2 gives the signed area - positive for clockwise.
       * @example
       * ```ts
       * // Check polygon winding
       * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
       * console.log(polygon.isClockwise()); // Check direction
       *
       * // Use in path construction
       * const hole = new Polygon([25, 25, 75, 25, 75, 75, 25, 75]);
       * if (hole.isClockwise() === shape.isClockwise()) {
       *     hole.points.reverse(); // Reverse for proper hole winding
       * }
       * ```
       * @returns `true` if the polygon's points are arranged clockwise, `false` if counter-clockwise
       */
      isClockwise() {
        let area = 0;
        const points = this.points;
        const length = points.length;
        for (let i = 0; i < length; i += 2) {
          const x1 = points[i];
          const y1 = points[i + 1];
          const x2 = points[(i + 2) % length];
          const y2 = points[(i + 3) % length];
          area += (x2 - x1) * (y2 + y1);
        }
        return area < 0;
      }
      /**
       * Checks if this polygon completely contains another polygon.
       * Used for detecting holes in shapes, like when parsing SVG paths.
       * @example
       * ```ts
       * // Basic containment check
       * const outerSquare = new Polygon([0,0, 100,0, 100,100, 0,100]); // A square
       * const innerSquare = new Polygon([25,25, 75,25, 75,75, 25,75]); // A smaller square inside
       *
       * outerSquare.containsPolygon(innerSquare); // Returns true
       * innerSquare.containsPolygon(outerSquare); // Returns false
       * ```
       * @remarks
       * - Uses bounds check for quick rejection
       * - Tests all points for containment
       * @param polygon - The polygon to test for containment
       * @returns True if this polygon completely contains the other polygon
       * @see {@link Polygon.contains} For single point testing
       * @see {@link Polygon.getBounds} For bounds calculation
       */
      containsPolygon(polygon) {
        const thisBounds = this.getBounds(tempRect$2);
        const otherBounds = polygon.getBounds(tempRect2);
        if (!thisBounds.containsRect(otherBounds)) {
          return false;
        }
        const points = polygon.points;
        for (let i = 0; i < points.length; i += 2) {
          const x = points[i];
          const y = points[i + 1];
          if (!this.contains(x, y)) {
            return false;
          }
        }
        return true;
      }
      /**
       * Creates a clone of this polygon.
       * @example
       * ```ts
       * // Basic cloning
       * const original = new Polygon([0, 0, 100, 0, 50, 100]);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.points[0] = 10; // Modify first x coordinate
       * ```
       * @returns A copy of the polygon
       * @see {@link Polygon.copyFrom} For copying into existing polygon
       * @see {@link Polygon.copyTo} For copying to another polygon
       */
      clone() {
        const points = this.points.slice();
        const polygon = new Polygon(points);
        polygon.closePath = this.closePath;
        return polygon;
      }
      /**
       * Checks whether the x and y coordinates passed to this function are contained within this polygon.
       * Uses raycasting algorithm for point-in-polygon testing.
       * @example
       * ```ts
       * // Basic containment check
       * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
       * const isInside = polygon.contains(25, 25); // true
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coordinates are within this polygon
       * @see {@link Polygon.strokeContains} For checking stroke intersection
       * @see {@link Polygon.containsPolygon} For polygon-in-polygon testing
       */
      contains(x, y) {
        let inside = false;
        const length = this.points.length / 2;
        for (let i = 0, j = length - 1; i < length; j = i++) {
          const xi = this.points[i * 2];
          const yi = this.points[i * 2 + 1];
          const xj = this.points[j * 2];
          const yj = this.points[j * 2 + 1];
          const intersect = yi > y !== yj > y && x < (xj - xi) * ((y - yi) / (yj - yi)) + xi;
          if (intersect) {
            inside = !inside;
          }
        }
        return inside;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this polygon including the stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
       * const isOnStroke = polygon.strokeContains(25, 25, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = polygon.strokeContains(25, 25, 4, 1);   // Inside
       * const centerStroke = polygon.strokeContains(25, 25, 4, 0.5); // Centered
       * const outerStroke = polygon.strokeContains(25, 25, 4, 0);   // Outside
       * ```
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @param strokeWidth - The width of the line to check
       * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
       * @returns Whether the x/y coordinates are within this polygon's stroke
       * @see {@link Polygon.contains} For checking fill containment
       * @see {@link Polygon.getBounds} For getting stroke bounds
       */
      strokeContains(x, y, strokeWidth, alignment = 0.5) {
        const strokeWidthSquared = strokeWidth * strokeWidth;
        const rightWidthSquared = strokeWidthSquared * (1 - alignment);
        const leftWidthSquared = strokeWidthSquared - rightWidthSquared;
        const { points } = this;
        const iterationLength = points.length - (this.closePath ? 0 : 2);
        for (let i = 0; i < iterationLength; i += 2) {
          const x1 = points[i];
          const y1 = points[i + 1];
          const x2 = points[(i + 2) % points.length];
          const y2 = points[(i + 3) % points.length];
          const distanceSquared = squaredDistanceToLineSegment(x, y, x1, y1, x2, y2);
          const sign = Math.sign((x2 - x1) * (y - y1) - (y2 - y1) * (x - x1));
          if (distanceSquared <= (sign < 0 ? leftWidthSquared : rightWidthSquared)) {
            return true;
          }
        }
        return false;
      }
      /**
       * Returns the framing rectangle of the polygon as a Rectangle object.
       * @example
       * ```ts
       * // Basic bounds calculation
       * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);
       * const bounds = polygon.getBounds();
       * // bounds: x=0, y=0, width=100, height=100
       *
       * // Reuse existing rectangle
       * const rect = new Rectangle();
       * polygon.getBounds(rect);
       * ```
       * @param out - Optional rectangle to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle} For rectangle properties
       * @see {@link Polygon.contains} For checking if a point is inside
       */
      getBounds(out) {
        out || (out = new Rectangle());
        const points = this.points;
        let minX = Infinity;
        let maxX = -Infinity;
        let minY = Infinity;
        let maxY = -Infinity;
        for (let i = 0, n = points.length; i < n; i += 2) {
          const x = points[i];
          const y = points[i + 1];
          minX = x < minX ? x : minX;
          maxX = x > maxX ? x : maxX;
          minY = y < minY ? y : minY;
          maxY = y > maxY ? y : maxY;
        }
        out.x = minX;
        out.width = maxX - minX;
        out.y = minY;
        out.height = maxY - minY;
        return out;
      }
      /**
       * Copies another polygon to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Polygon([0, 0, 100, 0, 50, 100]);
       * const target = new Polygon();
       * target.copyFrom(source);
       * ```
       * @param polygon - The polygon to copy from
       * @returns Returns itself
       * @see {@link Polygon.copyTo} For copying to another polygon
       * @see {@link Polygon.clone} For creating new polygon copy
       */
      copyFrom(polygon) {
        this.points = polygon.points.slice();
        this.closePath = polygon.closePath;
        return this;
      }
      /**
       * Copies this polygon to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Polygon([0, 0, 100, 0, 50, 100]);
       * const target = new Polygon();
       * source.copyTo(target);
       * ```
       * @param polygon - The polygon to copy to
       * @returns Returns given parameter
       * @see {@link Polygon.copyFrom} For copying from another polygon
       * @see {@link Polygon.clone} For creating new polygon copy
       */
      copyTo(polygon) {
        polygon.copyFrom(this);
        return polygon;
      }
      toString() {
        return `[pixi.js/math:PolygoncloseStroke=${this.closePath}points=${this.points.reduce((pointsDesc, currentPoint) => `${pointsDesc}, ${currentPoint}`, "")}]`;
      }
      /**
       * Get the last X coordinate of the polygon.
       * @example
       * ```ts
       * // Basic coordinate access
       * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
       * console.log(polygon.lastX); // 300
       * ```
       * @readonly
       * @returns The x-coordinate of the last vertex
       * @see {@link Polygon.lastY} For last Y coordinate
       * @see {@link Polygon.points} For raw points array
       */
      get lastX() {
        return this.points[this.points.length - 2];
      }
      /**
       * Get the last Y coordinate of the polygon.
       * @example
       * ```ts
       * // Basic coordinate access
       * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
       * console.log(polygon.lastY); // 400
       * ```
       * @readonly
       * @returns The y-coordinate of the last vertex
       * @see {@link Polygon.lastX} For last X coordinate
       * @see {@link Polygon.points} For raw points array
       */
      get lastY() {
        return this.points[this.points.length - 1];
      }
      /**
       * Get the last X coordinate of the polygon.
       * @readonly
       * @deprecated since 8.11.0, use {@link Polygon.lastX} instead.
       */
      get x() {
        deprecation("8.11.0", "Polygon.lastX is deprecated, please use Polygon.lastX instead.");
        return this.points[this.points.length - 2];
      }
      /**
       * Get the last Y coordinate of the polygon.
       * @readonly
       * @deprecated since 8.11.0, use {@link Polygon.lastY} instead.
       */
      get y() {
        deprecation("8.11.0", "Polygon.y is deprecated, please use Polygon.lastY instead.");
        return this.points[this.points.length - 1];
      }
      /**
       * Get the first X coordinate of the polygon.
       * @example
       * ```ts
       * // Basic coordinate access
       * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
       * console.log(polygon.x); // 0
       * ```
       * @readonly
       * @returns The x-coordinate of the first vertex
       * @see {@link Polygon.startY} For first Y coordinate
       * @see {@link Polygon.points} For raw points array
       */
      get startX() {
        return this.points[0];
      }
      /**
       * Get the first Y coordinate of the polygon.
       * @example
       * ```ts
       * // Basic coordinate access
       * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);
       * console.log(polygon.y); // 0
       * ```
       * @readonly
       * @returns The y-coordinate of the first vertex
       * @see {@link Polygon.startX} For first X coordinate
       * @see {@link Polygon.points} For raw points array
       */
      get startY() {
        return this.points[1];
      }
    }

    "use strict";
    const isCornerWithinStroke = (pX, pY, cornerX, cornerY, radius, strokeWidthInner, strokeWidthOuter) => {
      const dx = pX - cornerX;
      const dy = pY - cornerY;
      const distance = Math.sqrt(dx * dx + dy * dy);
      return distance >= radius - strokeWidthInner && distance <= radius + strokeWidthOuter;
    };
    class RoundedRectangle {
      /**
       * @param x - The X coordinate of the upper-left corner of the rounded rectangle
       * @param y - The Y coordinate of the upper-left corner of the rounded rectangle
       * @param width - The overall width of this rounded rectangle
       * @param height - The overall height of this rounded rectangle
       * @param radius - Controls the radius of the rounded corners
       */
      constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks
         * @example
         * ```ts
         * // Check shape type
         * const shape = new RoundedRectangle(0, 0, 100, 100, 20);
         * console.log(shape.type); // 'roundedRectangle'
         *
         * // Use in type guards
         * if (shape.type === 'roundedRectangle') {
         *     console.log(shape.radius);
         * }
         * ```
         * @readonly
         * @default 'roundedRectangle'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         */
        this.type = "roundedRectangle";
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.radius = radius;
      }
      /**
       * Returns the framing rectangle of the rounded rectangle as a Rectangle object
       * @example
       * ```ts
       * // Basic bounds calculation
       * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
       * const bounds = rect.getBounds();
       * // bounds: x=100, y=100, width=200, height=150
       *
       * // Reuse existing rectangle
       * const out = new Rectangle();
       * rect.getBounds(out);
       * ```
       * @remarks
       * - Rectangle matches outer dimensions
       * - Ignores corner radius
       * @param out - Optional rectangle to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle} For rectangle properties
       * @see {@link RoundedRectangle.contains} For checking if a point is inside
       */
      getBounds(out) {
        out || (out = new Rectangle());
        out.x = this.x;
        out.y = this.y;
        out.width = this.width;
        out.height = this.height;
        return out;
      }
      /**
       * Creates a clone of this Rounded Rectangle.
       * @example
       * ```ts
       * // Basic cloning
       * const original = new RoundedRectangle(100, 100, 200, 150, 20);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.radius = 30;
       * modified.width *= 2;
       *
       * // Verify independence
       * console.log(original.radius);  // 20
       * console.log(modified.radius);  // 30
       * ```
       * @returns A copy of the rounded rectangle
       * @see {@link RoundedRectangle.copyFrom} For copying into existing rectangle
       * @see {@link RoundedRectangle.copyTo} For copying to another rectangle
       */
      clone() {
        return new RoundedRectangle(this.x, this.y, this.width, this.height, this.radius);
      }
      /**
       * Copies another rectangle to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new RoundedRectangle(100, 100, 200, 150, 20);
       * const target = new RoundedRectangle();
       * target.copyFrom(source);
       *
       * // Chain with other operations
       * const rect = new RoundedRectangle()
       *     .copyFrom(source)
       *     .getBounds(rect);
       * ```
       * @param rectangle - The rectangle to copy from
       * @returns Returns itself
       * @see {@link RoundedRectangle.copyTo} For copying to another rectangle
       * @see {@link RoundedRectangle.clone} For creating new rectangle copy
       */
      copyFrom(rectangle) {
        this.x = rectangle.x;
        this.y = rectangle.y;
        this.width = rectangle.width;
        this.height = rectangle.height;
        return this;
      }
      /**
       * Copies this rectangle to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new RoundedRectangle(100, 100, 200, 150, 20);
       * const target = new RoundedRectangle();
       * source.copyTo(target);
       *
       * // Chain with other operations
       * const result = source
       *     .copyTo(new RoundedRectangle())
       *     .getBounds();
       * ```
       * @param rectangle - The rectangle to copy to
       * @returns Returns given parameter
       * @see {@link RoundedRectangle.copyFrom} For copying from another rectangle
       * @see {@link RoundedRectangle.clone} For creating new rectangle copy
       */
      copyTo(rectangle) {
        rectangle.copyFrom(this);
        return rectangle;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this Rounded Rectangle
       * @example
       * ```ts
       * // Basic containment check
       * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
       * const isInside = rect.contains(150, 125); // true
       * // Check corner radius
       * const corner = rect.contains(100, 100); // false if within corner curve
       * ```
       * @remarks
       * - Returns false if width/height is 0 or negative
       * - Handles rounded corners with radius check
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coordinates are within this Rounded Rectangle
       * @see {@link RoundedRectangle.strokeContains} For checking stroke intersection
       * @see {@link RoundedRectangle.getBounds} For getting containing rectangle
       */
      contains(x, y) {
        if (this.width <= 0 || this.height <= 0) {
          return false;
        }
        if (x >= this.x && x <= this.x + this.width) {
          if (y >= this.y && y <= this.y + this.height) {
            const radius = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2));
            if (y >= this.y + radius && y <= this.y + this.height - radius || x >= this.x + radius && x <= this.x + this.width - radius) {
              return true;
            }
            let dx = x - (this.x + radius);
            let dy = y - (this.y + radius);
            const radius2 = radius * radius;
            if (dx * dx + dy * dy <= radius2) {
              return true;
            }
            dx = x - (this.x + this.width - radius);
            if (dx * dx + dy * dy <= radius2) {
              return true;
            }
            dy = y - (this.y + this.height - radius);
            if (dx * dx + dy * dy <= radius2) {
              return true;
            }
            dx = x - (this.x + radius);
            if (dx * dx + dy * dy <= radius2) {
              return true;
            }
          }
        }
        return false;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const rect = new RoundedRectangle(100, 100, 200, 150, 20);
       * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = rect.strokeContains(150, 100, 4, 1);   // Inside
       * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
       * const outerStroke = rect.strokeContains(150, 100, 4, 0);   // Outside
       * ```
       * @param pX - The X coordinate of the point to test
       * @param pY - The Y coordinate of the point to test
       * @param strokeWidth - The width of the line to check
       * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
       * @returns Whether the x/y coordinates are within this rectangle's stroke
       * @see {@link RoundedRectangle.contains} For checking fill containment
       * @see {@link RoundedRectangle.getBounds} For getting stroke bounds
       */
      strokeContains(pX, pY, strokeWidth, alignment = 0.5) {
        const { x, y, width, height, radius } = this;
        const strokeWidthOuter = strokeWidth * (1 - alignment);
        const strokeWidthInner = strokeWidth - strokeWidthOuter;
        const innerX = x + radius;
        const innerY = y + radius;
        const innerWidth = width - radius * 2;
        const innerHeight = height - radius * 2;
        const rightBound = x + width;
        const bottomBound = y + height;
        if ((pX >= x - strokeWidthOuter && pX <= x + strokeWidthInner || pX >= rightBound - strokeWidthInner && pX <= rightBound + strokeWidthOuter) && pY >= innerY && pY <= innerY + innerHeight) {
          return true;
        }
        if ((pY >= y - strokeWidthOuter && pY <= y + strokeWidthInner || pY >= bottomBound - strokeWidthInner && pY <= bottomBound + strokeWidthOuter) && pX >= innerX && pX <= innerX + innerWidth) {
          return true;
        }
        return (
          // Top-left
          pX < innerX && pY < innerY && isCornerWithinStroke(
            pX,
            pY,
            innerX,
            innerY,
            radius,
            strokeWidthInner,
            strokeWidthOuter
          ) || pX > rightBound - radius && pY < innerY && isCornerWithinStroke(
            pX,
            pY,
            rightBound - radius,
            innerY,
            radius,
            strokeWidthInner,
            strokeWidthOuter
          ) || pX > rightBound - radius && pY > bottomBound - radius && isCornerWithinStroke(
            pX,
            pY,
            rightBound - radius,
            bottomBound - radius,
            radius,
            strokeWidthInner,
            strokeWidthOuter
          ) || pX < innerX && pY > bottomBound - radius && isCornerWithinStroke(
            pX,
            pY,
            innerX,
            bottomBound - radius,
            radius,
            strokeWidthInner,
            strokeWidthOuter
          )
        );
      }
      toString() {
        return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`;
      }
    }

    "use strict";
    const RECURSION_LIMIT$1 = 8;
    const FLT_EPSILON$1 = 11920929e-14;
    const PATH_DISTANCE_EPSILON$1 = 1;
    const curveAngleToleranceEpsilon$1 = 0.01;
    const mAngleTolerance$1 = 0;
    const mCuspLimit = 0;
    function buildAdaptiveBezier(points, sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, smoothness) {
      const scale = 1;
      const smoothing = Math.min(
        0.99,
        // a value of 1.0 actually inverts smoothing, so we cap it at 0.99
        Math.max(0, smoothness != null ? smoothness : GraphicsContextSystem.defaultOptions.bezierSmoothness)
      );
      let distanceTolerance = (PATH_DISTANCE_EPSILON$1 - smoothing) / scale;
      distanceTolerance *= distanceTolerance;
      begin$1(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);
      return points;
    }
    function begin$1(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance) {
      recursive$1(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance, 0);
      points.push(eX, eY);
    }
    function recursive$1(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, level) {
      if (level > RECURSION_LIMIT$1) {
        return;
      }
      const pi = Math.PI;
      const x12 = (x1 + x2) / 2;
      const y12 = (y1 + y2) / 2;
      const x23 = (x2 + x3) / 2;
      const y23 = (y2 + y3) / 2;
      const x34 = (x3 + x4) / 2;
      const y34 = (y3 + y4) / 2;
      const x123 = (x12 + x23) / 2;
      const y123 = (y12 + y23) / 2;
      const x234 = (x23 + x34) / 2;
      const y234 = (y23 + y34) / 2;
      const x1234 = (x123 + x234) / 2;
      const y1234 = (y123 + y234) / 2;
      if (level > 0) {
        let dx = x4 - x1;
        let dy = y4 - y1;
        const d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx);
        const d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx);
        let da1;
        let da2;
        if (d2 > FLT_EPSILON$1 && d3 > FLT_EPSILON$1) {
          if ((d2 + d3) * (d2 + d3) <= distanceTolerance * (dx * dx + dy * dy)) {
            if (mAngleTolerance$1 < curveAngleToleranceEpsilon$1) {
              points.push(x1234, y1234);
              return;
            }
            const a23 = Math.atan2(y3 - y2, x3 - x2);
            da1 = Math.abs(a23 - Math.atan2(y2 - y1, x2 - x1));
            da2 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - a23);
            if (da1 >= pi)
              da1 = 2 * pi - da1;
            if (da2 >= pi)
              da2 = 2 * pi - da2;
            if (da1 + da2 < mAngleTolerance$1) {
              points.push(x1234, y1234);
              return;
            }
            if (mCuspLimit !== 0) {
              if (da1 > mCuspLimit) {
                points.push(x2, y2);
                return;
              }
              if (da2 > mCuspLimit) {
                points.push(x3, y3);
                return;
              }
            }
          }
        } else if (d2 > FLT_EPSILON$1) {
          if (d2 * d2 <= distanceTolerance * (dx * dx + dy * dy)) {
            if (mAngleTolerance$1 < curveAngleToleranceEpsilon$1) {
              points.push(x1234, y1234);
              return;
            }
            da1 = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
            if (da1 >= pi)
              da1 = 2 * pi - da1;
            if (da1 < mAngleTolerance$1) {
              points.push(x2, y2);
              points.push(x3, y3);
              return;
            }
            if (mCuspLimit !== 0) {
              if (da1 > mCuspLimit) {
                points.push(x2, y2);
                return;
              }
            }
          }
        } else if (d3 > FLT_EPSILON$1) {
          if (d3 * d3 <= distanceTolerance * (dx * dx + dy * dy)) {
            if (mAngleTolerance$1 < curveAngleToleranceEpsilon$1) {
              points.push(x1234, y1234);
              return;
            }
            da1 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y3 - y2, x3 - x2));
            if (da1 >= pi)
              da1 = 2 * pi - da1;
            if (da1 < mAngleTolerance$1) {
              points.push(x2, y2);
              points.push(x3, y3);
              return;
            }
            if (mCuspLimit !== 0) {
              if (da1 > mCuspLimit) {
                points.push(x3, y3);
                return;
              }
            }
          }
        } else {
          dx = x1234 - (x1 + x4) / 2;
          dy = y1234 - (y1 + y4) / 2;
          if (dx * dx + dy * dy <= distanceTolerance) {
            points.push(x1234, y1234);
            return;
          }
        }
      }
      recursive$1(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);
      recursive$1(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);
    }

    "use strict";
    const RECURSION_LIMIT = 8;
    const FLT_EPSILON = 11920929e-14;
    const PATH_DISTANCE_EPSILON = 1;
    const curveAngleToleranceEpsilon = 0.01;
    const mAngleTolerance = 0;
    function buildAdaptiveQuadratic(points, sX, sY, cp1x, cp1y, eX, eY, smoothness) {
      const scale = 1;
      const smoothing = Math.min(
        0.99,
        // a value of 1.0 actually inverts smoothing, so we cap it at 0.99
        Math.max(0, smoothness != null ? smoothness : GraphicsContextSystem.defaultOptions.bezierSmoothness)
      );
      let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
      distanceTolerance *= distanceTolerance;
      begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance);
      return points;
    }
    function begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance) {
      recursive(points, sX, sY, cp1x, cp1y, eX, eY, distanceTolerance, 0);
      points.push(eX, eY);
    }
    function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
      if (level > RECURSION_LIMIT) {
        return;
      }
      const pi = Math.PI;
      const x12 = (x1 + x2) / 2;
      const y12 = (y1 + y2) / 2;
      const x23 = (x2 + x3) / 2;
      const y23 = (y2 + y3) / 2;
      const x123 = (x12 + x23) / 2;
      const y123 = (y12 + y23) / 2;
      let dx = x3 - x1;
      let dy = y3 - y1;
      const d = Math.abs((x2 - x3) * dy - (y2 - y3) * dx);
      if (d > FLT_EPSILON) {
        if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
          if (mAngleTolerance < curveAngleToleranceEpsilon) {
            points.push(x123, y123);
            return;
          }
          let da = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
          if (da >= pi)
            da = 2 * pi - da;
          if (da < mAngleTolerance) {
            points.push(x123, y123);
            return;
          }
        }
      } else {
        dx = x123 - (x1 + x3) / 2;
        dy = y123 - (y1 + y3) / 2;
        if (dx * dx + dy * dy <= distanceTolerance) {
          points.push(x123, y123);
          return;
        }
      }
      recursive(points, x1, y1, x12, y12, x123, y123, distanceTolerance, level + 1);
      recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
    }

    "use strict";
    function buildArc(points, x, y, radius, start, end, clockwise, steps) {
      let dist = Math.abs(start - end);
      if (!clockwise && start > end) {
        dist = 2 * Math.PI - dist;
      } else if (clockwise && end > start) {
        dist = 2 * Math.PI - dist;
      }
      steps || (steps = Math.max(6, Math.floor(6 * Math.pow(radius, 1 / 3) * (dist / Math.PI))));
      steps = Math.max(steps, 3);
      let f = dist / steps;
      let t = start;
      f *= clockwise ? -1 : 1;
      for (let i = 0; i < steps + 1; i++) {
        const cs = Math.cos(t);
        const sn = Math.sin(t);
        const nx = x + cs * radius;
        const ny = y + sn * radius;
        points.push(nx, ny);
        t += f;
      }
    }

    "use strict";
    function buildArcTo(points, x1, y1, x2, y2, radius) {
      const fromX = points[points.length - 2];
      const fromY = points[points.length - 1];
      const a1 = fromY - y1;
      const b1 = fromX - x1;
      const a2 = y2 - y1;
      const b2 = x2 - x1;
      const mm = Math.abs(a1 * b2 - b1 * a2);
      if (mm < 1e-8 || radius === 0) {
        if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1) {
          points.push(x1, y1);
        }
        return;
      }
      const dd = a1 * a1 + b1 * b1;
      const cc = a2 * a2 + b2 * b2;
      const tt = a1 * a2 + b1 * b2;
      const k1 = radius * Math.sqrt(dd) / mm;
      const k2 = radius * Math.sqrt(cc) / mm;
      const j1 = k1 * tt / dd;
      const j2 = k2 * tt / cc;
      const cx = k1 * b2 + k2 * b1;
      const cy = k1 * a2 + k2 * a1;
      const px = b1 * (k2 + j1);
      const py = a1 * (k2 + j1);
      const qx = b2 * (k1 + j2);
      const qy = a2 * (k1 + j2);
      const startAngle = Math.atan2(py - cy, px - cx);
      const endAngle = Math.atan2(qy - cy, qx - cx);
      buildArc(
        points,
        cx + x1,
        cy + y1,
        radius,
        startAngle,
        endAngle,
        b1 * a2 > b2 * a1
      );
    }

    "use strict";
    const TAU = Math.PI * 2;
    const out = {
      centerX: 0,
      centerY: 0,
      ang1: 0,
      ang2: 0
    };
    const mapToEllipse = ({ x, y }, rx, ry, cosPhi, sinPhi, centerX, centerY, out2) => {
      x *= rx;
      y *= ry;
      const xp = cosPhi * x - sinPhi * y;
      const yp = sinPhi * x + cosPhi * y;
      out2.x = xp + centerX;
      out2.y = yp + centerY;
      return out2;
    };
    function approxUnitArc(ang1, ang2) {
      const a1 = ang2 === -1.5707963267948966 ? -0.551915024494 : 4 / 3 * Math.tan(ang2 / 4);
      const a = ang2 === 1.5707963267948966 ? 0.551915024494 : a1;
      const x1 = Math.cos(ang1);
      const y1 = Math.sin(ang1);
      const x2 = Math.cos(ang1 + ang2);
      const y2 = Math.sin(ang1 + ang2);
      return [
        {
          x: x1 - y1 * a,
          y: y1 + x1 * a
        },
        {
          x: x2 + y2 * a,
          y: y2 - x2 * a
        },
        {
          x: x2,
          y: y2
        }
      ];
    }
    const vectorAngle = (ux, uy, vx, vy) => {
      const sign = ux * vy - uy * vx < 0 ? -1 : 1;
      let dot = ux * vx + uy * vy;
      if (dot > 1) {
        dot = 1;
      }
      if (dot < -1) {
        dot = -1;
      }
      return sign * Math.acos(dot);
    };
    const getArcCenter = (px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinPhi, cosPhi, pxp, pyp, out2) => {
      const rxSq = Math.pow(rx, 2);
      const rySq = Math.pow(ry, 2);
      const pxpSq = Math.pow(pxp, 2);
      const pypSq = Math.pow(pyp, 2);
      let radicant = rxSq * rySq - rxSq * pypSq - rySq * pxpSq;
      if (radicant < 0) {
        radicant = 0;
      }
      radicant /= rxSq * pypSq + rySq * pxpSq;
      radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
      const centerXp = radicant * rx / ry * pyp;
      const centerYp = radicant * -ry / rx * pxp;
      const centerX = cosPhi * centerXp - sinPhi * centerYp + (px + cx) / 2;
      const centerY = sinPhi * centerXp + cosPhi * centerYp + (py + cy) / 2;
      const vx1 = (pxp - centerXp) / rx;
      const vy1 = (pyp - centerYp) / ry;
      const vx2 = (-pxp - centerXp) / rx;
      const vy2 = (-pyp - centerYp) / ry;
      const ang1 = vectorAngle(1, 0, vx1, vy1);
      let ang2 = vectorAngle(vx1, vy1, vx2, vy2);
      if (sweepFlag === 0 && ang2 > 0) {
        ang2 -= TAU;
      }
      if (sweepFlag === 1 && ang2 < 0) {
        ang2 += TAU;
      }
      out2.centerX = centerX;
      out2.centerY = centerY;
      out2.ang1 = ang1;
      out2.ang2 = ang2;
    };
    function buildArcToSvg(points, px, py, cx, cy, rx, ry, xAxisRotation = 0, largeArcFlag = 0, sweepFlag = 0) {
      if (rx === 0 || ry === 0) {
        return;
      }
      const sinPhi = Math.sin(xAxisRotation * TAU / 360);
      const cosPhi = Math.cos(xAxisRotation * TAU / 360);
      const pxp = cosPhi * (px - cx) / 2 + sinPhi * (py - cy) / 2;
      const pyp = -sinPhi * (px - cx) / 2 + cosPhi * (py - cy) / 2;
      if (pxp === 0 && pyp === 0) {
        return;
      }
      rx = Math.abs(rx);
      ry = Math.abs(ry);
      const lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
      if (lambda > 1) {
        rx *= Math.sqrt(lambda);
        ry *= Math.sqrt(lambda);
      }
      getArcCenter(
        px,
        py,
        cx,
        cy,
        rx,
        ry,
        largeArcFlag,
        sweepFlag,
        sinPhi,
        cosPhi,
        pxp,
        pyp,
        out
      );
      let { ang1, ang2 } = out;
      const { centerX, centerY } = out;
      let ratio = Math.abs(ang2) / (TAU / 4);
      if (Math.abs(1 - ratio) < 1e-7) {
        ratio = 1;
      }
      const segments = Math.max(Math.ceil(ratio), 1);
      ang2 /= segments;
      let lastX = points[points.length - 2];
      let lastY = points[points.length - 1];
      const outCurvePoint = { x: 0, y: 0 };
      for (let i = 0; i < segments; i++) {
        const curve = approxUnitArc(ang1, ang2);
        const { x: x1, y: y1 } = mapToEllipse(curve[0], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
        const { x: x2, y: y2 } = mapToEllipse(curve[1], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
        const { x, y } = mapToEllipse(curve[2], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
        buildAdaptiveBezier(
          points,
          lastX,
          lastY,
          x1,
          y1,
          x2,
          y2,
          x,
          y
        );
        lastX = x;
        lastY = y;
        ang1 += ang2;
      }
    }

    "use strict";
    function roundedShapeArc(g, points, radius) {
      var _a;
      const vecFrom = (p, pp) => {
        const x = pp.x - p.x;
        const y = pp.y - p.y;
        const len = Math.sqrt(x * x + y * y);
        const nx = x / len;
        const ny = y / len;
        return { len, nx, ny };
      };
      const sharpCorner = (i, p) => {
        if (i === 0) {
          g.moveTo(p.x, p.y);
        } else {
          g.lineTo(p.x, p.y);
        }
      };
      let p1 = points[points.length - 1];
      for (let i = 0; i < points.length; i++) {
        const p2 = points[i % points.length];
        const pRadius = (_a = p2.radius) != null ? _a : radius;
        if (pRadius <= 0) {
          sharpCorner(i, p2);
          p1 = p2;
          continue;
        }
        const p3 = points[(i + 1) % points.length];
        const v1 = vecFrom(p2, p1);
        const v2 = vecFrom(p2, p3);
        if (v1.len < 1e-4 || v2.len < 1e-4) {
          sharpCorner(i, p2);
          p1 = p2;
          continue;
        }
        let angle = Math.asin(v1.nx * v2.ny - v1.ny * v2.nx);
        let radDirection = 1;
        let drawDirection = false;
        if (v1.nx * v2.nx - v1.ny * -v2.ny < 0) {
          if (angle < 0) {
            angle = Math.PI + angle;
          } else {
            angle = Math.PI - angle;
            radDirection = -1;
            drawDirection = true;
          }
        } else if (angle > 0) {
          radDirection = -1;
          drawDirection = true;
        }
        const halfAngle = angle / 2;
        let cRadius;
        let lenOut = Math.abs(
          Math.cos(halfAngle) * pRadius / Math.sin(halfAngle)
        );
        if (lenOut > Math.min(v1.len / 2, v2.len / 2)) {
          lenOut = Math.min(v1.len / 2, v2.len / 2);
          cRadius = Math.abs(lenOut * Math.sin(halfAngle) / Math.cos(halfAngle));
        } else {
          cRadius = pRadius;
        }
        const cX = p2.x + v2.nx * lenOut + -v2.ny * cRadius * radDirection;
        const cY = p2.y + v2.ny * lenOut + v2.nx * cRadius * radDirection;
        const startAngle = Math.atan2(v1.ny, v1.nx) + Math.PI / 2 * radDirection;
        const endAngle = Math.atan2(v2.ny, v2.nx) - Math.PI / 2 * radDirection;
        if (i === 0) {
          g.moveTo(
            cX + Math.cos(startAngle) * cRadius,
            cY + Math.sin(startAngle) * cRadius
          );
        }
        g.arc(cX, cY, cRadius, startAngle, endAngle, drawDirection);
        p1 = p2;
      }
    }
    function roundedShapeQuadraticCurve(g, points, radius, smoothness) {
      var _a;
      const distance = (p1, p2) => Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
      const pointLerp = (p1, p2, t) => ({
        x: p1.x + (p2.x - p1.x) * t,
        y: p1.y + (p2.y - p1.y) * t
      });
      const numPoints = points.length;
      for (let i = 0; i < numPoints; i++) {
        const thisPoint = points[(i + 1) % numPoints];
        const pRadius = (_a = thisPoint.radius) != null ? _a : radius;
        if (pRadius <= 0) {
          if (i === 0) {
            g.moveTo(thisPoint.x, thisPoint.y);
          } else {
            g.lineTo(thisPoint.x, thisPoint.y);
          }
          continue;
        }
        const lastPoint = points[i];
        const nextPoint = points[(i + 2) % numPoints];
        const lastEdgeLength = distance(lastPoint, thisPoint);
        let start;
        if (lastEdgeLength < 1e-4) {
          start = thisPoint;
        } else {
          const lastOffsetDistance = Math.min(lastEdgeLength / 2, pRadius);
          start = pointLerp(
            thisPoint,
            lastPoint,
            lastOffsetDistance / lastEdgeLength
          );
        }
        const nextEdgeLength = distance(nextPoint, thisPoint);
        let end;
        if (nextEdgeLength < 1e-4) {
          end = thisPoint;
        } else {
          const nextOffsetDistance = Math.min(nextEdgeLength / 2, pRadius);
          end = pointLerp(
            thisPoint,
            nextPoint,
            nextOffsetDistance / nextEdgeLength
          );
        }
        if (i === 0) {
          g.moveTo(start.x, start.y);
        } else {
          g.lineTo(start.x, start.y);
        }
        g.quadraticCurveTo(thisPoint.x, thisPoint.y, end.x, end.y, smoothness);
      }
    }

    "use strict";
    const tempRectangle = new Rectangle();
    class ShapePath {
      constructor(graphicsPath2D) {
        /** The list of shape primitives that make up the path. */
        this.shapePrimitives = [];
        this._currentPoly = null;
        this._bounds = new Bounds();
        this._graphicsPath2D = graphicsPath2D;
        this.signed = graphicsPath2D.checkForHoles;
      }
      /**
       * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
       * @param x - The x-coordinate for the starting point.
       * @param y - The y-coordinate for the starting point.
       * @returns The instance of the current object for chaining.
       */
      moveTo(x, y) {
        this.startPoly(x, y);
        return this;
      }
      /**
       * Connects the current point to a new point with a straight line. This method updates the current path.
       * @param x - The x-coordinate of the new point to connect to.
       * @param y - The y-coordinate of the new point to connect to.
       * @returns The instance of the current object for chaining.
       */
      lineTo(x, y) {
        this._ensurePoly();
        const points = this._currentPoly.points;
        const fromX = points[points.length - 2];
        const fromY = points[points.length - 1];
        if (fromX !== x || fromY !== y) {
          points.push(x, y);
        }
        return this;
      }
      /**
       * Adds an arc to the path. The arc is centered at (x, y)
       *  position with radius `radius` starting at `startAngle` and ending at `endAngle`.
       * @param x - The x-coordinate of the arc's center.
       * @param y - The y-coordinate of the arc's center.
       * @param radius - The radius of the arc.
       * @param startAngle - The starting angle of the arc, in radians.
       * @param endAngle - The ending angle of the arc, in radians.
       * @param counterclockwise - Specifies whether the arc should be drawn in the anticlockwise direction. False by default.
       * @returns The instance of the current object for chaining.
       */
      arc(x, y, radius, startAngle, endAngle, counterclockwise) {
        this._ensurePoly(false);
        const points = this._currentPoly.points;
        buildArc(points, x, y, radius, startAngle, endAngle, counterclockwise);
        return this;
      }
      /**
       * Adds an arc to the path with the arc tangent to the line joining two specified points.
       * The arc radius is specified by `radius`.
       * @param x1 - The x-coordinate of the first point.
       * @param y1 - The y-coordinate of the first point.
       * @param x2 - The x-coordinate of the second point.
       * @param y2 - The y-coordinate of the second point.
       * @param radius - The radius of the arc.
       * @returns The instance of the current object for chaining.
       */
      arcTo(x1, y1, x2, y2, radius) {
        this._ensurePoly();
        const points = this._currentPoly.points;
        buildArcTo(points, x1, y1, x2, y2, radius);
        return this;
      }
      /**
       * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
       * @param rx - The x-radius of the ellipse.
       * @param ry - The y-radius of the ellipse.
       * @param xAxisRotation - The rotation of the ellipse's x-axis relative
       * to the x-axis of the coordinate system, in degrees.
       * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
       * @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
       * @param x - The x-coordinate of the arc's end point.
       * @param y - The y-coordinate of the arc's end point.
       * @returns The instance of the current object for chaining.
       */
      arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
        const points = this._currentPoly.points;
        buildArcToSvg(
          points,
          this._currentPoly.lastX,
          this._currentPoly.lastY,
          x,
          y,
          rx,
          ry,
          xAxisRotation,
          largeArcFlag,
          sweepFlag
        );
        return this;
      }
      /**
       * Adds a cubic Bezier curve to the path.
       * It requires three points: the first two are control points and the third one is the end point.
       * The starting point is the last point in the current path.
       * @param cp1x - The x-coordinate of the first control point.
       * @param cp1y - The y-coordinate of the first control point.
       * @param cp2x - The x-coordinate of the second control point.
       * @param cp2y - The y-coordinate of the second control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothness - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
        this._ensurePoly();
        const currentPoly = this._currentPoly;
        buildAdaptiveBezier(
          this._currentPoly.points,
          currentPoly.lastX,
          currentPoly.lastY,
          cp1x,
          cp1y,
          cp2x,
          cp2y,
          x,
          y,
          smoothness
        );
        return this;
      }
      /**
       * Adds a quadratic curve to the path. It requires two points: the control point and the end point.
       * The starting point is the last point in the current path.
       * @param cp1x - The x-coordinate of the control point.
       * @param cp1y - The y-coordinate of the control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothing - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      quadraticCurveTo(cp1x, cp1y, x, y, smoothing) {
        this._ensurePoly();
        const currentPoly = this._currentPoly;
        buildAdaptiveQuadratic(
          this._currentPoly.points,
          currentPoly.lastX,
          currentPoly.lastY,
          cp1x,
          cp1y,
          x,
          y,
          smoothing
        );
        return this;
      }
      /**
       * Closes the current path by drawing a straight line back to the start.
       * If the shape is already closed or there are no points in the path, this method does nothing.
       * @returns The instance of the current object for chaining.
       */
      closePath() {
        this.endPoly(true);
        return this;
      }
      /**
       * Adds another path to the current path. This method allows for the combination of multiple paths into one.
       * @param path - The `GraphicsPath` object representing the path to add.
       * @param transform - An optional `Matrix` object to apply a transformation to the path before adding it.
       * @returns The instance of the current object for chaining.
       */
      addPath(path, transform) {
        this.endPoly();
        if (transform && !transform.isIdentity()) {
          path = path.clone(true);
          path.transform(transform);
        }
        const shapePrimitives = this.shapePrimitives;
        const start = shapePrimitives.length;
        for (let i = 0; i < path.instructions.length; i++) {
          const instruction = path.instructions[i];
          this[instruction.action](...instruction.data);
        }
        if (path.checkForHoles && shapePrimitives.length - start > 1) {
          let mainShape = null;
          for (let i = start; i < shapePrimitives.length; i++) {
            const shapePrimitive = shapePrimitives[i];
            if (shapePrimitive.shape.type === "polygon") {
              const polygon = shapePrimitive.shape;
              const mainPolygon = mainShape == null ? void 0 : mainShape.shape;
              if (mainPolygon && mainPolygon.containsPolygon(polygon)) {
                mainShape.holes || (mainShape.holes = []);
                mainShape.holes.push(shapePrimitive);
                shapePrimitives.copyWithin(i, i + 1);
                shapePrimitives.length--;
                i--;
              } else {
                mainShape = shapePrimitive;
              }
            }
          }
        }
        return this;
      }
      /**
       * Finalizes the drawing of the current path. Optionally, it can close the path.
       * @param closePath - A boolean indicating whether to close the path after finishing. False by default.
       */
      finish(closePath = false) {
        this.endPoly(closePath);
      }
      /**
       * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
       * @param x - The x-coordinate of the top-left corner of the rectangle.
       * @param y - The y-coordinate of the top-left corner of the rectangle.
       * @param w - The width of the rectangle.
       * @param h - The height of the rectangle.
       * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
       * @returns The instance of the current object for chaining.
       */
      rect(x, y, w, h, transform) {
        this.drawShape(new Rectangle(x, y, w, h), transform);
        return this;
      }
      /**
       * Draws a circle shape. This method adds a new circle path to the current drawing.
       * @param x - The x-coordinate of the center of the circle.
       * @param y - The y-coordinate of the center of the circle.
       * @param radius - The radius of the circle.
       * @param transform - An optional `Matrix` object to apply a transformation to the circle.
       * @returns The instance of the current object for chaining.
       */
      circle(x, y, radius, transform) {
        this.drawShape(new Circle(x, y, radius), transform);
        return this;
      }
      /**
       * Draws a polygon shape. This method allows for the creation of complex polygons by specifying a sequence of points.
       * @param points - An array of numbers, or or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
       * representing the x and y coordinates of the polygon's vertices, in sequence.
       * @param close - A boolean indicating whether to close the polygon path. True by default.
       * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
       * @returns The instance of the current object for chaining.
       */
      poly(points, close, transform) {
        const polygon = new Polygon(points);
        polygon.closePath = close;
        this.drawShape(polygon, transform);
        return this;
      }
      /**
       * Draws a regular polygon with a specified number of sides. All sides and angles are equal.
       * @param x - The x-coordinate of the center of the polygon.
       * @param y - The y-coordinate of the center of the polygon.
       * @param radius - The radius of the circumscribed circle of the polygon.
       * @param sides - The number of sides of the polygon. Must be 3 or more.
       * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
       * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
       * @returns The instance of the current object for chaining.
       */
      regularPoly(x, y, radius, sides, rotation = 0, transform) {
        sides = Math.max(sides | 0, 3);
        const startAngle = -1 * Math.PI / 2 + rotation;
        const delta = Math.PI * 2 / sides;
        const polygon = [];
        for (let i = 0; i < sides; i++) {
          const angle = startAngle - i * delta;
          polygon.push(
            x + radius * Math.cos(angle),
            y + radius * Math.sin(angle)
          );
        }
        this.poly(polygon, true, transform);
        return this;
      }
      /**
       * Draws a polygon with rounded corners.
       * Similar to `regularPoly` but with the ability to round the corners of the polygon.
       * @param x - The x-coordinate of the center of the polygon.
       * @param y - The y-coordinate of the center of the polygon.
       * @param radius - The radius of the circumscribed circle of the polygon.
       * @param sides - The number of sides of the polygon. Must be 3 or more.
       * @param corner - The radius of the rounding of the corners.
       * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
       * @param smoothness - Optional parameter to adjust the smoothness of the rounding.
       * @returns The instance of the current object for chaining.
       */
      roundPoly(x, y, radius, sides, corner, rotation = 0, smoothness) {
        sides = Math.max(sides | 0, 3);
        if (corner <= 0) {
          return this.regularPoly(x, y, radius, sides, rotation);
        }
        const sideLength = radius * Math.sin(Math.PI / sides) - 1e-3;
        corner = Math.min(corner, sideLength);
        const startAngle = -1 * Math.PI / 2 + rotation;
        const delta = Math.PI * 2 / sides;
        const internalAngle = (sides - 2) * Math.PI / sides / 2;
        for (let i = 0; i < sides; i++) {
          const angle = i * delta + startAngle;
          const x0 = x + radius * Math.cos(angle);
          const y0 = y + radius * Math.sin(angle);
          const a1 = angle + Math.PI + internalAngle;
          const a2 = angle - Math.PI - internalAngle;
          const x1 = x0 + corner * Math.cos(a1);
          const y1 = y0 + corner * Math.sin(a1);
          const x3 = x0 + corner * Math.cos(a2);
          const y3 = y0 + corner * Math.sin(a2);
          if (i === 0) {
            this.moveTo(x1, y1);
          } else {
            this.lineTo(x1, y1);
          }
          this.quadraticCurveTo(x0, y0, x3, y3, smoothness);
        }
        return this.closePath();
      }
      /**
       * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
       * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
       * @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
       * A minimum of 3 points is required.
       * @param radius - The default radius for the corners.
       * This radius is applied to all corners unless overridden in `points`.
       * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
       *  method instead of an arc method. Defaults to false.
       * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
       * Higher values make the curve smoother.
       * @returns The instance of the current object for chaining.
       */
      roundShape(points, radius, useQuadratic = false, smoothness) {
        if (points.length < 3) {
          return this;
        }
        if (useQuadratic) {
          roundedShapeQuadraticCurve(this, points, radius, smoothness);
        } else {
          roundedShapeArc(this, points, radius);
        }
        return this.closePath();
      }
      /**
       * Draw Rectangle with fillet corners. This is much like rounded rectangle
       * however it support negative numbers as well for the corner radius.
       * @param x - Upper left corner of rect
       * @param y - Upper right corner of rect
       * @param width - Width of rect
       * @param height - Height of rect
       * @param fillet - accept negative or positive values
       */
      filletRect(x, y, width, height, fillet) {
        if (fillet === 0) {
          return this.rect(x, y, width, height);
        }
        const maxFillet = Math.min(width, height) / 2;
        const inset = Math.min(maxFillet, Math.max(-maxFillet, fillet));
        const right = x + width;
        const bottom = y + height;
        const dir = inset < 0 ? -inset : 0;
        const size = Math.abs(inset);
        return this.moveTo(x, y + size).arcTo(x + dir, y + dir, x + size, y, size).lineTo(right - size, y).arcTo(right - dir, y + dir, right, y + size, size).lineTo(right, bottom - size).arcTo(right - dir, bottom - dir, x + width - size, bottom, size).lineTo(x + size, bottom).arcTo(x + dir, bottom - dir, x, bottom - size, size).closePath();
      }
      /**
       * Draw Rectangle with chamfer corners. These are angled corners.
       * @param x - Upper left corner of rect
       * @param y - Upper right corner of rect
       * @param width - Width of rect
       * @param height - Height of rect
       * @param chamfer - non-zero real number, size of corner cutout
       * @param transform
       */
      chamferRect(x, y, width, height, chamfer, transform) {
        if (chamfer <= 0) {
          return this.rect(x, y, width, height);
        }
        const inset = Math.min(chamfer, Math.min(width, height) / 2);
        const right = x + width;
        const bottom = y + height;
        const points = [
          x + inset,
          y,
          right - inset,
          y,
          right,
          y + inset,
          right,
          bottom - inset,
          right - inset,
          bottom,
          x + inset,
          bottom,
          x,
          bottom - inset,
          x,
          y + inset
        ];
        for (let i = points.length - 1; i >= 2; i -= 2) {
          if (points[i] === points[i - 2] && points[i - 1] === points[i - 3]) {
            points.splice(i - 1, 2);
          }
        }
        return this.poly(points, true, transform);
      }
      /**
       * Draws an ellipse at the specified location and with the given x and y radii.
       * An optional transformation can be applied, allowing for rotation, scaling, and translation.
       * @param x - The x-coordinate of the center of the ellipse.
       * @param y - The y-coordinate of the center of the ellipse.
       * @param radiusX - The horizontal radius of the ellipse.
       * @param radiusY - The vertical radius of the ellipse.
       * @param transform - An optional `Matrix` object to apply a transformation to the ellipse. This can include rotations.
       * @returns The instance of the current object for chaining.
       */
      ellipse(x, y, radiusX, radiusY, transform) {
        this.drawShape(new Ellipse(x, y, radiusX, radiusY), transform);
        return this;
      }
      /**
       * Draws a rectangle with rounded corners.
       * The corner radius can be specified to determine how rounded the corners should be.
       * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
       * @param x - The x-coordinate of the top-left corner of the rectangle.
       * @param y - The y-coordinate of the top-left corner of the rectangle.
       * @param w - The width of the rectangle.
       * @param h - The height of the rectangle.
       * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
       * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
       * @returns The instance of the current object for chaining.
       */
      roundRect(x, y, w, h, radius, transform) {
        this.drawShape(new RoundedRectangle(x, y, w, h, radius), transform);
        return this;
      }
      /**
       * Draws a given shape on the canvas.
       * This is a generic method that can draw any type of shape specified by the `ShapePrimitive` parameter.
       * An optional transformation matrix can be applied to the shape, allowing for complex transformations.
       * @param shape - The shape to draw, defined as a `ShapePrimitive` object.
       * @param matrix - An optional `Matrix` for transforming the shape. This can include rotations,
       * scaling, and translations.
       * @returns The instance of the current object for chaining.
       */
      drawShape(shape, matrix) {
        this.endPoly();
        this.shapePrimitives.push({ shape, transform: matrix });
        return this;
      }
      /**
       * Starts a new polygon path from the specified starting point.
       * This method initializes a new polygon or ends the current one if it exists.
       * @param x - The x-coordinate of the starting point of the new polygon.
       * @param y - The y-coordinate of the starting point of the new polygon.
       * @returns The instance of the current object for chaining.
       */
      startPoly(x, y) {
        let currentPoly = this._currentPoly;
        if (currentPoly) {
          this.endPoly();
        }
        currentPoly = new Polygon();
        currentPoly.points.push(x, y);
        this._currentPoly = currentPoly;
        return this;
      }
      /**
       * Ends the current polygon path. If `closePath` is set to true,
       * the path is closed by connecting the last point to the first one.
       * This method finalizes the current polygon and prepares it for drawing or adding to the shape primitives.
       * @param closePath - A boolean indicating whether to close the polygon by connecting the last point
       *  back to the starting point. False by default.
       * @returns The instance of the current object for chaining.
       */
      endPoly(closePath = false) {
        const shape = this._currentPoly;
        if (shape && shape.points.length > 2) {
          shape.closePath = closePath;
          this.shapePrimitives.push({ shape });
        }
        this._currentPoly = null;
        return this;
      }
      _ensurePoly(start = true) {
        if (this._currentPoly)
          return;
        this._currentPoly = new Polygon();
        if (start) {
          const lastShape = this.shapePrimitives[this.shapePrimitives.length - 1];
          if (lastShape) {
            let lx = lastShape.shape.x;
            let ly = lastShape.shape.y;
            if (lastShape.transform && !lastShape.transform.isIdentity()) {
              const t = lastShape.transform;
              const tempX = lx;
              lx = t.a * lx + t.c * ly + t.tx;
              ly = t.b * tempX + t.d * ly + t.ty;
            }
            this._currentPoly.points.push(lx, ly);
          } else {
            this._currentPoly.points.push(0, 0);
          }
        }
      }
      /** Builds the path. */
      buildPath() {
        const path = this._graphicsPath2D;
        this.shapePrimitives.length = 0;
        this._currentPoly = null;
        for (let i = 0; i < path.instructions.length; i++) {
          const instruction = path.instructions[i];
          this[instruction.action](...instruction.data);
        }
        this.finish();
      }
      /** Gets the bounds of the path. */
      get bounds() {
        const bounds = this._bounds;
        bounds.clear();
        const shapePrimitives = this.shapePrimitives;
        for (let i = 0; i < shapePrimitives.length; i++) {
          const shapePrimitive = shapePrimitives[i];
          const boundsRect = shapePrimitive.shape.getBounds(tempRectangle);
          if (shapePrimitive.transform) {
            bounds.addRect(boundsRect, shapePrimitive.transform);
          } else {
            bounds.addRect(boundsRect);
          }
        }
        return bounds;
      }
    }

    "use strict";
    class GraphicsPath {
      /**
       * Creates a `GraphicsPath` instance optionally from an SVG path string or an array of `PathInstruction`.
       * @param instructions - An SVG path string or an array of `PathInstruction` objects.
       * @param signed
       */
      constructor(instructions, signed = false) {
        this.instructions = [];
        /** unique id for this graphics path */
        this.uid = uid$1("graphicsPath");
        this._dirty = true;
        var _a;
        this.checkForHoles = signed;
        if (typeof instructions === "string") {
          parseSVGPath(instructions, this);
        } else {
          this.instructions = (_a = instructions == null ? void 0 : instructions.slice()) != null ? _a : [];
        }
      }
      /**
       * Provides access to the internal shape path, ensuring it is up-to-date with the current instructions.
       * @returns The `ShapePath` instance associated with this `GraphicsPath`.
       */
      get shapePath() {
        if (!this._shapePath) {
          this._shapePath = new ShapePath(this);
        }
        if (this._dirty) {
          this._dirty = false;
          this._shapePath.buildPath();
        }
        return this._shapePath;
      }
      /**
       * Adds another `GraphicsPath` to this path, optionally applying a transformation.
       * @param path - The `GraphicsPath` to add.
       * @param transform - An optional transformation to apply to the added path.
       * @returns The instance of the current object for chaining.
       */
      addPath(path, transform) {
        path = path.clone();
        this.instructions.push({ action: "addPath", data: [path, transform] });
        this._dirty = true;
        return this;
      }
      arc(...args) {
        this.instructions.push({ action: "arc", data: args });
        this._dirty = true;
        return this;
      }
      arcTo(...args) {
        this.instructions.push({ action: "arcTo", data: args });
        this._dirty = true;
        return this;
      }
      arcToSvg(...args) {
        this.instructions.push({ action: "arcToSvg", data: args });
        this._dirty = true;
        return this;
      }
      bezierCurveTo(...args) {
        this.instructions.push({ action: "bezierCurveTo", data: args });
        this._dirty = true;
        return this;
      }
      /**
       * Adds a cubic Bezier curve to the path.
       * It requires two points: the second control point and the end point. The first control point is assumed to be
       * The starting point is the last point in the current path.
       * @param cp2x - The x-coordinate of the second control point.
       * @param cp2y - The y-coordinate of the second control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothness - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      bezierCurveToShort(cp2x, cp2y, x, y, smoothness) {
        const last = this.instructions[this.instructions.length - 1];
        const lastPoint = this.getLastPoint(Point.shared);
        let cp1x = 0;
        let cp1y = 0;
        if (!last || last.action !== "bezierCurveTo") {
          cp1x = lastPoint.x;
          cp1y = lastPoint.y;
        } else {
          cp1x = last.data[2];
          cp1y = last.data[3];
          const currentX = lastPoint.x;
          const currentY = lastPoint.y;
          cp1x = currentX + (currentX - cp1x);
          cp1y = currentY + (currentY - cp1y);
        }
        this.instructions.push({ action: "bezierCurveTo", data: [cp1x, cp1y, cp2x, cp2y, x, y, smoothness] });
        this._dirty = true;
        return this;
      }
      /**
       * Closes the current path by drawing a straight line back to the start.
       * If the shape is already closed or there are no points in the path, this method does nothing.
       * @returns The instance of the current object for chaining.
       */
      closePath() {
        this.instructions.push({ action: "closePath", data: [] });
        this._dirty = true;
        return this;
      }
      ellipse(...args) {
        this.instructions.push({ action: "ellipse", data: args });
        this._dirty = true;
        return this;
      }
      lineTo(...args) {
        this.instructions.push({ action: "lineTo", data: args });
        this._dirty = true;
        return this;
      }
      moveTo(...args) {
        this.instructions.push({ action: "moveTo", data: args });
        return this;
      }
      quadraticCurveTo(...args) {
        this.instructions.push({ action: "quadraticCurveTo", data: args });
        this._dirty = true;
        return this;
      }
      /**
       * Adds a quadratic curve to the path. It uses the previous point as the control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothness - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      quadraticCurveToShort(x, y, smoothness) {
        const last = this.instructions[this.instructions.length - 1];
        const lastPoint = this.getLastPoint(Point.shared);
        let cpx1 = 0;
        let cpy1 = 0;
        if (!last || last.action !== "quadraticCurveTo") {
          cpx1 = lastPoint.x;
          cpy1 = lastPoint.y;
        } else {
          cpx1 = last.data[0];
          cpy1 = last.data[1];
          const currentX = lastPoint.x;
          const currentY = lastPoint.y;
          cpx1 = currentX + (currentX - cpx1);
          cpy1 = currentY + (currentY - cpy1);
        }
        this.instructions.push({ action: "quadraticCurveTo", data: [cpx1, cpy1, x, y, smoothness] });
        this._dirty = true;
        return this;
      }
      /**
       * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
       * @param x - The x-coordinate of the top-left corner of the rectangle.
       * @param y - The y-coordinate of the top-left corner of the rectangle.
       * @param w - The width of the rectangle.
       * @param h - The height of the rectangle.
       * @param transform - An optional `Matrix` object to apply a transformation to the rectangle.
       * @returns The instance of the current object for chaining.
       */
      rect(x, y, w, h, transform) {
        this.instructions.push({ action: "rect", data: [x, y, w, h, transform] });
        this._dirty = true;
        return this;
      }
      /**
       * Draws a circle shape. This method adds a new circle path to the current drawing.
       * @param x - The x-coordinate of the center of the circle.
       * @param y - The y-coordinate of the center of the circle.
       * @param radius - The radius of the circle.
       * @param transform - An optional `Matrix` object to apply a transformation to the circle.
       * @returns The instance of the current object for chaining.
       */
      circle(x, y, radius, transform) {
        this.instructions.push({ action: "circle", data: [x, y, radius, transform] });
        this._dirty = true;
        return this;
      }
      roundRect(...args) {
        this.instructions.push({ action: "roundRect", data: args });
        this._dirty = true;
        return this;
      }
      poly(...args) {
        this.instructions.push({ action: "poly", data: args });
        this._dirty = true;
        return this;
      }
      regularPoly(...args) {
        this.instructions.push({ action: "regularPoly", data: args });
        this._dirty = true;
        return this;
      }
      roundPoly(...args) {
        this.instructions.push({ action: "roundPoly", data: args });
        this._dirty = true;
        return this;
      }
      roundShape(...args) {
        this.instructions.push({ action: "roundShape", data: args });
        this._dirty = true;
        return this;
      }
      filletRect(...args) {
        this.instructions.push({ action: "filletRect", data: args });
        this._dirty = true;
        return this;
      }
      chamferRect(...args) {
        this.instructions.push({ action: "chamferRect", data: args });
        this._dirty = true;
        return this;
      }
      /**
       * Draws a star shape centered at a specified location. This method allows for the creation
       *  of stars with a variable number of points, outer radius, optional inner radius, and rotation.
       * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
       * An optional transformation can be applied to scale, rotate, or translate the star as needed.
       * @param x - The x-coordinate of the center of the star.
       * @param y - The y-coordinate of the center of the star.
       * @param points - The number of points of the star.
       * @param radius - The outer radius of the star (distance from the center to the outer points).
       * @param innerRadius - Optional. The inner radius of the star
       * (distance from the center to the inner points between the outer points).
       * If not provided, defaults to half of the `radius`.
       * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
       * Defaults to 0, meaning one point is directly upward.
       * @param transform - An optional `Matrix` object to apply a transformation to the star.
       * This can include rotations, scaling, and translations.
       * @returns The instance of the current object for chaining further drawing commands.
       */
      // eslint-disable-next-line max-len
      star(x, y, points, radius, innerRadius, rotation, transform) {
        innerRadius || (innerRadius = radius / 2);
        const startAngle = -1 * Math.PI / 2 + rotation;
        const len = points * 2;
        const delta = Math.PI * 2 / len;
        const polygon = [];
        for (let i = 0; i < len; i++) {
          const r = i % 2 ? innerRadius : radius;
          const angle = i * delta + startAngle;
          polygon.push(
            x + r * Math.cos(angle),
            y + r * Math.sin(angle)
          );
        }
        this.poly(polygon, true, transform);
        return this;
      }
      /**
       * Creates a copy of the current `GraphicsPath` instance. This method supports both shallow and deep cloning.
       * A shallow clone copies the reference of the instructions array, while a deep clone creates a new array and
       * copies each instruction individually, ensuring that modifications to the instructions of the cloned `GraphicsPath`
       * do not affect the original `GraphicsPath` and vice versa.
       * @param deep - A boolean flag indicating whether the clone should be deep.
       * @returns A new `GraphicsPath` instance that is a clone of the current instance.
       */
      clone(deep = false) {
        const newGraphicsPath2D = new GraphicsPath();
        newGraphicsPath2D.checkForHoles = this.checkForHoles;
        if (!deep) {
          newGraphicsPath2D.instructions = this.instructions.slice();
        } else {
          for (let i = 0; i < this.instructions.length; i++) {
            const instruction = this.instructions[i];
            newGraphicsPath2D.instructions.push({ action: instruction.action, data: instruction.data.slice() });
          }
        }
        return newGraphicsPath2D;
      }
      clear() {
        this.instructions.length = 0;
        this._dirty = true;
        return this;
      }
      /**
       * Applies a transformation matrix to all drawing instructions within the `GraphicsPath`.
       * This method enables the modification of the path's geometry according to the provided
       * transformation matrix, which can include translations, rotations, scaling, and skewing.
       *
       * Each drawing instruction in the path is updated to reflect the transformation,
       * ensuring the visual representation of the path is consistent with the applied matrix.
       *
       * Note: The transformation is applied directly to the coordinates and control points of the drawing instructions,
       * not to the path as a whole. This means the transformation's effects are baked into the individual instructions,
       * allowing for fine-grained control over the path's appearance.
       * @param matrix - A `Matrix` object representing the transformation to apply.
       * @returns The instance of the current object for chaining further operations.
       */
      transform(matrix) {
        if (matrix.isIdentity())
          return this;
        const a = matrix.a;
        const b = matrix.b;
        const c = matrix.c;
        const d = matrix.d;
        const tx = matrix.tx;
        const ty = matrix.ty;
        let x = 0;
        let y = 0;
        let cpx1 = 0;
        let cpy1 = 0;
        let cpx2 = 0;
        let cpy2 = 0;
        let rx = 0;
        let ry = 0;
        for (let i = 0; i < this.instructions.length; i++) {
          const instruction = this.instructions[i];
          const data = instruction.data;
          switch (instruction.action) {
            case "moveTo":
            case "lineTo":
              x = data[0];
              y = data[1];
              data[0] = a * x + c * y + tx;
              data[1] = b * x + d * y + ty;
              break;
            case "bezierCurveTo":
              cpx1 = data[0];
              cpy1 = data[1];
              cpx2 = data[2];
              cpy2 = data[3];
              x = data[4];
              y = data[5];
              data[0] = a * cpx1 + c * cpy1 + tx;
              data[1] = b * cpx1 + d * cpy1 + ty;
              data[2] = a * cpx2 + c * cpy2 + tx;
              data[3] = b * cpx2 + d * cpy2 + ty;
              data[4] = a * x + c * y + tx;
              data[5] = b * x + d * y + ty;
              break;
            case "quadraticCurveTo":
              cpx1 = data[0];
              cpy1 = data[1];
              x = data[2];
              y = data[3];
              data[0] = a * cpx1 + c * cpy1 + tx;
              data[1] = b * cpx1 + d * cpy1 + ty;
              data[2] = a * x + c * y + tx;
              data[3] = b * x + d * y + ty;
              break;
            case "arcToSvg":
              x = data[5];
              y = data[6];
              rx = data[0];
              ry = data[1];
              data[0] = a * rx + c * ry;
              data[1] = b * rx + d * ry;
              data[5] = a * x + c * y + tx;
              data[6] = b * x + d * y + ty;
              break;
            case "circle":
              data[4] = adjustTransform(data[3], matrix);
              break;
            case "rect":
              data[4] = adjustTransform(data[4], matrix);
              break;
            case "ellipse":
              data[8] = adjustTransform(data[8], matrix);
              break;
            case "roundRect":
              data[5] = adjustTransform(data[5], matrix);
              break;
            case "addPath":
              data[0].transform(matrix);
              break;
            case "poly":
              data[2] = adjustTransform(data[2], matrix);
              break;
            default:
              warn("unknown transform action", instruction.action);
              break;
          }
        }
        this._dirty = true;
        return this;
      }
      get bounds() {
        return this.shapePath.bounds;
      }
      /**
       * Retrieves the last point from the current drawing instructions in the `GraphicsPath`.
       * This method is useful for operations that depend on the path's current endpoint,
       * such as connecting subsequent shapes or paths. It supports various drawing instructions,
       * ensuring the last point's position is accurately determined regardless of the path's complexity.
       *
       * If the last instruction is a `closePath`, the method iterates backward through the instructions
       *  until it finds an actionable instruction that defines a point (e.g., `moveTo`, `lineTo`,
       * `quadraticCurveTo`, etc.). For compound paths added via `addPath`, it recursively retrieves
       * the last point from the nested path.
       * @param out - A `Point` object where the last point's coordinates will be stored.
       * This object is modified directly to contain the result.
       * @returns The `Point` object containing the last point's coordinates.
       */
      getLastPoint(out) {
        let index = this.instructions.length - 1;
        let lastInstruction = this.instructions[index];
        if (!lastInstruction) {
          out.x = 0;
          out.y = 0;
          return out;
        }
        while (lastInstruction.action === "closePath") {
          index--;
          if (index < 0) {
            out.x = 0;
            out.y = 0;
            return out;
          }
          lastInstruction = this.instructions[index];
        }
        switch (lastInstruction.action) {
          case "moveTo":
          case "lineTo":
            out.x = lastInstruction.data[0];
            out.y = lastInstruction.data[1];
            break;
          case "quadraticCurveTo":
            out.x = lastInstruction.data[2];
            out.y = lastInstruction.data[3];
            break;
          case "bezierCurveTo":
            out.x = lastInstruction.data[4];
            out.y = lastInstruction.data[5];
            break;
          case "arc":
          case "arcToSvg":
            out.x = lastInstruction.data[5];
            out.y = lastInstruction.data[6];
            break;
          case "addPath":
            lastInstruction.data[0].getLastPoint(out);
            break;
        }
        return out;
      }
    }
    function adjustTransform(currentMatrix, transform) {
      if (currentMatrix) {
        return currentMatrix.prepend(transform);
      }
      return transform.clone();
    }

    "use strict";
    function parseSVGFloatAttribute(svg, id, defaultValue) {
      const value = svg.getAttribute(id);
      return value ? Number(value) : defaultValue;
    }

    "use strict";
    function parseSVGDefinitions(svg, session) {
      const definitions = svg.querySelectorAll("defs");
      for (let i = 0; i < definitions.length; i++) {
        const definition = definitions[i];
        for (let j = 0; j < definition.children.length; j++) {
          const child = definition.children[j];
          switch (child.nodeName.toLowerCase()) {
            case "lineargradient":
              session.defs[child.id] = parseLinearGradient(child);
              break;
            case "radialgradient":
              session.defs[child.id] = parseRadialGradient(child);
              break;
            default:
              break;
          }
        }
      }
    }
    function parseLinearGradient(child) {
      const x0 = parseSVGFloatAttribute(child, "x1", 0);
      const y0 = parseSVGFloatAttribute(child, "y1", 0);
      const x1 = parseSVGFloatAttribute(child, "x2", 1);
      const y1 = parseSVGFloatAttribute(child, "y2", 0);
      const gradientUnit = child.getAttribute("gradientUnits") || "objectBoundingBox";
      const gradient = new FillGradient(
        x0,
        y0,
        x1,
        y1,
        gradientUnit === "objectBoundingBox" ? "local" : "global"
      );
      for (let k = 0; k < child.children.length; k++) {
        const stop = child.children[k];
        const offset = parseSVGFloatAttribute(stop, "offset", 0);
        const color = Color.shared.setValue(stop.getAttribute("stop-color")).toNumber();
        gradient.addColorStop(offset, color);
      }
      return gradient;
    }
    function parseRadialGradient(_child) {
      warn("[SVG Parser] Radial gradients are not yet supported");
      return new FillGradient(0, 0, 1, 0);
    }

    "use strict";
    function extractSvgUrlId(url) {
      const match = url.match(/url\s*\(\s*['"]?\s*#([^'"\s)]+)\s*['"]?\s*\)/i);
      return match ? match[1] : "";
    }

    "use strict";
    const styleAttributes = {
      // Fill properties
      fill: { type: "paint", default: 0 },
      // Fill color/gradient
      "fill-opacity": { type: "number", default: 1 },
      // Fill transparency
      // Stroke properties
      stroke: { type: "paint", default: 0 },
      // Stroke color/gradient
      "stroke-width": { type: "number", default: 1 },
      // Width of stroke
      "stroke-opacity": { type: "number", default: 1 },
      // Stroke transparency
      "stroke-linecap": { type: "string", default: "butt" },
      // End cap style: butt, round, square
      "stroke-linejoin": { type: "string", default: "miter" },
      // Join style: miter, round, bevel
      "stroke-miterlimit": { type: "number", default: 10 },
      // Limit on miter join sharpness
      "stroke-dasharray": { type: "string", default: "none" },
      // Dash pattern
      "stroke-dashoffset": { type: "number", default: 0 },
      // Offset for dash pattern
      // Global properties
      opacity: { type: "number", default: 1 }
      // Overall opacity
    };
    function parseSVGStyle(svg, session) {
      const style = svg.getAttribute("style");
      const strokeStyle = {};
      const fillStyle = {};
      const result = {
        strokeStyle,
        fillStyle,
        useFill: false,
        useStroke: false
      };
      for (const key in styleAttributes) {
        const attribute = svg.getAttribute(key);
        if (attribute) {
          parseAttribute(session, result, key, attribute.trim());
        }
      }
      if (style) {
        const styleParts = style.split(";");
        for (let i = 0; i < styleParts.length; i++) {
          const stylePart = styleParts[i].trim();
          const [key, value] = stylePart.split(":");
          if (styleAttributes[key]) {
            parseAttribute(session, result, key, value.trim());
          }
        }
      }
      return {
        strokeStyle: result.useStroke ? strokeStyle : null,
        fillStyle: result.useFill ? fillStyle : null,
        useFill: result.useFill,
        useStroke: result.useStroke
      };
    }
    function parseAttribute(session, result, id, value) {
      switch (id) {
        case "stroke":
          if (value !== "none") {
            if (value.startsWith("url(")) {
              const id2 = extractSvgUrlId(value);
              result.strokeStyle.fill = session.defs[id2];
            } else {
              result.strokeStyle.color = Color.shared.setValue(value).toNumber();
            }
            result.useStroke = true;
          }
          break;
        case "stroke-width":
          result.strokeStyle.width = Number(value);
          break;
        case "fill":
          if (value !== "none") {
            if (value.startsWith("url(")) {
              const id2 = extractSvgUrlId(value);
              result.fillStyle.fill = session.defs[id2];
            } else {
              result.fillStyle.color = Color.shared.setValue(value).toNumber();
            }
            result.useFill = true;
          }
          break;
        case "fill-opacity":
          result.fillStyle.alpha = Number(value);
          break;
        case "stroke-opacity":
          result.strokeStyle.alpha = Number(value);
          break;
        case "opacity":
          result.fillStyle.alpha = Number(value);
          result.strokeStyle.alpha = Number(value);
          break;
      }
    }

    "use strict";
    function checkForNestedPattern(subpathsWithArea) {
      if (subpathsWithArea.length <= 2) {
        return true;
      }
      const areas = subpathsWithArea.map((s) => s.area).sort((a, b) => b - a);
      const [largestArea, secondArea] = areas;
      const smallestArea = areas[areas.length - 1];
      const largestToSecondRatio = largestArea / secondArea;
      const secondToSmallestRatio = secondArea / smallestArea;
      if (largestToSecondRatio > 3 && secondToSmallestRatio < 2) {
        return false;
      }
      return true;
    }
    function getFillInstructionData(context, index = 0) {
      const instruction = context.instructions[index];
      if (!instruction || instruction.action !== "fill") {
        throw new Error(`Expected fill instruction at index ${index}, got ${(instruction == null ? void 0 : instruction.action) || "undefined"}`);
      }
      return instruction.data;
    }

    "use strict";
    function extractSubpaths(pathData) {
      const parts = pathData.split(/(?=[Mm])/);
      const subpaths = parts.filter((part) => part.trim().length > 0);
      return subpaths;
    }
    function calculatePathArea(pathData) {
      const coords = pathData.match(/[-+]?[0-9]*\.?[0-9]+/g);
      if (!coords || coords.length < 4)
        return 0;
      const numbers = coords.map(Number);
      const xs = [];
      const ys = [];
      for (let i = 0; i < numbers.length; i += 2) {
        if (i + 1 < numbers.length) {
          xs.push(numbers[i]);
          ys.push(numbers[i + 1]);
        }
      }
      if (xs.length === 0 || ys.length === 0)
        return 0;
      const minX = Math.min(...xs);
      const maxX = Math.max(...xs);
      const minY = Math.min(...ys);
      const maxY = Math.max(...ys);
      const area = (maxX - minX) * (maxY - minY);
      return area;
    }
    function appendSVGPath(pathData, graphicsPath) {
      const tempPath = new GraphicsPath(pathData, false);
      for (const instruction of tempPath.instructions) {
        graphicsPath.instructions.push(instruction);
      }
    }

    "use strict";
    var __defProp$Y = Object.defineProperty;
    var __getOwnPropSymbols$_ = Object.getOwnPropertySymbols;
    var __hasOwnProp$_ = Object.prototype.hasOwnProperty;
    var __propIsEnum$_ = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$Y = (obj, key, value) => key in obj ? __defProp$Y(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$Y = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$_.call(b, prop))
          __defNormalProp$Y(a, prop, b[prop]);
      if (__getOwnPropSymbols$_)
        for (var prop of __getOwnPropSymbols$_(b)) {
          if (__propIsEnum$_.call(b, prop))
            __defNormalProp$Y(a, prop, b[prop]);
        }
      return a;
    };
    function SVGParser(svg, graphicsContext) {
      if (typeof svg === "string") {
        const div = document.createElement("div");
        div.innerHTML = svg.trim();
        svg = div.querySelector("svg");
      }
      const session = {
        context: graphicsContext,
        defs: {},
        path: new GraphicsPath()
      };
      parseSVGDefinitions(svg, session);
      const children = svg.children;
      const { fillStyle, strokeStyle } = parseSVGStyle(svg, session);
      for (let i = 0; i < children.length; i++) {
        const child = children[i];
        if (child.nodeName.toLowerCase() === "defs")
          continue;
        renderChildren(child, session, fillStyle, strokeStyle);
      }
      return graphicsContext;
    }
    function renderChildren(svg, session, fillStyle, strokeStyle) {
      const children = svg.children;
      const { fillStyle: f1, strokeStyle: s1 } = parseSVGStyle(svg, session);
      if (f1 && fillStyle) {
        fillStyle = __spreadValues$Y(__spreadValues$Y({}, fillStyle), f1);
      } else if (f1) {
        fillStyle = f1;
      }
      if (s1 && strokeStyle) {
        strokeStyle = __spreadValues$Y(__spreadValues$Y({}, strokeStyle), s1);
      } else if (s1) {
        strokeStyle = s1;
      }
      const noStyle = !fillStyle && !strokeStyle;
      if (noStyle) {
        fillStyle = { color: 0 };
      }
      let x;
      let y;
      let x1;
      let y1;
      let x2;
      let y2;
      let cx;
      let cy;
      let r;
      let rx;
      let ry;
      let points;
      let pointsString;
      let d;
      let graphicsPath;
      let width;
      let height;
      switch (svg.nodeName.toLowerCase()) {
        case "path": {
          d = svg.getAttribute("d");
          const fillRule = svg.getAttribute("fill-rule");
          const subpaths = extractSubpaths(d);
          const hasExplicitEvenodd = fillRule === "evenodd";
          const hasMultipleSubpaths = subpaths.length > 1;
          const shouldProcessHoles = hasExplicitEvenodd && hasMultipleSubpaths;
          if (shouldProcessHoles) {
            const subpathsWithArea = subpaths.map((subpath) => ({
              path: subpath,
              area: calculatePathArea(subpath)
            }));
            subpathsWithArea.sort((a, b) => b.area - a.area);
            const useMultipleHolesApproach = subpaths.length > 3 || !checkForNestedPattern(subpathsWithArea);
            if (useMultipleHolesApproach) {
              for (let i = 0; i < subpathsWithArea.length; i++) {
                const subpath = subpathsWithArea[i];
                const isMainShape = i === 0;
                session.context.beginPath();
                const newPath = new GraphicsPath(void 0, true);
                appendSVGPath(subpath.path, newPath);
                session.context.path(newPath);
                if (isMainShape) {
                  if (fillStyle)
                    session.context.fill(fillStyle);
                  if (strokeStyle)
                    session.context.stroke(strokeStyle);
                } else {
                  session.context.cut();
                }
              }
            } else {
              for (let i = 0; i < subpathsWithArea.length; i++) {
                const subpath = subpathsWithArea[i];
                const isHole = i % 2 === 1;
                session.context.beginPath();
                const newPath = new GraphicsPath(void 0, true);
                appendSVGPath(subpath.path, newPath);
                session.context.path(newPath);
                if (isHole) {
                  session.context.cut();
                } else {
                  if (fillStyle)
                    session.context.fill(fillStyle);
                  if (strokeStyle)
                    session.context.stroke(strokeStyle);
                }
              }
            }
          } else {
            const useEvenoddForGraphicsPath = fillRule ? fillRule === "evenodd" : true;
            graphicsPath = new GraphicsPath(d, useEvenoddForGraphicsPath);
            session.context.path(graphicsPath);
            if (fillStyle)
              session.context.fill(fillStyle);
            if (strokeStyle)
              session.context.stroke(strokeStyle);
          }
          break;
        }
        case "circle":
          cx = parseSVGFloatAttribute(svg, "cx", 0);
          cy = parseSVGFloatAttribute(svg, "cy", 0);
          r = parseSVGFloatAttribute(svg, "r", 0);
          session.context.ellipse(cx, cy, r, r);
          if (fillStyle)
            session.context.fill(fillStyle);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "rect":
          x = parseSVGFloatAttribute(svg, "x", 0);
          y = parseSVGFloatAttribute(svg, "y", 0);
          width = parseSVGFloatAttribute(svg, "width", 0);
          height = parseSVGFloatAttribute(svg, "height", 0);
          rx = parseSVGFloatAttribute(svg, "rx", 0);
          ry = parseSVGFloatAttribute(svg, "ry", 0);
          if (rx || ry) {
            session.context.roundRect(x, y, width, height, rx || ry);
          } else {
            session.context.rect(x, y, width, height);
          }
          if (fillStyle)
            session.context.fill(fillStyle);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "ellipse":
          cx = parseSVGFloatAttribute(svg, "cx", 0);
          cy = parseSVGFloatAttribute(svg, "cy", 0);
          rx = parseSVGFloatAttribute(svg, "rx", 0);
          ry = parseSVGFloatAttribute(svg, "ry", 0);
          session.context.beginPath();
          session.context.ellipse(cx, cy, rx, ry);
          if (fillStyle)
            session.context.fill(fillStyle);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "line":
          x1 = parseSVGFloatAttribute(svg, "x1", 0);
          y1 = parseSVGFloatAttribute(svg, "y1", 0);
          x2 = parseSVGFloatAttribute(svg, "x2", 0);
          y2 = parseSVGFloatAttribute(svg, "y2", 0);
          session.context.beginPath();
          session.context.moveTo(x1, y1);
          session.context.lineTo(x2, y2);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "polygon":
          pointsString = svg.getAttribute("points");
          points = pointsString.match(/-?\d+/g).map((n) => parseInt(n, 10));
          session.context.poly(points, true);
          if (fillStyle)
            session.context.fill(fillStyle);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "polyline":
          pointsString = svg.getAttribute("points");
          points = pointsString.match(/-?\d+/g).map((n) => parseInt(n, 10));
          session.context.poly(points, false);
          if (strokeStyle)
            session.context.stroke(strokeStyle);
          break;
        case "g":
        case "svg":
          break;
        default: {
          warn(`[SVG parser] <${svg.nodeName}> elements unsupported`);
          break;
        }
      }
      if (noStyle) {
        fillStyle = null;
      }
      for (let i = 0; i < children.length; i++) {
        renderChildren(children[i], session, fillStyle, strokeStyle);
      }
    }

    "use strict";
    var __defProp$X = Object.defineProperty;
    var __getOwnPropSymbols$Z = Object.getOwnPropertySymbols;
    var __hasOwnProp$Z = Object.prototype.hasOwnProperty;
    var __propIsEnum$Z = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$X = (obj, key, value) => key in obj ? __defProp$X(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$X = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$Z.call(b, prop))
          __defNormalProp$X(a, prop, b[prop]);
      if (__getOwnPropSymbols$Z)
        for (var prop of __getOwnPropSymbols$Z(b)) {
          if (__propIsEnum$Z.call(b, prop))
            __defNormalProp$X(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$l = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$Z.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$Z)
        for (var prop of __getOwnPropSymbols$Z(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$Z.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    function isColorLike(value) {
      return Color.isColorLike(value);
    }
    function isFillPattern(value) {
      return value instanceof FillPattern;
    }
    function isFillGradient(value) {
      return value instanceof FillGradient;
    }
    function isTexture(value) {
      return value instanceof Texture;
    }
    function handleColorLike(fill, value, defaultStyle) {
      const temp = Color.shared.setValue(value != null ? value : 0);
      fill.color = temp.toNumber();
      fill.alpha = temp.alpha === 1 ? defaultStyle.alpha : temp.alpha;
      fill.texture = Texture.WHITE;
      return __spreadValues$X(__spreadValues$X({}, defaultStyle), fill);
    }
    function handleTexture(fill, value, defaultStyle) {
      fill.texture = value;
      return __spreadValues$X(__spreadValues$X({}, defaultStyle), fill);
    }
    function handleFillPattern(fill, value, defaultStyle) {
      fill.fill = value;
      fill.color = 16777215;
      fill.texture = value.texture;
      fill.matrix = value.transform;
      return __spreadValues$X(__spreadValues$X({}, defaultStyle), fill);
    }
    function handleFillGradient(fill, value, defaultStyle) {
      value.buildGradient();
      fill.fill = value;
      fill.color = 16777215;
      fill.texture = value.texture;
      fill.matrix = value.transform;
      fill.textureSpace = value.textureSpace;
      return __spreadValues$X(__spreadValues$X({}, defaultStyle), fill);
    }
    function handleFillObject(value, defaultStyle) {
      const style = __spreadValues$X(__spreadValues$X({}, defaultStyle), value);
      const color = Color.shared.setValue(style.color);
      style.alpha *= color.alpha;
      style.color = color.toNumber();
      return style;
    }
    function toFillStyle(value, defaultStyle) {
      if (value === void 0 || value === null) {
        return null;
      }
      const fill = {};
      const objectStyle = value;
      if (isColorLike(value)) {
        return handleColorLike(fill, value, defaultStyle);
      } else if (isTexture(value)) {
        return handleTexture(fill, value, defaultStyle);
      } else if (isFillPattern(value)) {
        return handleFillPattern(fill, value, defaultStyle);
      } else if (isFillGradient(value)) {
        return handleFillGradient(fill, value, defaultStyle);
      } else if (objectStyle.fill && isFillPattern(objectStyle.fill)) {
        return handleFillPattern(objectStyle, objectStyle.fill, defaultStyle);
      } else if (objectStyle.fill && isFillGradient(objectStyle.fill)) {
        return handleFillGradient(objectStyle, objectStyle.fill, defaultStyle);
      }
      return handleFillObject(objectStyle, defaultStyle);
    }
    function toStrokeStyle(value, defaultStyle) {
      const _a = defaultStyle, { width, alignment, miterLimit, cap, join, pixelLine } = _a, rest = __objRest$l(_a, ["width", "alignment", "miterLimit", "cap", "join", "pixelLine"]);
      const fill = toFillStyle(value, rest);
      if (!fill) {
        return null;
      }
      return __spreadValues$X({
        width,
        alignment,
        miterLimit,
        cap,
        join,
        pixelLine
      }, fill);
    }

    "use strict";
    var __defProp$W = Object.defineProperty;
    var __getOwnPropSymbols$Y = Object.getOwnPropertySymbols;
    var __hasOwnProp$Y = Object.prototype.hasOwnProperty;
    var __propIsEnum$Y = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$W = (obj, key, value) => key in obj ? __defProp$W(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$W = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$Y.call(b, prop))
          __defNormalProp$W(a, prop, b[prop]);
      if (__getOwnPropSymbols$Y)
        for (var prop of __getOwnPropSymbols$Y(b)) {
          if (__propIsEnum$Y.call(b, prop))
            __defNormalProp$W(a, prop, b[prop]);
        }
      return a;
    };
    const tmpPoint = new Point();
    const tempMatrix$3 = new Matrix();
    const _GraphicsContext = class _GraphicsContext extends EventEmitter {
      constructor() {
        super(...arguments);
        /** @internal */
        this._gpuData = /* @__PURE__ */ Object.create(null);
        /** If set to true, the resource will be garbage collected automatically when it is not used. */
        this.autoGarbageCollect = true;
        /** @internal */
        this._gcLastUsed = -1;
        /**
         * unique id for this graphics context
         * @internal
         */
        this.uid = uid$1("graphicsContext");
        /**
         * Indicates whether content is updated and have to be re-rendered.
         * @internal
         */
        this.dirty = true;
        /** The batch mode for this graphics context. It can be 'auto', 'batch', or 'no-batch'. */
        this.batchMode = "auto";
        /** @internal */
        this.instructions = [];
        /** Whether the graphics context has been destroyed. */
        this.destroyed = false;
        this._activePath = new GraphicsPath();
        this._transform = new Matrix();
        this._fillStyle = __spreadValues$W({}, _GraphicsContext.defaultFillStyle);
        this._strokeStyle = __spreadValues$W({}, _GraphicsContext.defaultStrokeStyle);
        this._stateStack = [];
        this._tick = 0;
        this._bounds = new Bounds();
        this._boundsDirty = true;
      }
      /**
       * Creates a new GraphicsContext object that is a clone of this instance, copying all properties,
       * including the current drawing state, transformations, styles, and instructions.
       * @returns A new GraphicsContext instance with the same properties and state as this one.
       */
      clone() {
        const clone = new _GraphicsContext();
        clone.batchMode = this.batchMode;
        clone.instructions = this.instructions.slice();
        clone._activePath = this._activePath.clone();
        clone._transform = this._transform.clone();
        clone._fillStyle = __spreadValues$W({}, this._fillStyle);
        clone._strokeStyle = __spreadValues$W({}, this._strokeStyle);
        clone._stateStack = this._stateStack.slice();
        clone._bounds = this._bounds.clone();
        clone._boundsDirty = true;
        return clone;
      }
      /**
       * The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object.
       */
      get fillStyle() {
        return this._fillStyle;
      }
      set fillStyle(value) {
        this._fillStyle = toFillStyle(value, _GraphicsContext.defaultFillStyle);
      }
      /**
       * The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
       */
      get strokeStyle() {
        return this._strokeStyle;
      }
      set strokeStyle(value) {
        this._strokeStyle = toStrokeStyle(value, _GraphicsContext.defaultStrokeStyle);
      }
      /**
       * Sets the current fill style of the graphics context. The fill style can be a color, gradient,
       * pattern, or a more complex style defined by a FillStyle object.
       * @param style - The fill style to apply. This can be a simple color, a gradient or pattern object,
       *                or a FillStyle or ConvertedFillStyle object.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      setFillStyle(style) {
        this._fillStyle = toFillStyle(style, _GraphicsContext.defaultFillStyle);
        return this;
      }
      /**
       * Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
       * encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
       * @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern,
       *                or a StrokeStyle or ConvertedStrokeStyle object.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      setStrokeStyle(style) {
        this._strokeStyle = toFillStyle(style, _GraphicsContext.defaultStrokeStyle);
        return this;
      }
      texture(texture, tint, dx, dy, dw, dh) {
        this.instructions.push({
          action: "texture",
          data: {
            image: texture,
            dx: dx || 0,
            dy: dy || 0,
            dw: dw || texture.frame.width,
            dh: dh || texture.frame.height,
            transform: this._transform.clone(),
            alpha: this._fillStyle.alpha,
            style: tint ? Color.shared.setValue(tint).toNumber() : 16777215
          }
        });
        this.onUpdate();
        return this;
      }
      /**
       * Resets the current path. Any previous path and its commands are discarded and a new path is
       * started. This is typically called before beginning a new shape or series of drawing commands.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      beginPath() {
        this._activePath = new GraphicsPath();
        return this;
      }
      fill(style, alpha) {
        let path;
        const lastInstruction = this.instructions[this.instructions.length - 1];
        if (this._tick === 0 && (lastInstruction == null ? void 0 : lastInstruction.action) === "stroke") {
          path = lastInstruction.data.path;
        } else {
          path = this._activePath.clone();
        }
        if (!path)
          return this;
        if (style != null) {
          if (alpha !== void 0 && typeof style === "number") {
            deprecation(v8_0_0, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead");
            style = { color: style, alpha };
          }
          this._fillStyle = toFillStyle(style, _GraphicsContext.defaultFillStyle);
        }
        this.instructions.push({
          action: "fill",
          // TODO copy fill style!
          data: { style: this.fillStyle, path }
        });
        this.onUpdate();
        this._initNextPathLocation();
        this._tick = 0;
        return this;
      }
      _initNextPathLocation() {
        const { x, y } = this._activePath.getLastPoint(Point.shared);
        this._activePath.clear();
        this._activePath.moveTo(x, y);
      }
      /**
       * Strokes the current path with the current stroke style. This method can take an optional
       * FillInput parameter to define the stroke's appearance, including its color, width, and other properties.
       * @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      stroke(style) {
        let path;
        const lastInstruction = this.instructions[this.instructions.length - 1];
        if (this._tick === 0 && (lastInstruction == null ? void 0 : lastInstruction.action) === "fill") {
          path = lastInstruction.data.path;
        } else {
          path = this._activePath.clone();
        }
        if (!path)
          return this;
        if (style != null) {
          this._strokeStyle = toStrokeStyle(style, _GraphicsContext.defaultStrokeStyle);
        }
        this.instructions.push({
          action: "stroke",
          // TODO copy fill style!
          data: { style: this.strokeStyle, path }
        });
        this.onUpdate();
        this._initNextPathLocation();
        this._tick = 0;
        return this;
      }
      /**
       * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
       * subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
       * fail to cut correctly!
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      cut() {
        for (let i = 0; i < 2; i++) {
          const lastInstruction = this.instructions[this.instructions.length - 1 - i];
          const holePath = this._activePath.clone();
          if (lastInstruction) {
            if (lastInstruction.action === "stroke" || lastInstruction.action === "fill") {
              if (lastInstruction.data.hole) {
                lastInstruction.data.hole.addPath(holePath);
              } else {
                lastInstruction.data.hole = holePath;
                break;
              }
            }
          }
        }
        this._initNextPathLocation();
        return this;
      }
      /**
       * Adds an arc to the current path, which is centered at (x, y) with the specified radius,
       * starting and ending angles, and direction.
       * @param x - The x-coordinate of the arc's center.
       * @param y - The y-coordinate of the arc's center.
       * @param radius - The arc's radius.
       * @param startAngle - The starting angle, in radians.
       * @param endAngle - The ending angle, in radians.
       * @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      arc(x, y, radius, startAngle, endAngle, counterclockwise) {
        this._tick++;
        const t = this._transform;
        this._activePath.arc(
          t.a * x + t.c * y + t.tx,
          t.b * x + t.d * y + t.ty,
          radius,
          startAngle,
          endAngle,
          counterclockwise
        );
        return this;
      }
      /**
       * Adds an arc to the current path with the given control points and radius, connected to the previous point
       * by a straight line if necessary.
       * @param x1 - The x-coordinate of the first control point.
       * @param y1 - The y-coordinate of the first control point.
       * @param x2 - The x-coordinate of the second control point.
       * @param y2 - The y-coordinate of the second control point.
       * @param radius - The arc's radius.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      arcTo(x1, y1, x2, y2, radius) {
        this._tick++;
        const t = this._transform;
        this._activePath.arcTo(
          t.a * x1 + t.c * y1 + t.tx,
          t.b * x1 + t.d * y1 + t.ty,
          t.a * x2 + t.c * y2 + t.tx,
          t.b * x2 + t.d * y2 + t.ty,
          radius
        );
        return this;
      }
      /**
       * Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
       * @param rx - The x-radius of the ellipse.
       * @param ry - The y-radius of the ellipse.
       * @param xAxisRotation - The rotation of the ellipse's x-axis relative
       * to the x-axis of the coordinate system, in degrees.
       * @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
       * @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
       * @param x - The x-coordinate of the arc's end point.
       * @param y - The y-coordinate of the arc's end point.
       * @returns The instance of the current object for chaining.
       */
      arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
        this._tick++;
        const t = this._transform;
        this._activePath.arcToSvg(
          rx,
          ry,
          xAxisRotation,
          // should we rotate this with transform??
          largeArcFlag,
          sweepFlag,
          t.a * x + t.c * y + t.tx,
          t.b * x + t.d * y + t.ty
        );
        return this;
      }
      /**
       * Adds a cubic Bezier curve to the path.
       * It requires three points: the first two are control points and the third one is the end point.
       * The starting point is the last point in the current path.
       * @param cp1x - The x-coordinate of the first control point.
       * @param cp1y - The y-coordinate of the first control point.
       * @param cp2x - The x-coordinate of the second control point.
       * @param cp2y - The y-coordinate of the second control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothness - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
        this._tick++;
        const t = this._transform;
        this._activePath.bezierCurveTo(
          t.a * cp1x + t.c * cp1y + t.tx,
          t.b * cp1x + t.d * cp1y + t.ty,
          t.a * cp2x + t.c * cp2y + t.tx,
          t.b * cp2x + t.d * cp2y + t.ty,
          t.a * x + t.c * y + t.tx,
          t.b * x + t.d * y + t.ty,
          smoothness
        );
        return this;
      }
      /**
       * Closes the current path by drawing a straight line back to the start.
       * If the shape is already closed or there are no points in the path, this method does nothing.
       * @returns The instance of the current object for chaining.
       */
      closePath() {
        var _a;
        this._tick++;
        (_a = this._activePath) == null ? void 0 : _a.closePath();
        return this;
      }
      /**
       * Draws an ellipse at the specified location and with the given x and y radii.
       * An optional transformation can be applied, allowing for rotation, scaling, and translation.
       * @param x - The x-coordinate of the center of the ellipse.
       * @param y - The y-coordinate of the center of the ellipse.
       * @param radiusX - The horizontal radius of the ellipse.
       * @param radiusY - The vertical radius of the ellipse.
       * @returns The instance of the current object for chaining.
       */
      ellipse(x, y, radiusX, radiusY) {
        this._tick++;
        this._activePath.ellipse(x, y, radiusX, radiusY, this._transform.clone());
        return this;
      }
      /**
       * Draws a circle shape. This method adds a new circle path to the current drawing.
       * @param x - The x-coordinate of the center of the circle.
       * @param y - The y-coordinate of the center of the circle.
       * @param radius - The radius of the circle.
       * @returns The instance of the current object for chaining.
       */
      circle(x, y, radius) {
        this._tick++;
        this._activePath.circle(x, y, radius, this._transform.clone());
        return this;
      }
      /**
       * Adds another `GraphicsPath` to this path, optionally applying a transformation.
       * @param path - The `GraphicsPath` to add.
       * @returns The instance of the current object for chaining.
       */
      path(path) {
        this._tick++;
        this._activePath.addPath(path, this._transform.clone());
        return this;
      }
      /**
       * Connects the current point to a new point with a straight line. This method updates the current path.
       * @param x - The x-coordinate of the new point to connect to.
       * @param y - The y-coordinate of the new point to connect to.
       * @returns The instance of the current object for chaining.
       */
      lineTo(x, y) {
        this._tick++;
        const t = this._transform;
        this._activePath.lineTo(
          t.a * x + t.c * y + t.tx,
          t.b * x + t.d * y + t.ty
        );
        return this;
      }
      /**
       * Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
       * @param x - The x-coordinate for the starting point.
       * @param y - The y-coordinate for the starting point.
       * @returns The instance of the current object for chaining.
       */
      moveTo(x, y) {
        this._tick++;
        const t = this._transform;
        const instructions = this._activePath.instructions;
        const transformedX = t.a * x + t.c * y + t.tx;
        const transformedY = t.b * x + t.d * y + t.ty;
        if (instructions.length === 1 && instructions[0].action === "moveTo") {
          instructions[0].data[0] = transformedX;
          instructions[0].data[1] = transformedY;
          return this;
        }
        this._activePath.moveTo(
          transformedX,
          transformedY
        );
        return this;
      }
      /**
       * Adds a quadratic curve to the path. It requires two points: the control point and the end point.
       * The starting point is the last point in the current path.
       * @param cpx - The x-coordinate of the control point.
       * @param cpy - The y-coordinate of the control point.
       * @param x - The x-coordinate of the end point.
       * @param y - The y-coordinate of the end point.
       * @param smoothness - Optional parameter to adjust the smoothness of the curve.
       * @returns The instance of the current object for chaining.
       */
      quadraticCurveTo(cpx, cpy, x, y, smoothness) {
        this._tick++;
        const t = this._transform;
        this._activePath.quadraticCurveTo(
          t.a * cpx + t.c * cpy + t.tx,
          t.b * cpx + t.d * cpy + t.ty,
          t.a * x + t.c * y + t.tx,
          t.b * x + t.d * y + t.ty,
          smoothness
        );
        return this;
      }
      /**
       * Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
       * @param x - The x-coordinate of the top-left corner of the rectangle.
       * @param y - The y-coordinate of the top-left corner of the rectangle.
       * @param w - The width of the rectangle.
       * @param h - The height of the rectangle.
       * @returns The instance of the current object for chaining.
       */
      rect(x, y, w, h) {
        this._tick++;
        this._activePath.rect(x, y, w, h, this._transform.clone());
        return this;
      }
      /**
       * Draws a rectangle with rounded corners.
       * The corner radius can be specified to determine how rounded the corners should be.
       * An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
       * @param x - The x-coordinate of the top-left corner of the rectangle.
       * @param y - The y-coordinate of the top-left corner of the rectangle.
       * @param w - The width of the rectangle.
       * @param h - The height of the rectangle.
       * @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
       * @returns The instance of the current object for chaining.
       */
      roundRect(x, y, w, h, radius) {
        this._tick++;
        this._activePath.roundRect(x, y, w, h, radius, this._transform.clone());
        return this;
      }
      /**
       * Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
       * which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
       * rotated, or translated as needed.
       * @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
       * representing the x and y coordinates, of the polygon's vertices, in sequence.
       * @param close - A boolean indicating whether to close the polygon path. True by default.
       */
      poly(points, close) {
        this._tick++;
        this._activePath.poly(points, close, this._transform.clone());
        return this;
      }
      /**
       * Draws a regular polygon with a specified number of sides. All sides and angles are equal.
       * @param x - The x-coordinate of the center of the polygon.
       * @param y - The y-coordinate of the center of the polygon.
       * @param radius - The radius of the circumscribed circle of the polygon.
       * @param sides - The number of sides of the polygon. Must be 3 or more.
       * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
       * @param transform - An optional `Matrix` object to apply a transformation to the polygon.
       * @returns The instance of the current object for chaining.
       */
      regularPoly(x, y, radius, sides, rotation = 0, transform) {
        this._tick++;
        this._activePath.regularPoly(x, y, radius, sides, rotation, transform);
        return this;
      }
      /**
       * Draws a polygon with rounded corners.
       * Similar to `regularPoly` but with the ability to round the corners of the polygon.
       * @param x - The x-coordinate of the center of the polygon.
       * @param y - The y-coordinate of the center of the polygon.
       * @param radius - The radius of the circumscribed circle of the polygon.
       * @param sides - The number of sides of the polygon. Must be 3 or more.
       * @param corner - The radius of the rounding of the corners.
       * @param rotation - The rotation angle of the polygon, in radians. Zero by default.
       * @returns The instance of the current object for chaining.
       */
      roundPoly(x, y, radius, sides, corner, rotation) {
        this._tick++;
        this._activePath.roundPoly(x, y, radius, sides, corner, rotation);
        return this;
      }
      /**
       * Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
       * Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
       * @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
       * A minimum of 3 points is required.
       * @param radius - The default radius for the corners.
       * This radius is applied to all corners unless overridden in `points`.
       * @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
       *  method instead of an arc method. Defaults to false.
       * @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
       * Higher values make the curve smoother.
       * @returns The instance of the current object for chaining.
       */
      roundShape(points, radius, useQuadratic, smoothness) {
        this._tick++;
        this._activePath.roundShape(points, radius, useQuadratic, smoothness);
        return this;
      }
      /**
       * Draw Rectangle with fillet corners. This is much like rounded rectangle
       * however it support negative numbers as well for the corner radius.
       * @param x - Upper left corner of rect
       * @param y - Upper right corner of rect
       * @param width - Width of rect
       * @param height - Height of rect
       * @param fillet - accept negative or positive values
       */
      filletRect(x, y, width, height, fillet) {
        this._tick++;
        this._activePath.filletRect(x, y, width, height, fillet);
        return this;
      }
      /**
       * Draw Rectangle with chamfer corners. These are angled corners.
       * @param x - Upper left corner of rect
       * @param y - Upper right corner of rect
       * @param width - Width of rect
       * @param height - Height of rect
       * @param chamfer - non-zero real number, size of corner cutout
       * @param transform
       */
      chamferRect(x, y, width, height, chamfer, transform) {
        this._tick++;
        this._activePath.chamferRect(x, y, width, height, chamfer, transform);
        return this;
      }
      /**
       * Draws a star shape centered at a specified location. This method allows for the creation
       *  of stars with a variable number of points, outer radius, optional inner radius, and rotation.
       * The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
       * An optional transformation can be applied to scale, rotate, or translate the star as needed.
       * @param x - The x-coordinate of the center of the star.
       * @param y - The y-coordinate of the center of the star.
       * @param points - The number of points of the star.
       * @param radius - The outer radius of the star (distance from the center to the outer points).
       * @param innerRadius - Optional. The inner radius of the star
       * (distance from the center to the inner points between the outer points).
       * If not provided, defaults to half of the `radius`.
       * @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
       * Defaults to 0, meaning one point is directly upward.
       * @returns The instance of the current object for chaining further drawing commands.
       */
      star(x, y, points, radius, innerRadius = 0, rotation = 0) {
        this._tick++;
        this._activePath.star(x, y, points, radius, innerRadius, rotation, this._transform.clone());
        return this;
      }
      /**
       * Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
       * defined in SVG format to be drawn within the graphics context.
       * @param svg - The SVG string to be parsed and rendered.
       */
      svg(svg) {
        this._tick++;
        SVGParser(svg, this);
        return this;
      }
      /**
       * Restores the most recently saved graphics state by popping the top of the graphics state stack.
       * This includes transformations, fill styles, and stroke styles.
       */
      restore() {
        const state = this._stateStack.pop();
        if (state) {
          this._transform = state.transform;
          this._fillStyle = state.fillStyle;
          this._strokeStyle = state.strokeStyle;
        }
        return this;
      }
      /** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
      save() {
        this._stateStack.push({
          transform: this._transform.clone(),
          fillStyle: __spreadValues$W({}, this._fillStyle),
          strokeStyle: __spreadValues$W({}, this._strokeStyle)
        });
        return this;
      }
      /**
       * Returns the current transformation matrix of the graphics context.
       * @returns The current transformation matrix.
       */
      getTransform() {
        return this._transform;
      }
      /**
       * Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      resetTransform() {
        this._transform.identity();
        return this;
      }
      /**
       * Applies a rotation transformation to the graphics context around the current origin.
       * @param angle - The angle of rotation in radians.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      rotate(angle) {
        this._transform.rotate(angle);
        return this;
      }
      /**
       * Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
       * @param x - The scale factor in the horizontal direction.
       * @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      scale(x, y = x) {
        this._transform.scale(x, y);
        return this;
      }
      setTransform(a, b, c, d, dx, dy) {
        if (a instanceof Matrix) {
          this._transform.set(a.a, a.b, a.c, a.d, a.tx, a.ty);
          return this;
        }
        this._transform.set(a, b, c, d, dx, dy);
        return this;
      }
      transform(a, b, c, d, dx, dy) {
        if (a instanceof Matrix) {
          this._transform.append(a);
          return this;
        }
        tempMatrix$3.set(a, b, c, d, dx, dy);
        this._transform.append(tempMatrix$3);
        return this;
      }
      /**
       * Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
       * @param x - The amount to translate in the horizontal direction.
       * @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      translate(x, y = x) {
        this._transform.translate(x, y);
        return this;
      }
      /**
       * Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
       * and optionally resetting transformations to the identity matrix.
       * @returns The instance of the current GraphicsContext for method chaining.
       */
      clear() {
        this._activePath.clear();
        this.instructions.length = 0;
        this.resetTransform();
        this.onUpdate();
        return this;
      }
      onUpdate() {
        this._boundsDirty = true;
        if (this.dirty)
          return;
        this.emit("update", this, 16);
        this.dirty = true;
      }
      /** The bounds of the graphic shape. */
      get bounds() {
        if (!this._boundsDirty)
          return this._bounds;
        this._boundsDirty = false;
        const bounds = this._bounds;
        bounds.clear();
        for (let i = 0; i < this.instructions.length; i++) {
          const instruction = this.instructions[i];
          const action = instruction.action;
          if (action === "fill") {
            const data = instruction.data;
            bounds.addBounds(data.path.bounds);
          } else if (action === "texture") {
            const data = instruction.data;
            bounds.addFrame(data.dx, data.dy, data.dx + data.dw, data.dy + data.dh, data.transform);
          }
          if (action === "stroke") {
            const data = instruction.data;
            const alignment = data.style.alignment;
            const outerPadding = data.style.width * (1 - alignment);
            const _bounds = data.path.bounds;
            bounds.addFrame(
              _bounds.minX - outerPadding,
              _bounds.minY - outerPadding,
              _bounds.maxX + outerPadding,
              _bounds.maxY + outerPadding
            );
          }
        }
        return bounds;
      }
      /**
       * Check to see if a point is contained within this geometry.
       * @param point - Point to check if it's contained.
       * @returns {boolean} `true` if the point is contained within geometry.
       */
      containsPoint(point) {
        var _a;
        if (!this.bounds.containsPoint(point.x, point.y))
          return false;
        const instructions = this.instructions;
        let hasHit = false;
        for (let k = 0; k < instructions.length; k++) {
          const instruction = instructions[k];
          const data = instruction.data;
          const path = data.path;
          if (!instruction.action || !path)
            continue;
          const style = data.style;
          const shapes = path.shapePath.shapePrimitives;
          for (let i = 0; i < shapes.length; i++) {
            const shape = shapes[i].shape;
            if (!style || !shape)
              continue;
            const transform = shapes[i].transform;
            const transformedPoint = transform ? transform.applyInverse(point, tmpPoint) : point;
            if (instruction.action === "fill") {
              hasHit = shape.contains(transformedPoint.x, transformedPoint.y);
            } else {
              const strokeStyle = style;
              hasHit = shape.strokeContains(transformedPoint.x, transformedPoint.y, strokeStyle.width, strokeStyle.alignment);
            }
            const holes = data.hole;
            if (holes) {
              const holeShapes = (_a = holes.shapePath) == null ? void 0 : _a.shapePrimitives;
              if (holeShapes) {
                for (let j = 0; j < holeShapes.length; j++) {
                  if (holeShapes[j].shape.contains(transformedPoint.x, transformedPoint.y)) {
                    hasHit = false;
                  }
                }
              }
            }
            if (hasHit) {
              return true;
            }
          }
        }
        return hasHit;
      }
      /** Unloads the GPU data from the graphics context. */
      unload() {
        var _a;
        this.emit("unload", this);
        for (const key in this._gpuData) {
          (_a = this._gpuData[key]) == null ? void 0 : _a.destroy();
        }
        this._gpuData = /* @__PURE__ */ Object.create(null);
      }
      /**
       * Destroys the GraphicsData object.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * context.destroy();
       * context.destroy(true);
       * context.destroy({ texture: true, textureSource: true });
       */
      destroy(options = false) {
        if (this.destroyed)
          return;
        this.destroyed = true;
        this._stateStack.length = 0;
        this._transform = null;
        this.unload();
        this.emit("destroy", this);
        this.removeAllListeners();
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          if (this._fillStyle.texture) {
            this._fillStyle.fill && "uid" in this._fillStyle.fill ? this._fillStyle.fill.destroy() : this._fillStyle.texture.destroy(destroyTextureSource);
          }
          if (this._strokeStyle.texture) {
            this._strokeStyle.fill && "uid" in this._strokeStyle.fill ? this._strokeStyle.fill.destroy() : this._strokeStyle.texture.destroy(destroyTextureSource);
          }
        }
        this._fillStyle = null;
        this._strokeStyle = null;
        this.instructions = null;
        this._activePath = null;
        this._bounds = null;
        this._stateStack = null;
        this.customShader = null;
        this._transform = null;
      }
    };
    /** The default fill style to use when none is provided. */
    _GraphicsContext.defaultFillStyle = {
      /** The color to use for the fill. */
      color: 16777215,
      /** The alpha value to use for the fill. */
      alpha: 1,
      /** The texture to use for the fill. */
      texture: Texture.WHITE,
      /** The matrix to apply. */
      matrix: null,
      /** The fill pattern to use. */
      fill: null,
      /** Whether coordinates are 'global' or 'local' */
      textureSpace: "local"
    };
    /** The default stroke style to use when none is provided. */
    _GraphicsContext.defaultStrokeStyle = {
      /** The width of the stroke. */
      width: 1,
      /** The color to use for the stroke. */
      color: 16777215,
      /** The alpha value to use for the stroke. */
      alpha: 1,
      /** The alignment of the stroke. */
      alignment: 0.5,
      /** The miter limit to use. */
      miterLimit: 10,
      /** The line cap style to use. */
      cap: "butt",
      /** The line join style to use. */
      join: "miter",
      /** The texture to use for the fill. */
      texture: Texture.WHITE,
      /** The matrix to apply. */
      matrix: null,
      /** The fill pattern to use. */
      fill: null,
      /** Whether coordinates are 'global' or 'local' */
      textureSpace: "local",
      /** If the stroke is a pixel line. */
      pixelLine: false
    };
    let GraphicsContext = _GraphicsContext;

    "use strict";
    var __defProp$V = Object.defineProperty;
    var __defProps$o = Object.defineProperties;
    var __getOwnPropDescs$o = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$X = Object.getOwnPropertySymbols;
    var __hasOwnProp$X = Object.prototype.hasOwnProperty;
    var __propIsEnum$X = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$V = (obj, key, value) => key in obj ? __defProp$V(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$V = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$X.call(b, prop))
          __defNormalProp$V(a, prop, b[prop]);
      if (__getOwnPropSymbols$X)
        for (var prop of __getOwnPropSymbols$X(b)) {
          if (__propIsEnum$X.call(b, prop))
            __defNormalProp$V(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$o = (a, b) => __defProps$o(a, __getOwnPropDescs$o(b));
    const _TextStyle = class _TextStyle extends EventEmitter {
      constructor(style = {}) {
        super();
        /**
         * Unique identifier for the TextStyle class.
         * This is used to track instances and ensure uniqueness.
         * @internal
         */
        this.uid = uid$1("textStyle");
        /**
         * Internal tick counter used to track updates and changes.
         * This is incremented whenever the style is modified, allowing for efficient change detection.
         * @internal
         */
        this._tick = 0;
        convertV7Tov8Style(style);
        const fullStyle = __spreadValues$V(__spreadValues$V({}, _TextStyle.defaultTextStyle), style);
        for (const key in fullStyle) {
          const thisKey = key;
          this[thisKey] = fullStyle[key];
        }
        this.update();
        this._tick = 0;
      }
      /**
       * Alignment for multiline text, does not affect single line text.
       * @type {'left'|'center'|'right'|'justify'}
       */
      get align() {
        return this._align;
      }
      set align(value) {
        if (this._align === value)
          return;
        this._align = value;
        this.update();
      }
      /** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
      get breakWords() {
        return this._breakWords;
      }
      set breakWords(value) {
        if (this._breakWords === value)
          return;
        this._breakWords = value;
        this.update();
      }
      /** Set a drop shadow for the text. */
      get dropShadow() {
        return this._dropShadow;
      }
      set dropShadow(value) {
        if (this._dropShadow === value)
          return;
        if (value !== null && typeof value === "object") {
          this._dropShadow = this._createProxy(__spreadValues$V(__spreadValues$V({}, _TextStyle.defaultDropShadow), value));
        } else {
          this._dropShadow = value ? this._createProxy(__spreadValues$V({}, _TextStyle.defaultDropShadow)) : null;
        }
        this.update();
      }
      /** The font family, can be a single font name, or a list of names where the first is the preferred font. */
      get fontFamily() {
        return this._fontFamily;
      }
      set fontFamily(value) {
        if (this._fontFamily === value)
          return;
        this._fontFamily = value;
        this.update();
      }
      /** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
      get fontSize() {
        return this._fontSize;
      }
      set fontSize(value) {
        if (this._fontSize === value)
          return;
        if (typeof value === "string") {
          this._fontSize = parseInt(value, 10);
        } else {
          this._fontSize = value;
        }
        this.update();
      }
      /**
       * The font style.
       * @type {'normal'|'italic'|'oblique'}
       */
      get fontStyle() {
        return this._fontStyle;
      }
      set fontStyle(value) {
        if (this._fontStyle === value)
          return;
        this._fontStyle = value.toLowerCase();
        this.update();
      }
      /**
       * The font variant.
       * @type {'normal'|'small-caps'}
       */
      get fontVariant() {
        return this._fontVariant;
      }
      set fontVariant(value) {
        if (this._fontVariant === value)
          return;
        this._fontVariant = value;
        this.update();
      }
      /**
       * The font weight.
       * @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
       */
      get fontWeight() {
        return this._fontWeight;
      }
      set fontWeight(value) {
        if (this._fontWeight === value)
          return;
        this._fontWeight = value;
        this.update();
      }
      /** The space between lines. */
      get leading() {
        return this._leading;
      }
      set leading(value) {
        if (this._leading === value)
          return;
        this._leading = value;
        this.update();
      }
      /** The amount of spacing between letters, default is 0. */
      get letterSpacing() {
        return this._letterSpacing;
      }
      set letterSpacing(value) {
        if (this._letterSpacing === value)
          return;
        this._letterSpacing = value;
        this.update();
      }
      /** The line height, a number that represents the vertical space that a letter uses. */
      get lineHeight() {
        return this._lineHeight;
      }
      set lineHeight(value) {
        if (this._lineHeight === value)
          return;
        this._lineHeight = value;
        this.update();
      }
      /**
       * Occasionally some fonts are cropped. Adding some padding will prevent this from happening
       * by adding padding to all sides of the text.
       * > [!NOTE] This will NOT affect the positioning or bounds of the text.
       */
      get padding() {
        return this._padding;
      }
      set padding(value) {
        if (this._padding === value)
          return;
        this._padding = value;
        this.update();
      }
      /**
       * An optional filter or array of filters to apply to the text, allowing for advanced visual effects.
       * These filters will be applied to the text as it is created, resulting in faster rendering for static text
       * compared to applying the filter directly to the text object (which would be applied at run time).
       * @default null
       */
      get filters() {
        return this._filters;
      }
      set filters(value) {
        if (this._filters === value)
          return;
        this._filters = Object.freeze(value);
        this.update();
      }
      /**
       * Trim transparent borders from the text texture.
       * > [!IMPORTANT] PERFORMANCE WARNING:
       * > This is a costly operation as it requires scanning pixel alpha values.
       * > Avoid using `trim: true` for dynamic text, as it could significantly impact performance.
       */
      get trim() {
        return this._trim;
      }
      set trim(value) {
        if (this._trim === value)
          return;
        this._trim = value;
        this.update();
      }
      /**
       * The baseline of the text that is rendered.
       * @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
       */
      get textBaseline() {
        return this._textBaseline;
      }
      set textBaseline(value) {
        if (this._textBaseline === value)
          return;
        this._textBaseline = value;
        this.update();
      }
      /**
       * How newlines and spaces should be handled.
       * Default is 'pre' (preserve, preserve).
       *
       *  value       | New lines     |   Spaces
       *  ---         | ---           |   ---
       * 'normal'     | Collapse      |   Collapse
       * 'pre'        | Preserve      |   Preserve
       * 'pre-line'   | Preserve      |   Collapse
       * @type {'normal'|'pre'|'pre-line'}
       */
      get whiteSpace() {
        return this._whiteSpace;
      }
      set whiteSpace(value) {
        if (this._whiteSpace === value)
          return;
        this._whiteSpace = value;
        this.update();
      }
      /** Indicates if word wrap should be used. */
      get wordWrap() {
        return this._wordWrap;
      }
      set wordWrap(value) {
        if (this._wordWrap === value)
          return;
        this._wordWrap = value;
        this.update();
      }
      /** The width at which text will wrap, it needs wordWrap to be set to true. */
      get wordWrapWidth() {
        return this._wordWrapWidth;
      }
      set wordWrapWidth(value) {
        if (this._wordWrapWidth === value)
          return;
        this._wordWrapWidth = value;
        this.update();
      }
      /**
       * The fill style that will be used to color the text.
       * This can be:
       * - A color string like 'red', '#00FF00', or 'rgba(255,0,0,0.5)'
       * - A hex number like 0xff0000 for red
       * - A FillStyle object with properties like { color: 0xff0000, alpha: 0.5 }
       * - A FillGradient for gradient fills
       * - A FillPattern for pattern/texture fills
       *
       * When using a FillGradient, vertical gradients (angle of 90 degrees) are applied per line of text,
       * while gradients at any other angle are spread across the entire text body as a whole.
       * @example
       * // Vertical gradient applied per line
       * const verticalGradient = new FillGradient(0, 0, 0, 1)
       *     .addColorStop(0, 0xff0000)
       *     .addColorStop(1, 0x0000ff);
       *
       * const text = new Text({
       *     text: 'Line 1\nLine 2',
       *     style: { fill: verticalGradient }
       * });
       *
       * To manage the gradient in a global scope, set the textureSpace property of the FillGradient to 'global'.
       * @type {string|number|FillStyle|FillGradient|FillPattern}
       */
      get fill() {
        return this._originalFill;
      }
      set fill(value) {
        if (value === this._originalFill)
          return;
        this._originalFill = value;
        if (this._isFillStyle(value)) {
          this._originalFill = this._createProxy(__spreadValues$V(__spreadValues$V({}, GraphicsContext.defaultFillStyle), value), () => {
            this._fill = toFillStyle(
              __spreadValues$V({}, this._originalFill),
              GraphicsContext.defaultFillStyle
            );
          });
        }
        this._fill = toFillStyle(
          value === 0 ? "black" : value,
          GraphicsContext.defaultFillStyle
        );
        this.update();
      }
      /** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
      get stroke() {
        return this._originalStroke;
      }
      set stroke(value) {
        if (value === this._originalStroke)
          return;
        this._originalStroke = value;
        if (this._isFillStyle(value)) {
          this._originalStroke = this._createProxy(__spreadValues$V(__spreadValues$V({}, GraphicsContext.defaultStrokeStyle), value), () => {
            this._stroke = toStrokeStyle(
              __spreadValues$V({}, this._originalStroke),
              GraphicsContext.defaultStrokeStyle
            );
          });
        }
        this._stroke = toStrokeStyle(value, GraphicsContext.defaultStrokeStyle);
        this.update();
      }
      update() {
        this._tick++;
        this.emit("update", this);
      }
      /** Resets all properties to the default values */
      reset() {
        const defaultStyle = _TextStyle.defaultTextStyle;
        for (const key in defaultStyle) {
          this[key] = defaultStyle[key];
        }
      }
      /**
       * Returns a unique key for this instance.
       * This key is used for caching.
       * @returns {string} Unique key for the instance
       */
      get styleKey() {
        return `${this.uid}-${this._tick}`;
      }
      /**
       * Creates a new TextStyle object with the same values as this one.
       * @returns New cloned TextStyle object
       */
      clone() {
        return new _TextStyle({
          align: this.align,
          breakWords: this.breakWords,
          dropShadow: this._dropShadow ? __spreadValues$V({}, this._dropShadow) : null,
          fill: this._fill,
          fontFamily: this.fontFamily,
          fontSize: this.fontSize,
          fontStyle: this.fontStyle,
          fontVariant: this.fontVariant,
          fontWeight: this.fontWeight,
          leading: this.leading,
          letterSpacing: this.letterSpacing,
          lineHeight: this.lineHeight,
          padding: this.padding,
          stroke: this._stroke,
          textBaseline: this.textBaseline,
          whiteSpace: this.whiteSpace,
          wordWrap: this.wordWrap,
          wordWrapWidth: this.wordWrapWidth,
          filters: this._filters ? [...this._filters] : void 0
        });
      }
      /**
       * Returns the final padding for the text style, taking into account any filters applied.
       * Used internally for correct measurements
       * @internal
       * @returns {number} The final padding for the text style.
       */
      _getFinalPadding() {
        let filterPadding = 0;
        if (this._filters) {
          for (let i = 0; i < this._filters.length; i++) {
            filterPadding += this._filters[i].padding;
          }
        }
        return Math.max(this._padding, filterPadding);
      }
      /**
       * Destroys this text style.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * // Destroy the text style and its textures
       * textStyle.destroy({ texture: true, textureSource: true });
       * textStyle.destroy(true);
       */
      destroy(options = false) {
        var _a, _b, _c, _d;
        this.removeAllListeners();
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          if ((_a = this._fill) == null ? void 0 : _a.texture) {
            this._fill.texture.destroy(destroyTextureSource);
          }
          if ((_b = this._originalFill) == null ? void 0 : _b.texture) {
            this._originalFill.texture.destroy(destroyTextureSource);
          }
          if ((_c = this._stroke) == null ? void 0 : _c.texture) {
            this._stroke.texture.destroy(destroyTextureSource);
          }
          if ((_d = this._originalStroke) == null ? void 0 : _d.texture) {
            this._originalStroke.texture.destroy(destroyTextureSource);
          }
        }
        this._fill = null;
        this._stroke = null;
        this.dropShadow = null;
        this._originalStroke = null;
        this._originalFill = null;
      }
      _createProxy(value, cb) {
        return new Proxy(value, {
          set: (target, property, newValue) => {
            if (target[property] === newValue)
              return true;
            target[property] = newValue;
            cb == null ? void 0 : cb(property, newValue);
            this.update();
            return true;
          }
        });
      }
      _isFillStyle(value) {
        return (value != null ? value : null) !== null && !(Color.isColorLike(value) || value instanceof FillGradient || value instanceof FillPattern);
      }
    };
    /**
     * Default drop shadow settings used when enabling drop shadows on text.
     * These values are used as the base configuration when drop shadows are enabled without specific settings.
     * @example
     * ```ts
     * // Customize default settings globally
     * TextStyle.defaultDropShadow.alpha = 0.5;    // 50% opacity for all shadows
     * TextStyle.defaultDropShadow.blur = 2;       // 2px blur for all shadows
     * TextStyle.defaultDropShadow.color = 'blue'; // Blue shadows by default
     * ```
     */
    _TextStyle.defaultDropShadow = {
      alpha: 1,
      angle: Math.PI / 6,
      blur: 0,
      color: "black",
      distance: 5
    };
    /**
     * Default text style settings used when creating new text objects.
     * These values serve as the base configuration and can be customized globally.
     * @example
     * ```ts
     * // Customize default text style globally
     * TextStyle.defaultTextStyle.fontSize = 16;
     * TextStyle.defaultTextStyle.fill = 0x333333;
     * TextStyle.defaultTextStyle.fontFamily = ['Arial', 'Helvetica', 'sans-serif'];
     * ```
     */
    _TextStyle.defaultTextStyle = {
      align: "left",
      breakWords: false,
      dropShadow: null,
      fill: "black",
      fontFamily: "Arial",
      fontSize: 26,
      fontStyle: "normal",
      fontVariant: "normal",
      fontWeight: "normal",
      leading: 0,
      letterSpacing: 0,
      lineHeight: 0,
      padding: 0,
      stroke: null,
      textBaseline: "alphabetic",
      trim: false,
      whiteSpace: "pre",
      wordWrap: false,
      wordWrapWidth: 100
    };
    let TextStyle = _TextStyle;
    function convertV7Tov8Style(style) {
      var _a, _b, _c, _d, _e;
      const oldStyle = style;
      if (typeof oldStyle.dropShadow === "boolean" && oldStyle.dropShadow) {
        const defaults = TextStyle.defaultDropShadow;
        style.dropShadow = {
          alpha: (_a = oldStyle.dropShadowAlpha) != null ? _a : defaults.alpha,
          angle: (_b = oldStyle.dropShadowAngle) != null ? _b : defaults.angle,
          blur: (_c = oldStyle.dropShadowBlur) != null ? _c : defaults.blur,
          color: (_d = oldStyle.dropShadowColor) != null ? _d : defaults.color,
          distance: (_e = oldStyle.dropShadowDistance) != null ? _e : defaults.distance
        };
      }
      if (oldStyle.strokeThickness !== void 0) {
        deprecation(v8_0_0, "strokeThickness is now a part of stroke");
        const color = oldStyle.stroke;
        let obj = {};
        if (Color.isColorLike(color)) {
          obj.color = color;
        } else if (color instanceof FillGradient || color instanceof FillPattern) {
          obj.fill = color;
        } else if (Object.hasOwnProperty.call(color, "color") || Object.hasOwnProperty.call(color, "fill")) {
          obj = color;
        } else {
          throw new Error("Invalid stroke value.");
        }
        style.stroke = __spreadProps$o(__spreadValues$V({}, obj), {
          width: oldStyle.strokeThickness
        });
      }
      if (Array.isArray(oldStyle.fillGradientStops)) {
        deprecation(v8_0_0, "gradient fill is now a fill pattern: `new FillGradient(...)`");
        if (!Array.isArray(oldStyle.fill) || oldStyle.fill.length === 0) {
          throw new Error("Invalid fill value. Expected an array of colors for gradient fill.");
        }
        if (oldStyle.fill.length !== oldStyle.fillGradientStops.length) {
          warn("The number of fill colors must match the number of fill gradient stops.");
        }
        const gradientFill = new FillGradient({
          start: { x: 0, y: 0 },
          end: { x: 0, y: 1 },
          textureSpace: "local"
        });
        const fillGradientStops = oldStyle.fillGradientStops.slice();
        const fills = oldStyle.fill.map((color) => Color.shared.setValue(color).toNumber());
        fillGradientStops.forEach((stop, index) => {
          gradientFill.addColorStop(stop, fills[index]);
        });
        style.fill = {
          fill: gradientFill
        };
      }
    }

    "use strict";
    const tempBounds$3 = new Bounds();
    function getPo2TextureFromSource(image, width, height, resolution) {
      const bounds = tempBounds$3;
      bounds.minX = 0;
      bounds.minY = 0;
      bounds.maxX = image.width / resolution | 0;
      bounds.maxY = image.height / resolution | 0;
      const texture = TexturePool.getOptimalTexture(
        bounds.width,
        bounds.height,
        resolution,
        false
      );
      texture.source.uploadMethodId = "image";
      texture.source.resource = image;
      texture.source.alphaMode = "premultiply-alpha-on-upload";
      texture.frame.width = width / resolution;
      texture.frame.height = height / resolution;
      texture.source.emit("update", texture.source);
      texture.updateUvs();
      return texture;
    }

    "use strict";
    class CanvasPoolClass {
      constructor(canvasOptions) {
        this._canvasPool = /* @__PURE__ */ Object.create(null);
        this.canvasOptions = canvasOptions || {};
        this.enableFullScreen = false;
      }
      /**
       * Creates texture with params that were specified in pool constructor.
       * @param pixelWidth - Width of texture in pixels.
       * @param pixelHeight - Height of texture in pixels.
       */
      _createCanvasAndContext(pixelWidth, pixelHeight) {
        const canvas = DOMAdapter.get().createCanvas();
        canvas.width = pixelWidth;
        canvas.height = pixelHeight;
        const context = canvas.getContext("2d");
        return { canvas, context };
      }
      /**
       * Gets a Power-of-Two render texture or fullScreen texture
       * @param minWidth - The minimum width of the render texture.
       * @param minHeight - The minimum height of the render texture.
       * @param resolution - The resolution of the render texture.
       * @returns The new render texture.
       */
      getOptimalCanvasAndContext(minWidth, minHeight, resolution = 1) {
        minWidth = Math.ceil(minWidth * resolution - 1e-6);
        minHeight = Math.ceil(minHeight * resolution - 1e-6);
        minWidth = nextPow2(minWidth);
        minHeight = nextPow2(minHeight);
        const key = (minWidth << 17) + (minHeight << 1);
        if (!this._canvasPool[key]) {
          this._canvasPool[key] = [];
        }
        let canvasAndContext = this._canvasPool[key].pop();
        if (!canvasAndContext) {
          canvasAndContext = this._createCanvasAndContext(minWidth, minHeight);
        }
        return canvasAndContext;
      }
      /**
       * Place a render texture back into the pool.
       * @param canvasAndContext
       */
      returnCanvasAndContext(canvasAndContext) {
        const canvas = canvasAndContext.canvas;
        const { width, height } = canvas;
        const key = (width << 17) + (height << 1);
        canvasAndContext.context.resetTransform();
        canvasAndContext.context.clearRect(0, 0, width, height);
        this._canvasPool[key].push(canvasAndContext);
      }
      clear() {
        this._canvasPool = {};
      }
    }
    const CanvasPool = new CanvasPoolClass();
    GlobalResourceRegistry.register(CanvasPool);

    "use strict";
    let _internalCanvas = null;
    let _internalContext = null;
    function ensureInternalCanvas(width, height) {
      if (!_internalCanvas) {
        _internalCanvas = DOMAdapter.get().createCanvas(256, 128);
        _internalContext = _internalCanvas.getContext("2d", { willReadFrequently: true });
        _internalContext.globalCompositeOperation = "copy";
        _internalContext.globalAlpha = 1;
      }
      if (_internalCanvas.width < width || _internalCanvas.height < height) {
        _internalCanvas.width = nextPow2(width);
        _internalCanvas.height = nextPow2(height);
      }
    }
    function checkRow(data, width, y) {
      for (let x = 0, index = 4 * y * width; x < width; ++x, index += 4) {
        if (data[index + 3] !== 0)
          return false;
      }
      return true;
    }
    function checkColumn(data, width, x, top, bottom) {
      const stride = 4 * width;
      for (let y = top, index = top * stride + 4 * x; y <= bottom; ++y, index += stride) {
        if (data[index + 3] !== 0)
          return false;
      }
      return true;
    }
    function getCanvasBoundingBox(...args) {
      var _a, _b, _c;
      let options = args[0];
      if (!options.canvas) {
        options = { canvas: args[0], resolution: args[1] };
      }
      const { canvas } = options;
      const resolution = Math.min((_a = options.resolution) != null ? _a : 1, 1);
      const width = (_b = options.width) != null ? _b : canvas.width;
      const height = (_c = options.height) != null ? _c : canvas.height;
      let output = options.output;
      ensureInternalCanvas(width, height);
      if (!_internalContext) {
        throw new TypeError("Failed to get canvas 2D context");
      }
      _internalContext.drawImage(
        canvas,
        0,
        0,
        width,
        height,
        0,
        0,
        width * resolution,
        height * resolution
      );
      const imageData = _internalContext.getImageData(0, 0, width, height);
      const data = imageData.data;
      let left = 0;
      let top = 0;
      let right = width - 1;
      let bottom = height - 1;
      while (top < height && checkRow(data, width, top))
        ++top;
      if (top === height)
        return Rectangle.EMPTY;
      while (checkRow(data, width, bottom))
        --bottom;
      while (checkColumn(data, width, left, top, bottom))
        ++left;
      while (checkColumn(data, width, right, top, bottom))
        --right;
      ++right;
      ++bottom;
      _internalContext.globalCompositeOperation = "source-over";
      _internalContext.strokeRect(left, top, right - left, bottom - top);
      _internalContext.globalCompositeOperation = "copy";
      output != null ? output : output = new Rectangle();
      output.set(left / resolution, top / resolution, (right - left) / resolution, (bottom - top) / resolution);
      return output;
    }

    /**
     * tiny-lru
     *
     * @copyright 2025 Jason Mulligan <jason.mulligan@avoidwork.com>
     * @license BSD-3-Clause
     * @version 11.4.5
     */
    /**
     * A high-performance Least Recently Used (LRU) cache implementation with optional TTL support.
     * Items are automatically evicted when the cache reaches its maximum size,
     * removing the least recently used items first. All core operations (get, set, delete) are O(1).
     *
     * @class LRU
     * @example
     * // Create a cache with max 100 items
     * const cache = new LRU(100);
     * cache.set('key1', 'value1');
     * console.log(cache.get('key1')); // 'value1'
     *
     * @example
     * // Create a cache with TTL
     * const cache = new LRU(100, 5000); // 5 second TTL
     * cache.set('key1', 'value1');
     * // After 5 seconds, key1 will be expired
     */
    class LRU {
    	/**
    	 * Creates a new LRU cache instance.
    	 * Note: Constructor does not validate parameters. Use lru() factory function for parameter validation.
    	 *
    	 * @constructor
    	 * @param {number} [max=0] - Maximum number of items to store. 0 means unlimited.
    	 * @param {number} [ttl=0] - Time to live in milliseconds. 0 means no expiration.
    	 * @param {boolean} [resetTtl=false] - Whether to reset TTL when accessing existing items via get().
    	 * @example
    	 * const cache = new LRU(1000, 60000, true); // 1000 items, 1 minute TTL, reset on access
    	 * @see {@link lru} For parameter validation
    	 * @since 1.0.0
    	 */
    	constructor (max = 0, ttl = 0, resetTtl = false) {
    		this.first = null;
    		this.items = Object.create(null);
    		this.last = null;
    		this.max = max;
    		this.resetTtl = resetTtl;
    		this.size = 0;
    		this.ttl = ttl;
    	}

    	/**
    	 * Removes all items from the cache.
    	 *
    	 * @method clear
    	 * @memberof LRU
    	 * @returns {LRU} The LRU instance for method chaining.
    	 * @example
    	 * cache.clear();
    	 * console.log(cache.size); // 0
    	 * @since 1.0.0
    	 */
    	clear () {
    		this.first = null;
    		this.items = Object.create(null);
    		this.last = null;
    		this.size = 0;

    		return this;
    	}

    	/**
    	 * Removes an item from the cache by key.
    	 *
    	 * @method delete
    	 * @memberof LRU
    	 * @param {string} key - The key of the item to delete.
    	 * @returns {LRU} The LRU instance for method chaining.
    	 * @example
    	 * cache.set('key1', 'value1');
    	 * cache.delete('key1');
    	 * console.log(cache.has('key1')); // false
    	 * @see {@link LRU#has}
    	 * @see {@link LRU#clear}
    	 * @since 1.0.0
    	 */
    	delete (key) {
    		if (this.has(key)) {
    			const item = this.items[key];

    			delete this.items[key];
    			this.size--;

    			if (item.prev !== null) {
    				item.prev.next = item.next;
    			}

    			if (item.next !== null) {
    				item.next.prev = item.prev;
    			}

    			if (this.first === item) {
    				this.first = item.next;
    			}

    			if (this.last === item) {
    				this.last = item.prev;
    			}
    		}

    		return this;
    	}

    	/**
    	 * Returns an array of [key, value] pairs for the specified keys.
    	 * Order follows LRU order (least to most recently used).
    	 *
    	 * @method entries
    	 * @memberof LRU
    	 * @param {string[]} [keys=this.keys()] - Array of keys to get entries for. Defaults to all keys.
    	 * @returns {Array<Array<*>>} Array of [key, value] pairs in LRU order.
    	 * @example
    	 * cache.set('a', 1).set('b', 2);
    	 * console.log(cache.entries()); // [['a', 1], ['b', 2]]
    	 * console.log(cache.entries(['a'])); // [['a', 1]]
    	 * @see {@link LRU#keys}
    	 * @see {@link LRU#values}
    	 * @since 11.1.0
    	 */
    	entries (keys = this.keys()) {
    		return keys.map(key => [key, this.get(key)]);
    	}

    	/**
    	 * Removes the least recently used item from the cache.
    	 *
    	 * @method evict
    	 * @memberof LRU
    	 * @param {boolean} [bypass=false] - Whether to force eviction even when cache is empty.
    	 * @returns {LRU} The LRU instance for method chaining.
    	 * @example
    	 * cache.set('old', 'value').set('new', 'value');
    	 * cache.evict(); // Removes 'old' item
    	 * @see {@link LRU#setWithEvicted}
    	 * @since 1.0.0
    	 */
    	evict (bypass = false) {
    		if (bypass || this.size > 0) {
    			const item = this.first;

    			delete this.items[item.key];

    			if (--this.size === 0) {
    				this.first = null;
    				this.last = null;
    			} else {
    				this.first = item.next;
    				this.first.prev = null;
    			}
    		}

    		return this;
    	}

    	/**
    	 * Returns the expiration timestamp for a given key.
    	 *
    	 * @method expiresAt
    	 * @memberof LRU
    	 * @param {string} key - The key to check expiration for.
    	 * @returns {number|undefined} The expiration timestamp in milliseconds, or undefined if key doesn't exist.
    	 * @example
    	 * const cache = new LRU(100, 5000); // 5 second TTL
    	 * cache.set('key1', 'value1');
    	 * console.log(cache.expiresAt('key1')); // timestamp 5 seconds from now
    	 * @see {@link LRU#get}
    	 * @see {@link LRU#has}
    	 * @since 1.0.0
    	 */
    	expiresAt (key) {
    		let result;

    		if (this.has(key)) {
    			result = this.items[key].expiry;
    		}

    		return result;
    	}

    	/**
    	 * Retrieves a value from the cache by key. Updates the item's position to most recently used.
    	 *
    	 * @method get
    	 * @memberof LRU
    	 * @param {string} key - The key to retrieve.
    	 * @returns {*} The value associated with the key, or undefined if not found or expired.
    	 * @example
    	 * cache.set('key1', 'value1');
    	 * console.log(cache.get('key1')); // 'value1'
    	 * console.log(cache.get('nonexistent')); // undefined
    	 * @see {@link LRU#set}
    	 * @see {@link LRU#has}
    	 * @since 1.0.0
    	 */
    	get (key) {
    		const item = this.items[key];

    		if (item !== undefined) {
    			// Check TTL only if enabled to avoid unnecessary Date.now() calls
    			if (this.ttl > 0) {
    				if (item.expiry <= Date.now()) {
    					this.delete(key);

    					return undefined;
    				}
    			}

    			// Fast LRU update without full set() overhead
    			this.moveToEnd(item);

    			return item.value;
    		}

    		return undefined;
    	}

    	/**
    	 * Checks if a key exists in the cache.
    	 *
    	 * @method has
    	 * @memberof LRU
    	 * @param {string} key - The key to check for.
    	 * @returns {boolean} True if the key exists, false otherwise.
    	 * @example
    	 * cache.set('key1', 'value1');
    	 * console.log(cache.has('key1')); // true
    	 * console.log(cache.has('nonexistent')); // false
    	 * @see {@link LRU#get}
    	 * @see {@link LRU#delete}
    	 * @since 9.0.0
    	 */
    	has (key) {
    		return key in this.items;
    	}

    	/**
    	 * Efficiently moves an item to the end of the LRU list (most recently used position).
    	 * This is an internal optimization method that avoids the overhead of the full set() operation
    	 * when only LRU position needs to be updated.
    	 *
    	 * @method moveToEnd
    	 * @memberof LRU
    	 * @param {Object} item - The cache item with prev/next pointers to reposition.
    	 * @private
    	 * @since 11.3.5
    	 */
    	moveToEnd (item) {
    		// If already at the end, nothing to do
    		if (this.last === item) {
    			return;
    		}

    		// Remove item from current position in the list
    		if (item.prev !== null) {
    			item.prev.next = item.next;
    		}

    		if (item.next !== null) {
    			item.next.prev = item.prev;
    		}

    		// Update first pointer if this was the first item
    		if (this.first === item) {
    			this.first = item.next;
    		}

    		// Add item to the end
    		item.prev = this.last;
    		item.next = null;

    		if (this.last !== null) {
    			this.last.next = item;
    		}

    		this.last = item;

    		// Handle edge case: if this was the only item, it's also first
    		if (this.first === null) {
    			this.first = item;
    		}
    	}

    	/**
    	 * Returns an array of all keys in the cache, ordered from least to most recently used.
    	 *
    	 * @method keys
    	 * @memberof LRU
    	 * @returns {string[]} Array of keys in LRU order.
    	 * @example
    	 * cache.set('a', 1).set('b', 2);
    	 * cache.get('a'); // Move 'a' to most recent
    	 * console.log(cache.keys()); // ['b', 'a']
    	 * @see {@link LRU#values}
    	 * @see {@link LRU#entries}
    	 * @since 9.0.0
    	 */
    	keys () {
    		const result = [];
    		let x = this.first;

    		while (x !== null) {
    			result.push(x.key);
    			x = x.next;
    		}

    		return result;
    	}

    	/**
    	 * Sets a value in the cache and returns any evicted item.
    	 *
    	 * @method setWithEvicted
    	 * @memberof LRU
    	 * @param {string} key - The key to set.
    	 * @param {*} value - The value to store.
    	 * @param {boolean} [resetTtl=this.resetTtl] - Whether to reset the TTL for this operation.
    	 * @returns {Object|null} The evicted item (if any) with shape {key, value, expiry, prev, next}, or null.
    	 * @example
    	 * const cache = new LRU(2);
    	 * cache.set('a', 1).set('b', 2);
    	 * const evicted = cache.setWithEvicted('c', 3); // evicted = {key: 'a', value: 1, ...}
    	 * @see {@link LRU#set}
    	 * @see {@link LRU#evict}
    	 * @since 11.3.0
    	 */
    	setWithEvicted (key, value, resetTtl = this.resetTtl) {
    		let evicted = null;

    		if (this.has(key)) {
    			this.set(key, value, true, resetTtl);
    		} else {
    			if (this.max > 0 && this.size === this.max) {
    				evicted = {...this.first};
    				this.evict(true);
    			}

    			let item = this.items[key] = {
    				expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
    				key: key,
    				prev: this.last,
    				next: null,
    				value
    			};

    			if (++this.size === 1) {
    				this.first = item;
    			} else {
    				this.last.next = item;
    			}

    			this.last = item;
    		}

    		return evicted;
    	}

    	/**
    	 * Sets a value in the cache. Updates the item's position to most recently used.
    	 *
    	 * @method set
    	 * @memberof LRU
    	 * @param {string} key - The key to set.
    	 * @param {*} value - The value to store.
    	 * @param {boolean} [bypass=false] - Internal parameter for setWithEvicted method.
    	 * @param {boolean} [resetTtl=this.resetTtl] - Whether to reset the TTL for this operation.
    	 * @returns {LRU} The LRU instance for method chaining.
    	 * @example
    	 * cache.set('key1', 'value1')
    	 *      .set('key2', 'value2')
    	 *      .set('key3', 'value3');
    	 * @see {@link LRU#get}
    	 * @see {@link LRU#setWithEvicted}
    	 * @since 1.0.0
    	 */
    	set (key, value, bypass = false, resetTtl = this.resetTtl) {
    		let item = this.items[key];

    		if (bypass || item !== undefined) {
    			// Existing item: update value and position
    			item.value = value;

    			if (bypass === false && resetTtl) {
    				item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
    			}

    			// Always move to end, but the bypass parameter affects TTL reset behavior
    			this.moveToEnd(item);
    		} else {
    			// New item: check for eviction and create
    			if (this.max > 0 && this.size === this.max) {
    				this.evict(true);
    			}

    			item = this.items[key] = {
    				expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
    				key: key,
    				prev: this.last,
    				next: null,
    				value
    			};

    			if (++this.size === 1) {
    				this.first = item;
    			} else {
    				this.last.next = item;
    			}

    			this.last = item;
    		}

    		return this;
    	}

    	/**
    	 * Returns an array of all values in the cache for the specified keys.
    	 * Order follows LRU order (least to most recently used).
    	 *
    	 * @method values
    	 * @memberof LRU
    	 * @param {string[]} [keys=this.keys()] - Array of keys to get values for. Defaults to all keys.
    	 * @returns {Array<*>} Array of values corresponding to the keys in LRU order.
    	 * @example
    	 * cache.set('a', 1).set('b', 2);
    	 * console.log(cache.values()); // [1, 2]
    	 * console.log(cache.values(['a'])); // [1]
    	 * @see {@link LRU#keys}
    	 * @see {@link LRU#entries}
    	 * @since 11.1.0
    	 */
    	values (keys = this.keys()) {
    		return keys.map(key => this.get(key));
    	}
    }

    /**
     * Factory function to create a new LRU cache instance with parameter validation.
     *
     * @function lru
     * @param {number} [max=1000] - Maximum number of items to store. Must be >= 0. Use 0 for unlimited size.
     * @param {number} [ttl=0] - Time to live in milliseconds. Must be >= 0. Use 0 for no expiration.
     * @param {boolean} [resetTtl=false] - Whether to reset TTL when accessing existing items via get().
     * @returns {LRU} A new LRU cache instance.
     * @throws {TypeError} When parameters are invalid (negative numbers or wrong types).
     * @example
     * // Create cache with factory function
     * const cache = lru(100, 5000, true);
     * cache.set('key', 'value');
     *
     * @example
     * // Error handling
     * try {
     *   const cache = lru(-1); // Invalid max
     * } catch (error) {
     *   console.error(error.message); // "Invalid max value"
     * }
     * @see {@link LRU}
     * @since 1.0.0
     */
    function lru (max = 1000, ttl = 0, resetTtl = false) {
    	if (isNaN(max) || max < 0) {
    		throw new TypeError("Invalid max value");
    	}

    	if (isNaN(ttl) || ttl < 0) {
    		throw new TypeError("Invalid ttl value");
    	}

    	if (typeof resetTtl !== "boolean") {
    		throw new TypeError("Invalid resetTtl value");
    	}

    	return new LRU(max, ttl, resetTtl);
    }

    "use strict";
    const genericFontFamilies = [
      "serif",
      "sans-serif",
      "monospace",
      "cursive",
      "fantasy",
      "system-ui"
    ];
    function fontStringFromTextStyle(style) {
      const fontSizeString = typeof style.fontSize === "number" ? `${style.fontSize}px` : style.fontSize;
      let fontFamilies = style.fontFamily;
      if (!Array.isArray(style.fontFamily)) {
        fontFamilies = style.fontFamily.split(",");
      }
      for (let i = fontFamilies.length - 1; i >= 0; i--) {
        let fontFamily = fontFamilies[i].trim();
        if (!/([\"\'])[^\'\"]+\1/.test(fontFamily) && !genericFontFamilies.includes(fontFamily)) {
          fontFamily = `"${fontFamily}"`;
        }
        fontFamilies[i] = fontFamily;
      }
      return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(",")}`;
    }

    "use strict";
    const contextSettings = {
      // TextMetrics requires getImageData readback for measuring fonts.
      willReadFrequently: true
    };
    const _CanvasTextMetrics = class _CanvasTextMetrics {
      /**
       * Checking that we can use modern canvas 2D API.
       *
       * Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
       * @see TextMetrics.experimentalLetterSpacing
       * @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
       * @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
       */
      static get experimentalLetterSpacingSupported() {
        let result = _CanvasTextMetrics._experimentalLetterSpacingSupported;
        if (result === void 0) {
          const proto = DOMAdapter.get().getCanvasRenderingContext2D().prototype;
          result = _CanvasTextMetrics._experimentalLetterSpacingSupported = "letterSpacing" in proto || "textLetterSpacing" in proto;
        }
        return result;
      }
      /**
       * @param text - the text that was measured
       * @param style - the style that was measured
       * @param width - the measured width of the text
       * @param height - the measured height of the text
       * @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
       * @param lineWidths - an array of the line widths for each line matched to `lines`
       * @param lineHeight - the measured line height for this style
       * @param maxLineWidth - the maximum line width for all measured lines
       * @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
       */
      constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
        this.text = text;
        this.style = style;
        this.width = width;
        this.height = height;
        this.lines = lines;
        this.lineWidths = lineWidths;
        this.lineHeight = lineHeight;
        this.maxLineWidth = maxLineWidth;
        this.fontProperties = fontProperties;
      }
      /**
       * Measures the supplied string of text and returns a Rectangle.
       * @param text - The text to measure.
       * @param style - The text style to use for measuring
       * @param canvas - optional specification of the canvas to use for measuring.
       * @param wordWrap
       * @returns Measured width and height of the text.
       */
      static measureText(text = " ", style, canvas = _CanvasTextMetrics._canvas, wordWrap = style.wordWrap) {
        var _a;
        const textKey = `${text}-${style.styleKey}-wordWrap-${wordWrap}`;
        if (_CanvasTextMetrics._measurementCache.has(textKey)) {
          return _CanvasTextMetrics._measurementCache.get(textKey);
        }
        const font = fontStringFromTextStyle(style);
        const fontProperties = _CanvasTextMetrics.measureFont(font);
        if (fontProperties.fontSize === 0) {
          fontProperties.fontSize = style.fontSize;
          fontProperties.ascent = style.fontSize;
        }
        const context = _CanvasTextMetrics.__context;
        context.font = font;
        const outputText = wordWrap ? _CanvasTextMetrics._wordWrap(text, style, canvas) : text;
        const lines = outputText.split(/(?:\r\n|\r|\n)/);
        const lineWidths = new Array(lines.length);
        let maxLineWidth = 0;
        for (let i = 0; i < lines.length; i++) {
          const lineWidth = _CanvasTextMetrics._measureText(lines[i], style.letterSpacing, context);
          lineWidths[i] = lineWidth;
          maxLineWidth = Math.max(maxLineWidth, lineWidth);
        }
        const strokeWidth = ((_a = style._stroke) == null ? void 0 : _a.width) || 0;
        let width = maxLineWidth + strokeWidth;
        if (style.dropShadow) {
          width += style.dropShadow.distance;
        }
        const lineHeight = style.lineHeight || fontProperties.fontSize;
        let height = Math.max(lineHeight, fontProperties.fontSize + strokeWidth) + (lines.length - 1) * (lineHeight + style.leading);
        if (style.dropShadow) {
          height += style.dropShadow.distance;
        }
        const measurements = new _CanvasTextMetrics(
          text,
          style,
          width,
          height,
          lines,
          lineWidths,
          lineHeight + style.leading,
          maxLineWidth,
          fontProperties
        );
        _CanvasTextMetrics._measurementCache.set(textKey, measurements);
        return measurements;
      }
      static _measureText(text, letterSpacing, context) {
        let useExperimentalLetterSpacing = false;
        if (_CanvasTextMetrics.experimentalLetterSpacingSupported) {
          if (_CanvasTextMetrics.experimentalLetterSpacing) {
            context.letterSpacing = `${letterSpacing}px`;
            context.textLetterSpacing = `${letterSpacing}px`;
            useExperimentalLetterSpacing = true;
          } else {
            context.letterSpacing = "0px";
            context.textLetterSpacing = "0px";
          }
        }
        const metrics = context.measureText(text);
        let metricWidth = metrics.width;
        const actualBoundingBoxLeft = -metrics.actualBoundingBoxLeft;
        const actualBoundingBoxRight = metrics.actualBoundingBoxRight;
        let boundsWidth = actualBoundingBoxRight - actualBoundingBoxLeft;
        if (metricWidth > 0) {
          if (useExperimentalLetterSpacing) {
            metricWidth -= letterSpacing;
            boundsWidth -= letterSpacing;
          } else {
            const val = (_CanvasTextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing;
            metricWidth += val;
            boundsWidth += val;
          }
        }
        return Math.max(metricWidth, boundsWidth);
      }
      /**
       * Applies newlines to a string to have it optimally fit into the horizontal
       * bounds set by the Text object's wordWrapWidth property.
       * @param text - String to apply word wrapping to
       * @param style - the style to use when wrapping
       * @param canvas - optional specification of the canvas to use for measuring.
       * @returns New string with new lines applied where required
       */
      static _wordWrap(text, style, canvas = _CanvasTextMetrics._canvas) {
        const context = canvas.getContext("2d", contextSettings);
        let width = 0;
        let line = "";
        let lines = "";
        const cache = /* @__PURE__ */ Object.create(null);
        const { letterSpacing, whiteSpace } = style;
        const collapseSpaces = _CanvasTextMetrics._collapseSpaces(whiteSpace);
        const collapseNewlines = _CanvasTextMetrics._collapseNewlines(whiteSpace);
        let canPrependSpaces = !collapseSpaces;
        const wordWrapWidth = style.wordWrapWidth + letterSpacing;
        const tokens = _CanvasTextMetrics._tokenize(text);
        for (let i = 0; i < tokens.length; i++) {
          let token = tokens[i];
          if (_CanvasTextMetrics._isNewline(token)) {
            if (!collapseNewlines) {
              lines += _CanvasTextMetrics._addLine(line);
              canPrependSpaces = !collapseSpaces;
              line = "";
              width = 0;
              continue;
            }
            token = " ";
          }
          if (collapseSpaces) {
            const currIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(token);
            const lastIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(line[line.length - 1]);
            if (currIsBreakingSpace && lastIsBreakingSpace) {
              continue;
            }
          }
          const tokenWidth = _CanvasTextMetrics._getFromCache(token, letterSpacing, cache, context);
          if (tokenWidth > wordWrapWidth) {
            if (line !== "") {
              lines += _CanvasTextMetrics._addLine(line);
              line = "";
              width = 0;
            }
            if (_CanvasTextMetrics.canBreakWords(token, style.breakWords)) {
              const characters = _CanvasTextMetrics.wordWrapSplit(token);
              for (let j = 0; j < characters.length; j++) {
                let char = characters[j];
                let lastChar = char;
                let k = 1;
                while (characters[j + k]) {
                  const nextChar = characters[j + k];
                  if (!_CanvasTextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
                    char += nextChar;
                  } else {
                    break;
                  }
                  lastChar = nextChar;
                  k++;
                }
                j += k - 1;
                const characterWidth = _CanvasTextMetrics._getFromCache(char, letterSpacing, cache, context);
                if (characterWidth + width > wordWrapWidth) {
                  lines += _CanvasTextMetrics._addLine(line);
                  canPrependSpaces = false;
                  line = "";
                  width = 0;
                }
                line += char;
                width += characterWidth;
              }
            } else {
              if (line.length > 0) {
                lines += _CanvasTextMetrics._addLine(line);
                line = "";
                width = 0;
              }
              const isLastToken = i === tokens.length - 1;
              lines += _CanvasTextMetrics._addLine(token, !isLastToken);
              canPrependSpaces = false;
              line = "";
              width = 0;
            }
          } else {
            if (tokenWidth + width > wordWrapWidth) {
              canPrependSpaces = false;
              lines += _CanvasTextMetrics._addLine(line);
              line = "";
              width = 0;
            }
            if (line.length > 0 || !_CanvasTextMetrics.isBreakingSpace(token) || canPrependSpaces) {
              line += token;
              width += tokenWidth;
            }
          }
        }
        lines += _CanvasTextMetrics._addLine(line, false);
        return lines;
      }
      /**
       * Convenience function for logging each line added during the wordWrap method.
       * @param line    - The line of text to add
       * @param newLine - Add new line character to end
       * @returns A formatted line
       */
      static _addLine(line, newLine = true) {
        line = _CanvasTextMetrics._trimRight(line);
        line = newLine ? `${line}
` : line;
        return line;
      }
      /**
       * Gets & sets the widths of calculated characters in a cache object
       * @param key            - The key
       * @param letterSpacing  - The letter spacing
       * @param cache          - The cache
       * @param context        - The canvas context
       * @returns The from cache.
       */
      static _getFromCache(key, letterSpacing, cache, context) {
        let width = cache[key];
        if (typeof width !== "number") {
          width = _CanvasTextMetrics._measureText(key, letterSpacing, context) + letterSpacing;
          cache[key] = width;
        }
        return width;
      }
      /**
       * Determines whether we should collapse breaking spaces.
       * @param whiteSpace - The TextStyle property whiteSpace
       * @returns Should collapse
       */
      static _collapseSpaces(whiteSpace) {
        return whiteSpace === "normal" || whiteSpace === "pre-line";
      }
      /**
       * Determines whether we should collapse newLine chars.
       * @param whiteSpace - The white space
       * @returns should collapse
       */
      static _collapseNewlines(whiteSpace) {
        return whiteSpace === "normal";
      }
      /**
       * Trims breaking whitespaces from string.
       * @param text - The text
       * @returns Trimmed string
       */
      static _trimRight(text) {
        if (typeof text !== "string") {
          return "";
        }
        for (let i = text.length - 1; i >= 0; i--) {
          const char = text[i];
          if (!_CanvasTextMetrics.isBreakingSpace(char)) {
            break;
          }
          text = text.slice(0, -1);
        }
        return text;
      }
      /**
       * Determines if char is a newline.
       * @param char - The character
       * @returns True if newline, False otherwise.
       */
      static _isNewline(char) {
        if (typeof char !== "string") {
          return false;
        }
        return _CanvasTextMetrics._newlines.includes(char.charCodeAt(0));
      }
      /**
       * Determines if char is a breaking whitespace.
       *
       * It allows one to determine whether char should be a breaking whitespace
       * For example certain characters in CJK langs or numbers.
       * It must return a boolean.
       * @param char - The character
       * @param [_nextChar] - The next character
       * @returns True if whitespace, False otherwise.
       */
      static isBreakingSpace(char, _nextChar) {
        if (typeof char !== "string") {
          return false;
        }
        return _CanvasTextMetrics._breakingSpaces.includes(char.charCodeAt(0));
      }
      /**
       * Splits a string into words, breaking-spaces and newLine characters
       * @param text - The text
       * @returns A tokenized array
       */
      static _tokenize(text) {
        const tokens = [];
        let token = "";
        if (typeof text !== "string") {
          return tokens;
        }
        for (let i = 0; i < text.length; i++) {
          const char = text[i];
          const nextChar = text[i + 1];
          if (_CanvasTextMetrics.isBreakingSpace(char, nextChar) || _CanvasTextMetrics._isNewline(char)) {
            if (token !== "") {
              tokens.push(token);
              token = "";
            }
            if (char === "\r" && nextChar === "\n") {
              tokens.push("\r\n");
              i++;
            } else {
              tokens.push(char);
            }
            continue;
          }
          token += char;
        }
        if (token !== "") {
          tokens.push(token);
        }
        return tokens;
      }
      /**
       * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
       *
       * It allows one to customise which words should break
       * Examples are if the token is CJK or numbers.
       * It must return a boolean.
       * @param _token - The token
       * @param breakWords - The style attr break words
       * @returns Whether to break word or not
       */
      static canBreakWords(_token, breakWords) {
        return breakWords;
      }
      /**
       * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
       *
       * It allows one to determine whether a pair of characters
       * should be broken by newlines
       * For example certain characters in CJK langs or numbers.
       * It must return a boolean.
       * @param _char - The character
       * @param _nextChar - The next character
       * @param _token - The token/word the characters are from
       * @param _index - The index in the token of the char
       * @param _breakWords - The style attr break words
       * @returns whether to break word or not
       */
      static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
        return true;
      }
      /**
       * Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
       *
       * It is called when a token (usually a word) has to be split into separate pieces
       * in order to determine the point to break a word.
       * It must return an array of characters.
       * @param token - The token to split
       * @returns The characters of the token
       * @see CanvasTextMetrics.graphemeSegmenter
       */
      static wordWrapSplit(token) {
        return _CanvasTextMetrics.graphemeSegmenter(token);
      }
      /**
       * Calculates the ascent, descent and fontSize of a given font-style
       * @param font - String representing the style of the font
       * @returns Font properties object
       */
      static measureFont(font) {
        if (_CanvasTextMetrics._fonts[font]) {
          return _CanvasTextMetrics._fonts[font];
        }
        const context = _CanvasTextMetrics._context;
        context.font = font;
        const metrics = context.measureText(_CanvasTextMetrics.METRICS_STRING + _CanvasTextMetrics.BASELINE_SYMBOL);
        const properties = {
          ascent: metrics.actualBoundingBoxAscent,
          descent: metrics.actualBoundingBoxDescent,
          fontSize: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
        };
        _CanvasTextMetrics._fonts[font] = properties;
        return properties;
      }
      /**
       * Clear font metrics in metrics cache.
       * @param {string} [font] - font name. If font name not set then clear cache for all fonts.
       */
      static clearMetrics(font = "") {
        if (font) {
          delete _CanvasTextMetrics._fonts[font];
        } else {
          _CanvasTextMetrics._fonts = {};
        }
      }
      /**
       * Cached canvas element for measuring text
       * TODO: this should be private, but isn't because of backward compat, will fix later.
       * @ignore
       */
      static get _canvas() {
        if (!_CanvasTextMetrics.__canvas) {
          let canvas;
          try {
            const c = new OffscreenCanvas(0, 0);
            const context = c.getContext("2d", contextSettings);
            if (context == null ? void 0 : context.measureText) {
              _CanvasTextMetrics.__canvas = c;
              return c;
            }
            canvas = DOMAdapter.get().createCanvas();
          } catch (_cx) {
            canvas = DOMAdapter.get().createCanvas();
          }
          canvas.width = canvas.height = 10;
          _CanvasTextMetrics.__canvas = canvas;
        }
        return _CanvasTextMetrics.__canvas;
      }
      /**
       * TODO: this should be private, but isn't because of backward compat, will fix later.
       * @ignore
       */
      static get _context() {
        if (!_CanvasTextMetrics.__context) {
          _CanvasTextMetrics.__context = _CanvasTextMetrics._canvas.getContext("2d", contextSettings);
        }
        return _CanvasTextMetrics.__context;
      }
    };
    /**
     * String used for calculate font metrics.
     * These characters are all tall to help calculate the height required for text.
     */
    _CanvasTextMetrics.METRICS_STRING = "|\xC9q\xC5";
    /** Baseline symbol for calculate font metrics. */
    _CanvasTextMetrics.BASELINE_SYMBOL = "M";
    /** Baseline multiplier for calculate font metrics. */
    _CanvasTextMetrics.BASELINE_MULTIPLIER = 1.4;
    /** Height multiplier for setting height of canvas to calculate font metrics. */
    _CanvasTextMetrics.HEIGHT_MULTIPLIER = 2;
    /**
     * A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
     * such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
     * or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
     * The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
     * PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
     * If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
     * you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
     * or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
     * relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
     */
    _CanvasTextMetrics.graphemeSegmenter = (() => {
      if (typeof (Intl == null ? void 0 : Intl.Segmenter) === "function") {
        const segmenter = new Intl.Segmenter();
        return (s) => {
          const segments = segmenter.segment(s);
          const result = [];
          let i = 0;
          for (const segment of segments) {
            result[i++] = segment.segment;
          }
          return result;
        };
      }
      return (s) => [...s];
    })();
    /**
     * New rendering behavior for letter-spacing which uses Chrome's new native API. This will
     * lead to more accurate letter-spacing results because it does not try to manually draw
     * each character. However, this Chrome API is experimental and may not serve all cases yet.
     * @see TextMetrics.experimentalLetterSpacingSupported
     */
    _CanvasTextMetrics.experimentalLetterSpacing = false;
    /** Cache of {@link TextMetrics.FontMetrics} objects. */
    _CanvasTextMetrics._fonts = {};
    /** Cache of new line chars. */
    _CanvasTextMetrics._newlines = [
      10,
      // line feed
      13
      // carriage return
    ];
    /** Cache of breaking spaces. */
    _CanvasTextMetrics._breakingSpaces = [
      9,
      // character tabulation
      32,
      // space
      8192,
      // en quad
      8193,
      // em quad
      8194,
      // en space
      8195,
      // em space
      8196,
      // three-per-em space
      8197,
      // four-per-em space
      8198,
      // six-per-em space
      8200,
      // punctuation space
      8201,
      // thin space
      8202,
      // hair space
      8287,
      // medium mathematical space
      12288
      // ideographic space
    ];
    /** Cache for measured text metrics */
    _CanvasTextMetrics._measurementCache = lru(1e3);
    let CanvasTextMetrics = _CanvasTextMetrics;

    "use strict";
    const PRECISION = 1e5;
    function getCanvasFillStyle(fillStyle, context, textMetrics, padding = 0) {
      var _a;
      if (fillStyle.texture === Texture.WHITE && !fillStyle.fill) {
        return Color.shared.setValue(fillStyle.color).setAlpha((_a = fillStyle.alpha) != null ? _a : 1).toHexa();
      } else if (!fillStyle.fill) {
        const pattern = context.createPattern(fillStyle.texture.source.resource, "repeat");
        const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);
        tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);
        pattern.setTransform(tempMatrix);
        return pattern;
      } else if (fillStyle.fill instanceof FillPattern) {
        const fillPattern = fillStyle.fill;
        const pattern = context.createPattern(fillPattern.texture.source.resource, "repeat");
        const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);
        tempMatrix.scale(
          fillPattern.texture.frame.width,
          fillPattern.texture.frame.height
        );
        pattern.setTransform(tempMatrix);
        return pattern;
      } else if (fillStyle.fill instanceof FillGradient) {
        const fillGradient = fillStyle.fill;
        const isLinear = fillGradient.type === "linear";
        const isLocal = fillGradient.textureSpace === "local";
        let width = 1;
        let height = 1;
        if (isLocal && textMetrics) {
          width = textMetrics.width + padding;
          height = textMetrics.height + padding;
        }
        let gradient;
        let isNearlyVertical = false;
        if (isLinear) {
          const { start, end } = fillGradient;
          gradient = context.createLinearGradient(
            start.x * width,
            start.y * height,
            end.x * width,
            end.y * height
          );
          isNearlyVertical = Math.abs(end.x - start.x) < Math.abs((end.y - start.y) * 0.1);
        } else {
          const { center, innerRadius, outerCenter, outerRadius } = fillGradient;
          gradient = context.createRadialGradient(
            center.x * width,
            center.y * height,
            innerRadius * width,
            outerCenter.x * width,
            outerCenter.y * height,
            outerRadius * width
          );
        }
        if (isNearlyVertical && isLocal && textMetrics) {
          const ratio = textMetrics.lineHeight / height;
          for (let i = 0; i < textMetrics.lines.length; i++) {
            const start = (i * textMetrics.lineHeight + padding / 2) / height;
            fillGradient.colorStops.forEach((stop) => {
              const globalStop = start + stop.offset * ratio;
              gradient.addColorStop(
                // fix to 5 decimal places to avoid floating point precision issues
                Math.floor(globalStop * PRECISION) / PRECISION,
                Color.shared.setValue(stop.color).toHex()
              );
            });
          }
        } else {
          fillGradient.colorStops.forEach((stop) => {
            gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());
          });
        }
        return gradient;
      }
      warn("FillStyle not recognised", fillStyle);
      return "red";
    }

    "use strict";
    const tempRect$1 = new Rectangle();
    class CanvasTextGeneratorClass {
      /**
       * Creates a canvas with the specified text rendered to it.
       *
       * Generates a canvas of appropriate size, renders the text with the provided style,
       * and returns both the canvas/context and a Rectangle representing the text bounds.
       *
       * When trim is enabled in the style, the frame will represent the bounds of the
       * non-transparent pixels, which can be smaller than the full canvas.
       * @param options - The options for generating the text canvas
       * @param options.text - The text to render
       * @param options.style - The style to apply to the text
       * @param options.resolution - The resolution of the canvas (defaults to 1)
       * @param options.padding
       * @returns An object containing the canvas/context and the frame (bounds) of the text
       */
      getCanvasAndContext(options) {
        const { text, style, resolution = 1 } = options;
        const padding = style._getFinalPadding();
        const measured = CanvasTextMetrics.measureText(text || " ", style);
        const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + padding * 2) * resolution);
        const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + padding * 2) * resolution);
        const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height);
        this._renderTextToCanvas(text, style, padding, resolution, canvasAndContext);
        const frame = style.trim ? getCanvasBoundingBox({ canvas: canvasAndContext.canvas, width, height, resolution: 1, output: tempRect$1 }) : tempRect$1.set(0, 0, width, height);
        return {
          canvasAndContext,
          frame
        };
      }
      /**
       * Returns a canvas and context to the pool.
       *
       * This should be called when you're done with the canvas to allow reuse
       * and prevent memory leaks.
       * @param canvasAndContext - The canvas and context to return to the pool
       */
      returnCanvasAndContext(canvasAndContext) {
        CanvasPool.returnCanvasAndContext(canvasAndContext);
      }
      /**
       * Renders text to its canvas, and updates its texture.
       * @param text - The text to render
       * @param style - The style of the text
       * @param padding - The padding of the text
       * @param resolution - The resolution of the text
       * @param canvasAndContext - The canvas and context to render the text to
       */
      _renderTextToCanvas(text, style, padding, resolution, canvasAndContext) {
        var _a, _b, _c, _d, _e;
        const { canvas, context } = canvasAndContext;
        const font = fontStringFromTextStyle(style);
        const measured = CanvasTextMetrics.measureText(text || " ", style);
        const lines = measured.lines;
        const lineHeight = measured.lineHeight;
        const lineWidths = measured.lineWidths;
        const maxLineWidth = measured.maxLineWidth;
        const fontProperties = measured.fontProperties;
        const height = canvas.height;
        context.resetTransform();
        context.scale(resolution, resolution);
        context.textBaseline = style.textBaseline;
        if ((_a = style._stroke) == null ? void 0 : _a.width) {
          const strokeStyle = style._stroke;
          context.lineWidth = strokeStyle.width;
          context.miterLimit = strokeStyle.miterLimit;
          context.lineJoin = strokeStyle.join;
          context.lineCap = strokeStyle.cap;
        }
        context.font = font;
        let linePositionX;
        let linePositionY;
        const passesCount = style.dropShadow ? 2 : 1;
        for (let i = 0; i < passesCount; ++i) {
          const isShadowPass = style.dropShadow && i === 0;
          const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + padding * 2) : 0;
          const dsOffsetShadow = dsOffsetText * resolution;
          if (isShadowPass) {
            context.fillStyle = "black";
            context.strokeStyle = "black";
            const shadowOptions = style.dropShadow;
            const dropShadowColor = shadowOptions.color;
            const dropShadowAlpha = shadowOptions.alpha;
            context.shadowColor = Color.shared.setValue(dropShadowColor).setAlpha(dropShadowAlpha).toRgbaString();
            const dropShadowBlur = shadowOptions.blur * resolution;
            const dropShadowDistance = shadowOptions.distance * resolution;
            context.shadowBlur = dropShadowBlur;
            context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
            context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance + dsOffsetShadow;
          } else {
            context.fillStyle = style._fill ? getCanvasFillStyle(style._fill, context, measured, padding * 2) : null;
            if ((_b = style._stroke) == null ? void 0 : _b.width) {
              const strokePadding = style._stroke.width * 0.5 + padding * 2;
              context.strokeStyle = getCanvasFillStyle(style._stroke, context, measured, strokePadding);
            }
            context.shadowColor = "black";
          }
          let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;
          if (lineHeight - fontProperties.fontSize < 0) {
            linePositionYShift = 0;
          }
          const strokeWidth = (_d = (_c = style._stroke) == null ? void 0 : _c.width) != null ? _d : 0;
          for (let i2 = 0; i2 < lines.length; i2++) {
            linePositionX = strokeWidth / 2;
            linePositionY = strokeWidth / 2 + i2 * lineHeight + fontProperties.ascent + linePositionYShift;
            if (style.align === "right") {
              linePositionX += maxLineWidth - lineWidths[i2];
            } else if (style.align === "center") {
              linePositionX += (maxLineWidth - lineWidths[i2]) / 2;
            }
            if ((_e = style._stroke) == null ? void 0 : _e.width) {
              this._drawLetterSpacing(
                lines[i2],
                style,
                canvasAndContext,
                linePositionX + padding,
                linePositionY + padding - dsOffsetText,
                true
              );
            }
            if (style._fill !== void 0) {
              this._drawLetterSpacing(
                lines[i2],
                style,
                canvasAndContext,
                linePositionX + padding,
                linePositionY + padding - dsOffsetText
              );
            }
          }
        }
      }
      /**
       * Render the text with letter-spacing.
       *
       * This method handles rendering text with the correct letter spacing, using either:
       * 1. Native letter spacing if supported by the browser
       * 2. Manual letter spacing calculation if not natively supported
       *
       * For manual letter spacing, it calculates the position of each character
       * based on its width and the desired spacing.
       * @param text - The text to draw
       * @param style - The text style to apply
       * @param canvasAndContext - The canvas and context to draw to
       * @param x - Horizontal position to draw the text
       * @param y - Vertical position to draw the text
       * @param isStroke - Whether to render the stroke (true) or fill (false)
       * @private
       */
      _drawLetterSpacing(text, style, canvasAndContext, x, y, isStroke = false) {
        const { context } = canvasAndContext;
        const letterSpacing = style.letterSpacing;
        let useExperimentalLetterSpacing = false;
        if (CanvasTextMetrics.experimentalLetterSpacingSupported) {
          if (CanvasTextMetrics.experimentalLetterSpacing) {
            context.letterSpacing = `${letterSpacing}px`;
            context.textLetterSpacing = `${letterSpacing}px`;
            useExperimentalLetterSpacing = true;
          } else {
            context.letterSpacing = "0px";
            context.textLetterSpacing = "0px";
          }
        }
        if (letterSpacing === 0 || useExperimentalLetterSpacing) {
          if (isStroke) {
            context.strokeText(text, x, y);
          } else {
            context.fillText(text, x, y);
          }
          return;
        }
        let currentPosition = x;
        const stringArray = CanvasTextMetrics.graphemeSegmenter(text);
        let previousWidth = context.measureText(text).width;
        let currentWidth = 0;
        for (let i = 0; i < stringArray.length; ++i) {
          const currentChar = stringArray[i];
          if (isStroke) {
            context.strokeText(currentChar, currentPosition, y);
          } else {
            context.fillText(currentChar, currentPosition, y);
          }
          let textStr = "";
          for (let j = i + 1; j < stringArray.length; ++j) {
            textStr += stringArray[j];
          }
          currentWidth = context.measureText(textStr).width;
          currentPosition += previousWidth - currentWidth + letterSpacing;
          previousWidth = currentWidth;
        }
      }
    }
    const CanvasTextGenerator = new CanvasTextGeneratorClass();

    "use strict";
    class CanvasTextSystem {
      constructor(_renderer) {
        this._activeTextures = {};
        this._renderer = _renderer;
      }
      getTexture(options, _resolution, _style, _textKey) {
        var _a;
        if (typeof options === "string") {
          deprecation("8.0.0", "CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments");
          options = {
            text: options,
            style: _style,
            resolution: _resolution
          };
        }
        if (!(options.style instanceof TextStyle)) {
          options.style = new TextStyle(options.style);
        }
        if (!(options.textureStyle instanceof TextureStyle)) {
          options.textureStyle = new TextureStyle(options.textureStyle);
        }
        if (typeof options.text !== "string") {
          options.text = options.text.toString();
        }
        const { text, style, textureStyle } = options;
        const resolution = (_a = options.resolution) != null ? _a : this._renderer.resolution;
        const { frame, canvasAndContext } = CanvasTextGenerator.getCanvasAndContext({
          text,
          style,
          resolution
        });
        const texture = getPo2TextureFromSource(canvasAndContext.canvas, frame.width, frame.height, resolution);
        if (textureStyle)
          texture.source.style = textureStyle;
        if (style.trim) {
          frame.pad(style.padding);
          texture.frame.copyFrom(frame);
          texture.frame.scale(1 / resolution);
          texture.updateUvs();
        }
        if (style.filters) {
          const filteredTexture = this._applyFilters(texture, style.filters);
          this.returnTexture(texture);
          CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);
          return filteredTexture;
        }
        this._renderer.texture.initSource(texture._source);
        CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);
        return texture;
      }
      /**
       * Returns a texture that was created wit the above `getTexture` function.
       * Handy if you are done with a texture and want to return it to the pool.
       * @param texture - The texture to be returned.
       */
      returnTexture(texture) {
        const source = texture.source;
        source.resource = null;
        source.uploadMethodId = "unknown";
        source.alphaMode = "no-premultiply-alpha";
        TexturePool.returnTexture(texture, true);
      }
      /**
       * Renders text to its canvas, and updates its texture.
       * @deprecated since 8.10.0
       */
      renderTextToCanvas() {
        deprecation(
          "8.10.0",
          "CanvasTextSystem.renderTextToCanvas: no longer supported, use CanvasTextSystem.getTexture instead"
        );
      }
      /**
       * Gets or creates a managed texture for a Text object. This method handles texture reuse and reference counting.
       * @param text - The Text object that needs a texture
       * @returns A Texture instance that represents the rendered text
       * @remarks
       * This method performs the following:
       * 1. Sets the appropriate resolution based on auto-resolution settings
       * 2. Checks if a texture already exists for the text's style
       * 3. Creates a new texture if needed or returns an existing one
       * 4. Manages reference counting for texture reuse
       */
      getManagedTexture(text) {
        text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
        const textKey = text.styleKey;
        if (this._activeTextures[textKey]) {
          this._increaseReferenceCount(textKey);
          return this._activeTextures[textKey].texture;
        }
        const texture = this.getTexture({
          text: text.text,
          style: text.style,
          resolution: text._resolution,
          textureStyle: text.textureStyle
        });
        this._activeTextures[textKey] = {
          texture,
          usageCount: 1
        };
        return texture;
      }
      /**
       * Decreases the reference count for a texture associated with a text key.
       * When the reference count reaches zero, the texture is returned to the pool.
       * @param textKey - The unique key identifying the text style configuration
       * @remarks
       * This method is crucial for memory management, ensuring textures are properly
       * cleaned up when they are no longer needed by any Text instances.
       */
      decreaseReferenceCount(textKey) {
        const activeTexture = this._activeTextures[textKey];
        activeTexture.usageCount--;
        if (activeTexture.usageCount === 0) {
          this.returnTexture(activeTexture.texture);
          this._activeTextures[textKey] = null;
        }
      }
      /**
       * Gets the current reference count for a texture associated with a text key.
       * @param textKey - The unique key identifying the text style configuration
       * @returns The number of Text instances currently using this texture
       */
      getReferenceCount(textKey) {
        var _a, _b;
        return (_b = (_a = this._activeTextures[textKey]) == null ? void 0 : _a.usageCount) != null ? _b : 0;
      }
      _increaseReferenceCount(textKey) {
        this._activeTextures[textKey].usageCount++;
      }
      /**
       * Applies the specified filters to the given texture.
       *
       * This method takes a texture and a list of filters, applies the filters to the texture,
       * and returns the resulting texture. It also ensures that the alpha mode of the resulting
       * texture is set to 'premultiplied-alpha'.
       * @param {Texture} texture - The texture to which the filters will be applied.
       * @param {Filter[]} filters - The filters to apply to the texture.
       * @returns {Texture} The resulting texture after all filters have been applied.
       */
      _applyFilters(texture, filters) {
        const currentRenderTarget = this._renderer.renderTarget.renderTarget;
        const resultTexture = this._renderer.filter.generateFilteredTexture({
          texture,
          filters
        });
        this._renderer.renderTarget.bind(currentRenderTarget, false);
        return resultTexture;
      }
      destroy() {
        this._renderer = null;
        for (const key in this._activeTextures) {
          if (this._activeTextures[key])
            this.returnTexture(this._activeTextures[key].texture);
        }
        this._activeTextures = null;
      }
    }
    /** @ignore */
    CanvasTextSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "canvasText"
    };

    "use strict";
    extensions.add(CanvasTextSystem);
    extensions.add(CanvasTextPipe);

    "use strict";
    var __defProp$U = Object.defineProperty;
    var __getOwnPropSymbols$W = Object.getOwnPropertySymbols;
    var __hasOwnProp$W = Object.prototype.hasOwnProperty;
    var __propIsEnum$W = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$U = (obj, key, value) => key in obj ? __defProp$U(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$U = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$W.call(b, prop))
          __defNormalProp$U(a, prop, b[prop]);
      if (__getOwnPropSymbols$W)
        for (var prop of __getOwnPropSymbols$W(b)) {
          if (__propIsEnum$W.call(b, prop))
            __defNormalProp$U(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$k = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$W.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$W)
        for (var prop of __getOwnPropSymbols$W(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$W.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class Graphics extends ViewContainer {
      /**
       * Creates a new Graphics object.
       * @param options - Options for the Graphics.
       */
      constructor(options) {
        if (options instanceof GraphicsContext) {
          options = { context: options };
        }
        const _a = options || {}, { context, roundPixels } = _a, rest = __objRest$k(_a, ["context", "roundPixels"]);
        super(__spreadValues$U({
          label: "Graphics"
        }, rest));
        /** @internal */
        this.renderPipeId = "graphics";
        if (!context) {
          this.context = this._ownedContext = new GraphicsContext();
          this.context.autoGarbageCollect = this.autoGarbageCollect;
        } else {
          this.context = context;
        }
        this.didViewUpdate = true;
        this.allowChildren = false;
        this.roundPixels = roundPixels != null ? roundPixels : false;
      }
      set context(context) {
        if (context === this._context)
          return;
        if (this._context) {
          this._context.off("update", this.onViewUpdate, this);
          this._context.off("unload", this.unload, this);
        }
        this._context = context;
        this._context.on("update", this.onViewUpdate, this);
        this._context.on("unload", this.unload, this);
        this.onViewUpdate();
      }
      /**
       * The underlying graphics context used for drawing operations.
       * Controls how shapes and paths are rendered.
       * @example
       * ```ts
       * // Create a shared context
       * const sharedContext = new GraphicsContext();
       *
       * // Create graphics objects sharing the same context
       * const graphics1 = new Graphics();
       * const graphics2 = new Graphics();
       *
       * // Assign shared context
       * graphics1.context = sharedContext;
       * graphics2.context = sharedContext;
       *
       * // Both graphics will show the same shapes
       * sharedContext
       *     .rect(0, 0, 100, 100)
       *     .fill({ color: 0xff0000 });
       * ```
       * @see {@link GraphicsContext} For drawing operations
       * @see {@link GraphicsOptions} For context configuration
       */
      get context() {
        return this._context;
      }
      /**
       * The local bounds of the graphics object.
       * Returns the boundaries after all graphical operations but before any transforms.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Draw a shape
       * graphics
       *     .rect(0, 0, 100, 100)
       *     .fill({ color: 0xff0000 });
       *
       * // Get bounds information
       * const bounds = graphics.bounds;
       * console.log(bounds.width);  // 100
       * console.log(bounds.height); // 100
       * ```
       * @readonly
       * @see {@link Bounds} For bounds operations
       * @see {@link Container#getBounds} For transformed bounds
       */
      get bounds() {
        return this._context.bounds;
      }
      /**
       * Graphics objects do not need to update their bounds as the context handles this.
       * @private
       */
      updateBounds() {
      }
      /**
       * Checks if the object contains the given point.
       * Returns true if the point lies within the Graphics object's rendered area.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Draw a shape
       * graphics
       *     .rect(0, 0, 100, 100)
       *     .fill({ color: 0xff0000 });
       *
       * // Check point intersection
       * if (graphics.containsPoint({ x: 50, y: 50 })) {
       *     console.log('Point is inside rectangle!');
       * }
       * ```
       * @param point - The point to check in local coordinates
       * @returns True if the point is inside the Graphics object
       * @see {@link Graphics#bounds} For bounding box checks
       * @see {@link PointData} For point data structure
       */
      containsPoint(point) {
        return this._context.containsPoint(point);
      }
      /**
       * Destroys this graphics renderable and optionally its context.
       * @param options - Options parameter. A boolean will act as if all options
       *
       * If the context was created by this graphics and `destroy(false)` or `destroy()` is called
       * then the context will still be destroyed.
       *
       * If you want to explicitly not destroy this context that this graphics created,
       * then you should pass destroy({ context: false })
       *
       * If the context was passed in as an argument to the constructor then it will not be destroyed
       * @example
       * ```ts
       * // Destroy the graphics and its context
       * graphics.destroy();
       * graphics.destroy(true);
       * graphics.destroy({ context: true, texture: true, textureSource: true });
       * ```
       */
      destroy(options) {
        if (this._ownedContext && !options) {
          this._ownedContext.destroy(options);
        } else if (options === true || (options == null ? void 0 : options.context) === true) {
          this._context.destroy(options);
        }
        this._ownedContext = null;
        this._context = null;
        super.destroy(options);
      }
      /**
       * @param now - The current time in milliseconds.
       * @internal
       */
      _onTouch(now) {
        this._gcLastUsed = now;
        this._context._gcLastUsed = now;
      }
      _callContextMethod(method, args) {
        this.context[method](...args);
        return this;
      }
      // --------------------------------------- GraphicsContext methods ---------------------------------------
      /**
       * Sets the current fill style of the graphics context.
       * The fill style can be a color, gradient, pattern, or a complex style object.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Basic color fill
       * graphics
       *     .setFillStyle({ color: 0xff0000 }) // Red fill
       *     .rect(0, 0, 100, 100)
       *     .fill();
       *
       * // Gradient fill
       * const gradient = new FillGradient({
       *    end: { x: 1, y: 0 },
       *    colorStops: [
       *         { offset: 0, color: 0xff0000 }, // Red at start
       *         { offset: 0.5, color: 0x00ff00 }, // Green at middle
       *         { offset: 1, color: 0x0000ff }, // Blue at end
       *    ],
       * });
       *
       * graphics
       *     .setFillStyle(gradient)
       *     .circle(100, 100, 50)
       *     .fill();
       *
       * // Pattern fill
       * const pattern = new FillPattern(texture);
       * graphics
       *     .setFillStyle({
       *         fill: pattern,
       *         alpha: 0.5
       *     })
       *     .rect(0, 0, 200, 200)
       *     .fill();
       * ```
       * @param {FillInput} args - The fill style to apply
       * @returns The Graphics instance for chaining
       * @see {@link FillStyle} For fill style options
       * @see {@link FillGradient} For gradient fills
       * @see {@link FillPattern} For pattern fills
       */
      setFillStyle(...args) {
        return this._callContextMethod("setFillStyle", args);
      }
      /**
       * Sets the current stroke style of the graphics context.
       * Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Basic color stroke
       * graphics
       *     .setStrokeStyle({
       *         width: 2,
       *         color: 0x000000
       *     })
       *     .rect(0, 0, 100, 100)
       *     .stroke();
       *
       * // Complex stroke style
       * graphics
       *     .setStrokeStyle({
       *         width: 4,
       *         color: 0xff0000,
       *         alpha: 0.5,
       *         join: 'round',
       *         cap: 'round',
       *         alignment: 0.5
       *     })
       *     .circle(100, 100, 50)
       *     .stroke();
       *
       * // Gradient stroke
       * const gradient = new FillGradient({
       *    end: { x: 1, y: 0 },
       *    colorStops: [
       *         { offset: 0, color: 0xff0000 }, // Red at start
       *         { offset: 0.5, color: 0x00ff00 }, // Green at middle
       *         { offset: 1, color: 0x0000ff }, // Blue at end
       *    ],
       * });
       *
       * graphics
       *     .setStrokeStyle({
       *         width: 10,
       *         fill: gradient
       *     })
       *     .poly([0,0, 100,50, 0,100])
       *     .stroke();
       * ```
       * @param {StrokeInput} args - The stroke style to apply
       * @returns The Graphics instance for chaining
       * @see {@link StrokeStyle} For stroke style options
       * @see {@link FillGradient} For gradient strokes
       * @see {@link FillPattern} For pattern strokes
       */
      setStrokeStyle(...args) {
        return this._callContextMethod("setStrokeStyle", args);
      }
      fill(...args) {
        return this._callContextMethod("fill", args);
      }
      /**
       * Strokes the current path with the current stroke style or specified style.
       * Outlines the shape using the stroke settings.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Stroke with direct color
       * graphics
       *     .circle(50, 50, 25)
       *     .stroke({
       *         width: 2,
       *         color: 0xff0000
       *     }); // 2px red stroke
       *
       * // Fill with texture
       * graphics
       *    .rect(0, 0, 100, 100)
       *    .stroke(myTexture); // Fill with texture
       *
       * // Stroke with gradient
       * const gradient = new FillGradient({
       *     end: { x: 1, y: 0 },
       *     colorStops: [
       *         { offset: 0, color: 0xff0000 },
       *         { offset: 0.5, color: 0x00ff00 },
       *         { offset: 1, color: 0x0000ff },
       *     ],
       * });
       *
       * graphics
       *     .rect(0, 0, 100, 100)
       *     .stroke({
       *         width: 4,
       *         fill: gradient,
       *         alignment: 0.5,
       *         join: 'round'
       *     });
       * ```
       * @param {StrokeStyle} args - Optional stroke style to apply. Can be:
       * - A stroke style object with width, color, etc.
       * - A gradient
       * - A pattern
       * If omitted, uses current stroke style.
       * @returns The Graphics instance for chaining
       * @see {@link StrokeStyle} For stroke style options
       * @see {@link FillGradient} For gradient strokes
       * @see {@link setStrokeStyle} For setting default stroke style
       */
      stroke(...args) {
        return this._callContextMethod("stroke", args);
      }
      texture(...args) {
        return this._callContextMethod("texture", args);
      }
      /**
       * Resets the current path. Any previous path and its commands are discarded and a new path is
       * started. This is typically called before beginning a new shape or series of drawing commands.
       * @example
       * ```ts
       * const graphics = new Graphics();
       * graphics
       *     .circle(150, 150, 50)
       *     .fill({ color: 0x00ff00 })
       *     .beginPath() // Starts a new path
       *     .circle(250, 150, 50)
       *     .fill({ color: 0x0000ff });
       * ```
       * @returns The Graphics instance for chaining
       * @see {@link Graphics#moveTo} For starting a new subpath
       * @see {@link Graphics#closePath} For closing the current path
       */
      beginPath() {
        return this._callContextMethod("beginPath", []);
      }
      /**
       * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
       * subtracting a path from the previously drawn path.
       *
       * If a hole is not completely in a shape, it will fail to cut correctly.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Draw outer circle
       * graphics
       *     .circle(100, 100, 50)
       *     .fill({ color: 0xff0000 });
       *     .circle(100, 100, 25) // Inner circle
       *     .cut() // Cuts out the inner circle from the outer circle
       * ```
       */
      cut() {
        return this._callContextMethod("cut", []);
      }
      arc(...args) {
        return this._callContextMethod("arc", args);
      }
      arcTo(...args) {
        return this._callContextMethod("arcTo", args);
      }
      arcToSvg(...args) {
        return this._callContextMethod("arcToSvg", args);
      }
      bezierCurveTo(...args) {
        return this._callContextMethod("bezierCurveTo", args);
      }
      /**
       * Closes the current path by drawing a straight line back to the start point.
       *
       * This is useful for completing shapes and ensuring they are properly closed for fills.
       * @example
       * ```ts
       * // Create a triangle with closed path
       * const graphics = new Graphics();
       * graphics
       *     .moveTo(50, 50)
       *     .lineTo(100, 100)
       *     .lineTo(0, 100)
       *     .closePath()
       * ```
       * @returns The Graphics instance for method chaining
       * @see {@link Graphics#beginPath} For starting a new path
       * @see {@link Graphics#fill} For filling closed paths
       * @see {@link Graphics#stroke} For stroking paths
       */
      closePath() {
        return this._callContextMethod("closePath", []);
      }
      ellipse(...args) {
        return this._callContextMethod("ellipse", args);
      }
      circle(...args) {
        return this._callContextMethod("circle", args);
      }
      path(...args) {
        return this._callContextMethod("path", args);
      }
      lineTo(...args) {
        return this._callContextMethod("lineTo", args);
      }
      moveTo(...args) {
        return this._callContextMethod("moveTo", args);
      }
      quadraticCurveTo(...args) {
        return this._callContextMethod("quadraticCurveTo", args);
      }
      rect(...args) {
        return this._callContextMethod("rect", args);
      }
      roundRect(...args) {
        return this._callContextMethod("roundRect", args);
      }
      poly(...args) {
        return this._callContextMethod("poly", args);
      }
      regularPoly(...args) {
        return this._callContextMethod("regularPoly", args);
      }
      roundPoly(...args) {
        return this._callContextMethod("roundPoly", args);
      }
      roundShape(...args) {
        return this._callContextMethod("roundShape", args);
      }
      filletRect(...args) {
        return this._callContextMethod("filletRect", args);
      }
      chamferRect(...args) {
        return this._callContextMethod("chamferRect", args);
      }
      star(...args) {
        return this._callContextMethod("star", args);
      }
      svg(...args) {
        return this._callContextMethod("svg", args);
      }
      restore(...args) {
        return this._callContextMethod("restore", args);
      }
      /**
       * Saves the current graphics state onto a stack. The state includes:
       * - Current transformation matrix
       * - Current fill style
       * - Current stroke style
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Save state before complex operations
       * graphics.save();
       *
       * // Create transformed and styled shape
       * graphics
       *     .translateTransform(100, 100)
       *     .rotateTransform(Math.PI / 4)
       *     .setFillStyle({
       *         color: 0xff0000,
       *         alpha: 0.5
       *     })
       *     .rect(-25, -25, 50, 50)
       *     .fill();
       *
       * // Restore to original state
       * graphics.restore();
       *
       * // Continue drawing with previous state
       * graphics
       *     .circle(50, 50, 25)
       *     .fill();
       * ```
       * @returns The Graphics instance for method chaining
       * @see {@link Graphics#restore} For restoring the saved state
       * @see {@link Graphics#setTransform} For setting transformations
       */
      save() {
        return this._callContextMethod("save", []);
      }
      /**
       * Returns the current transformation matrix of the graphics context.
       * This matrix represents all accumulated transformations including translate, scale, and rotate.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Apply some transformations
       * graphics
       *     .translateTransform(100, 100)
       *     .rotateTransform(Math.PI / 4);
       *
       * // Get the current transform matrix
       * const matrix = graphics.getTransform();
       * console.log(matrix.tx, matrix.ty); // 100, 100
       *
       * // Use the matrix for other operations
       * graphics
       *     .setTransform(matrix)
       *     .circle(0, 0, 50)
       *     .fill({ color: 0xff0000 });
       * ```
       * @returns The current transformation matrix.
       * @see {@link Graphics#setTransform} For setting the transform matrix
       * @see {@link Matrix} For matrix operations
       */
      getTransform() {
        return this.context.getTransform();
      }
      /**
       * Resets the current transformation matrix to the identity matrix, effectively removing
       * any transformations (rotation, scaling, translation) previously applied.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Apply transformations
       * graphics
       *     .translateTransform(100, 100)
       *     .scaleTransform(2, 2)
       *     .circle(0, 0, 25)
       *     .fill({ color: 0xff0000 });
       * // Reset transform to default state
       * graphics
       *     .resetTransform()
       *     .circle(50, 50, 25) // Will draw at actual coordinates
       *     .fill({ color: 0x00ff00 });
       * ```
       * @returns The Graphics instance for method chaining
       * @see {@link Graphics#getTransform} For getting the current transform
       * @see {@link Graphics#setTransform} For setting a specific transform
       * @see {@link Graphics#save} For saving the current transform state
       * @see {@link Graphics#restore} For restoring a previous transform state
       */
      resetTransform() {
        return this._callContextMethod("resetTransform", []);
      }
      rotateTransform(...args) {
        return this._callContextMethod("rotate", args);
      }
      scaleTransform(...args) {
        return this._callContextMethod("scale", args);
      }
      setTransform(...args) {
        return this._callContextMethod("setTransform", args);
      }
      transform(...args) {
        return this._callContextMethod("transform", args);
      }
      translateTransform(...args) {
        return this._callContextMethod("translate", args);
      }
      /**
       * Clears all drawing commands from the graphics context, effectively resetting it.
       * This includes clearing the current path, fill style, stroke style, and transformations.
       *
       * > [!NOTE] Graphics objects are not designed to be continuously cleared and redrawn.
       * > Instead, they are intended to be used for static or semi-static graphics that
       * > can be redrawn as needed. Frequent clearing and redrawing may lead to performance issues.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Draw some shapes
       * graphics
       *     .circle(100, 100, 50)
       *     .fill({ color: 0xff0000 })
       *     .rect(200, 100, 100, 50)
       *     .fill({ color: 0x00ff00 });
       *
       * // Clear all graphics
       * graphics.clear();
       *
       * // Start fresh with new shapes
       * graphics
       *     .circle(150, 150, 30)
       *     .fill({ color: 0x0000ff });
       * ```
       * @returns The Graphics instance for method chaining
       * @see {@link Graphics#beginPath} For starting a new path without clearing styles
       * @see {@link Graphics#save} For saving the current state
       * @see {@link Graphics#restore} For restoring a previous state
       */
      clear() {
        return this._callContextMethod("clear", []);
      }
      /**
       * Gets or sets the current fill style for the graphics context. The fill style determines
       * how shapes are filled when using the fill() method.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Basic color fill
       * graphics.fillStyle = {
       *     color: 0xff0000,  // Red
       *     alpha: 1
       * };
       *
       * // Using gradients
       * const gradient = new FillGradient({
       *     end: { x: 0, y: 1 }, // Vertical gradient
       *     stops: [
       *         { offset: 0, color: 0xff0000, alpha: 1 }, // Start color
       *         { offset: 1, color: 0x0000ff, alpha: 1 }  // End color
       *     ]
       * });
       *
       * graphics.fillStyle = {
       *     fill: gradient,
       *     alpha: 0.8
       * };
       *
       * // Using patterns
       * graphics.fillStyle = {
       *     texture: myTexture,
       *     alpha: 1,
       *     matrix: new Matrix()
       *         .scale(0.5, 0.5)
       *         .rotate(Math.PI / 4)
       * };
       * ```
       * @type {ConvertedFillStyle}
       * @see {@link FillStyle} For all available fill style options
       * @see {@link FillGradient} For creating gradient fills
       * @see {@link Graphics#fill} For applying the fill to paths
       */
      get fillStyle() {
        return this._context.fillStyle;
      }
      set fillStyle(value) {
        this._context.fillStyle = value;
      }
      /**
       * Gets or sets the current stroke style for the graphics context. The stroke style determines
       * how paths are outlined when using the stroke() method.
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Basic stroke style
       * graphics.strokeStyle = {
       *     width: 2,
       *     color: 0xff0000,
       *     alpha: 1
       * };
       *
       * // Using with gradients
       * const gradient = new FillGradient({
       *   end: { x: 0, y: 1 },
       *   stops: [
       *       { offset: 0, color: 0xff0000, alpha: 1 },
       *       { offset: 1, color: 0x0000ff, alpha: 1 }
       *   ]
       * });
       *
       * graphics.strokeStyle = {
       *     width: 4,
       *     fill: gradient,
       *     alignment: 0.5,
       *     join: 'round',
       *     cap: 'round'
       * };
       *
       * // Complex stroke settings
       * graphics.strokeStyle = {
       *     width: 6,
       *     color: 0x00ff00,
       *     alpha: 0.5,
       *     join: 'miter',
       *     miterLimit: 10,
       * };
       * ```
       * @see {@link StrokeStyle} For all available stroke style options
       * @see {@link Graphics#stroke} For applying the stroke to paths
       */
      get strokeStyle() {
        return this._context.strokeStyle;
      }
      set strokeStyle(value) {
        this._context.strokeStyle = value;
      }
      /**
       * Creates a new Graphics object that copies the current graphics content.
       * The clone can either share the same context (shallow clone) or have its own independent
       * context (deep clone).
       * @example
       * ```ts
       * const graphics = new Graphics();
       *
       * // Create original graphics content
       * graphics
       *     .circle(100, 100, 50)
       *     .fill({ color: 0xff0000 });
       *
       * // Create a shallow clone (shared context)
       * const shallowClone = graphics.clone();
       *
       * // Changes to original affect the clone
       * graphics
       *     .circle(200, 100, 30)
       *     .fill({ color: 0x00ff00 });
       *
       * // Create a deep clone (independent context)
       * const deepClone = graphics.clone(true);
       *
       * // Modify deep clone independently
       * deepClone
       *     .translateTransform(100, 100)
       *     .circle(0, 0, 40)
       *     .fill({ color: 0x0000ff });
       * ```
       * @param deep - Whether to create a deep clone of the graphics object.
       *              If false (default), the context will be shared between objects.
       *              If true, creates an independent copy of the context.
       * @returns A new Graphics instance with either shared or copied context
       * @see {@link Graphics#context} For accessing the underlying graphics context
       * @see {@link GraphicsContext} For understanding the shared context behavior
       */
      clone(deep = false) {
        if (deep) {
          return new Graphics(this._context.clone());
        }
        this._ownedContext = null;
        const clone = new Graphics(this._context);
        return clone;
      }
      // -------- v7 deprecations ---------
      /**
       * @param width
       * @param color
       * @param alpha
       * @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
       */
      lineStyle(width, color, alpha) {
        deprecation(v8_0_0, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style.");
        const strokeStyle = {};
        width && (strokeStyle.width = width);
        color && (strokeStyle.color = color);
        alpha && (strokeStyle.alpha = alpha);
        this.context.strokeStyle = strokeStyle;
        return this;
      }
      /**
       * @param color
       * @param alpha
       * @deprecated since 8.0.0 Use {@link Graphics#fill} instead
       */
      beginFill(color, alpha) {
        deprecation(v8_0_0, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
        const fillStyle = {};
        if (color !== void 0)
          fillStyle.color = color;
        if (alpha !== void 0)
          fillStyle.alpha = alpha;
        this.context.fillStyle = fillStyle;
        return this;
      }
      /**
       * @deprecated since 8.0.0 Use {@link Graphics#fill} instead
       */
      endFill() {
        deprecation(v8_0_0, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
        this.context.fill();
        const strokeStyle = this.context.strokeStyle;
        if (strokeStyle.width !== GraphicsContext.defaultStrokeStyle.width || strokeStyle.color !== GraphicsContext.defaultStrokeStyle.color || strokeStyle.alpha !== GraphicsContext.defaultStrokeStyle.alpha) {
          this.context.stroke();
        }
        return this;
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#circle} instead
       */
      drawCircle(...args) {
        deprecation(v8_0_0, "Graphics#drawCircle has been renamed to Graphics#circle");
        return this._callContextMethod("circle", args);
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
       */
      drawEllipse(...args) {
        deprecation(v8_0_0, "Graphics#drawEllipse has been renamed to Graphics#ellipse");
        return this._callContextMethod("ellipse", args);
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#poly} instead
       */
      drawPolygon(...args) {
        deprecation(v8_0_0, "Graphics#drawPolygon has been renamed to Graphics#poly");
        return this._callContextMethod("poly", args);
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#rect} instead
       */
      drawRect(...args) {
        deprecation(v8_0_0, "Graphics#drawRect has been renamed to Graphics#rect");
        return this._callContextMethod("rect", args);
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
       */
      drawRoundedRect(...args) {
        deprecation(v8_0_0, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect");
        return this._callContextMethod("roundRect", args);
      }
      /**
       * @param {...any} args
       * @deprecated since 8.0.0 Use {@link Graphics#star} instead
       */
      drawStar(...args) {
        deprecation(v8_0_0, "Graphics#drawStar has been renamed to Graphics#star");
        return this._callContextMethod("star", args);
      }
    }

    "use strict";
    const localUniformMSDFBit = {
      name: "local-uniform-msdf-bit",
      vertex: {
        header: (
          /* wgsl */
          `
            struct LocalUniforms {
                uColor:vec4<f32>,
                uTransformMatrix:mat3x3<f32>,
                uDistance: f32,
                uRound:f32,
            }

            @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
        `
        ),
        main: (
          /* wgsl */
          `
            vColor *= localUniforms.uColor;
            modelMatrix *= localUniforms.uTransformMatrix;
        `
        ),
        end: (
          /* wgsl */
          `
            if(localUniforms.uRound == 1)
            {
                vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
            }
        `
        )
      },
      fragment: {
        header: (
          /* wgsl */
          `
            struct LocalUniforms {
                uColor:vec4<f32>,
                uTransformMatrix:mat3x3<f32>,
                uDistance: f32
            }

            @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
         `
        ),
        main: (
          /* wgsl */
          `
            outColor = vec4<f32>(calculateMSDFAlpha(outColor, localUniforms.uColor, localUniforms.uDistance));
        `
        )
      }
    };
    const localUniformMSDFBitGl = {
      name: "local-uniform-msdf-bit",
      vertex: {
        header: (
          /* glsl */
          `
            uniform mat3 uTransformMatrix;
            uniform vec4 uColor;
            uniform float uRound;
        `
        ),
        main: (
          /* glsl */
          `
            vColor *= uColor;
            modelMatrix *= uTransformMatrix;
        `
        ),
        end: (
          /* glsl */
          `
            if(uRound == 1.)
            {
                gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
            }
        `
        )
      },
      fragment: {
        header: (
          /* glsl */
          `
            uniform float uDistance;
         `
        ),
        main: (
          /* glsl */
          `
            outColor = vec4(calculateMSDFAlpha(outColor, vColor, uDistance));
        `
        )
      }
    };

    "use strict";
    const mSDFBit = {
      name: "msdf-bit",
      fragment: {
        header: (
          /* wgsl */
          `
            fn calculateMSDFAlpha(msdfColor:vec4<f32>, shapeColor:vec4<f32>, distance:f32) -> f32 {

                // MSDF
                var median = msdfColor.r + msdfColor.g + msdfColor.b -
                    min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
                    max(msdfColor.r, max(msdfColor.g, msdfColor.b));

                // SDF
                median = min(median, msdfColor.a);

                var screenPxDistance = distance * (median - 0.5);
                var alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);
                if (median < 0.01) {
                    alpha = 0.0;
                } else if (median > 0.99) {
                    alpha = 1.0;
                }

                // Gamma correction for coverage-like alpha
                var luma: f32 = dot(shapeColor.rgb, vec3<f32>(0.299, 0.587, 0.114));
                var gamma: f32 = mix(1.0, 1.0 / 2.2, luma);
                var coverage: f32 = pow(shapeColor.a * alpha, gamma);

                return coverage;

            }
        `
        )
      }
    };
    const mSDFBitGl = {
      name: "msdf-bit",
      fragment: {
        header: (
          /* glsl */
          `
            float calculateMSDFAlpha(vec4 msdfColor, vec4 shapeColor, float distance) {

                // MSDF
                float median = msdfColor.r + msdfColor.g + msdfColor.b -
                                min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
                                max(msdfColor.r, max(msdfColor.g, msdfColor.b));

                // SDF
                median = min(median, msdfColor.a);

                float screenPxDistance = distance * (median - 0.5);
                float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);

                if (median < 0.01) {
                    alpha = 0.0;
                } else if (median > 0.99) {
                    alpha = 1.0;
                }

                // Gamma correction for coverage-like alpha
                float luma = dot(shapeColor.rgb, vec3(0.299, 0.587, 0.114));
                float gamma = mix(1.0, 1.0 / 2.2, luma);
                float coverage = pow(shapeColor.a * alpha, gamma);

                return coverage;
            }
        `
        )
      }
    };

    "use strict";
    let gpuProgram$1;
    let glProgram$1;
    class SdfShader extends Shader {
      constructor(maxTextures) {
        const uniforms = new UniformGroup({
          uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
          uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uDistance: { value: 4, type: "f32" },
          uRound: { value: 0, type: "f32" }
        });
        gpuProgram$1 != null ? gpuProgram$1 : gpuProgram$1 = compileHighShaderGpuProgram({
          name: "sdf-shader",
          bits: [
            colorBit,
            generateTextureBatchBit(maxTextures),
            localUniformMSDFBit,
            mSDFBit,
            roundPixelsBit
          ]
        });
        glProgram$1 != null ? glProgram$1 : glProgram$1 = compileHighShaderGlProgram({
          name: "sdf-shader",
          bits: [
            colorBitGl,
            generateTextureBatchBitGl(maxTextures),
            localUniformMSDFBitGl,
            mSDFBitGl,
            roundPixelsBitGl
          ]
        });
        super({
          glProgram: glProgram$1,
          gpuProgram: gpuProgram$1,
          resources: {
            localUniforms: uniforms,
            batchSamplers: getBatchSamplersUniformGroup(maxTextures)
          }
        });
      }
    }

    "use strict";
    class AbstractBitmapFont extends EventEmitter {
      constructor() {
        super(...arguments);
        /** The map of characters by character code. */
        this.chars = /* @__PURE__ */ Object.create(null);
        /**
         * The line-height of the font face in pixels.
         * @type {number}
         */
        this.lineHeight = 0;
        /**
         * The name of the font face
         * @type {string}
         */
        this.fontFamily = "";
        /** The metrics of the font face. */
        this.fontMetrics = { fontSize: 0, ascent: 0, descent: 0 };
        /**
         * The offset of the font face from the baseline.
         * @type {number}
         */
        this.baseLineOffset = 0;
        /** The range and type of the distance field for this font. */
        this.distanceField = { type: "none", range: 0 };
        /** The map of base page textures (i.e., sheets of glyphs). */
        this.pages = [];
        /** should the fill for this font be applied as a tint to the text. */
        this.applyFillAsTint = true;
        /** The size of the font face in pixels. */
        this.baseMeasurementFontSize = 100;
        this.baseRenderedFontSize = 100;
      }
      /**
       * The name of the font face.
       * @deprecated since 8.0.0 Use `fontFamily` instead.
       */
      get font() {
        deprecation(v8_0_0, "BitmapFont.font is deprecated, please use BitmapFont.fontFamily instead.");
        return this.fontFamily;
      }
      /**
       * The map of base page textures (i.e., sheets of glyphs).
       * @deprecated since 8.0.0 Use `pages` instead.
       */
      get pageTextures() {
        deprecation(v8_0_0, "BitmapFont.pageTextures is deprecated, please use BitmapFont.pages instead.");
        return this.pages;
      }
      /**
       * The size of the font face in pixels.
       * @deprecated since 8.0.0 Use `fontMetrics.fontSize` instead.
       */
      get size() {
        deprecation(v8_0_0, "BitmapFont.size is deprecated, please use BitmapFont.fontMetrics.fontSize instead.");
        return this.fontMetrics.fontSize;
      }
      /**
       * The kind of distance field for this font or "none".
       * @deprecated since 8.0.0 Use `distanceField.type` instead.
       */
      get distanceFieldRange() {
        deprecation(v8_0_0, "BitmapFont.distanceFieldRange is deprecated, please use BitmapFont.distanceField.range instead.");
        return this.distanceField.range;
      }
      /**
       * The range of the distance field in pixels.
       * @deprecated since 8.0.0 Use `distanceField.range` instead.
       */
      get distanceFieldType() {
        deprecation(v8_0_0, "BitmapFont.distanceFieldType is deprecated, please use BitmapFont.distanceField.type instead.");
        return this.distanceField.type;
      }
      destroy(destroyTextures = false) {
        var _a;
        this.emit("destroy", this);
        this.removeAllListeners();
        for (const i in this.chars) {
          (_a = this.chars[i].texture) == null ? void 0 : _a.destroy();
        }
        this.chars = null;
        if (destroyTextures) {
          this.pages.forEach((page) => page.texture.destroy(true));
          this.pages = null;
        }
      }
    }

    "use strict";
    var __defProp$T = Object.defineProperty;
    var __getOwnPropSymbols$V = Object.getOwnPropertySymbols;
    var __hasOwnProp$V = Object.prototype.hasOwnProperty;
    var __propIsEnum$V = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$T = (obj, key, value) => key in obj ? __defProp$T(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$T = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$V.call(b, prop))
          __defNormalProp$T(a, prop, b[prop]);
      if (__getOwnPropSymbols$V)
        for (var prop of __getOwnPropSymbols$V(b)) {
          if (__propIsEnum$V.call(b, prop))
            __defNormalProp$T(a, prop, b[prop]);
        }
      return a;
    };
    const _DynamicBitmapFont = class _DynamicBitmapFont extends AbstractBitmapFont {
      /**
       * @param options - The options for the dynamic bitmap font.
       */
      constructor(options) {
        var _a, _b, _c;
        super();
        /**
         * this is a resolution modifier for the font size..
         * texture resolution will also be used to scale texture according to its font size also
         */
        this.resolution = 1;
        /** The pages of the font. */
        this.pages = [];
        this._padding = 0;
        this._measureCache = /* @__PURE__ */ Object.create(null);
        this._currentChars = [];
        this._currentX = 0;
        this._currentY = 0;
        this._currentMaxCharHeight = 0;
        this._currentPageIndex = -1;
        this._skipKerning = false;
        const dynamicOptions = __spreadValues$T(__spreadValues$T({}, _DynamicBitmapFont.defaultOptions), options);
        this._textureSize = dynamicOptions.textureSize;
        this._mipmap = dynamicOptions.mipmap;
        const style = dynamicOptions.style.clone();
        if (dynamicOptions.overrideFill) {
          style._fill.color = 16777215;
          style._fill.alpha = 1;
          style._fill.texture = Texture.WHITE;
          style._fill.fill = null;
        }
        this.applyFillAsTint = dynamicOptions.overrideFill;
        const requestedFontSize = style.fontSize;
        style.fontSize = this.baseMeasurementFontSize;
        const font = fontStringFromTextStyle(style);
        if (dynamicOptions.overrideSize) {
          if (style._stroke) {
            style._stroke.width *= this.baseRenderedFontSize / requestedFontSize;
          }
        } else {
          style.fontSize = this.baseRenderedFontSize = requestedFontSize;
        }
        this._style = style;
        this._skipKerning = (_a = dynamicOptions.skipKerning) != null ? _a : false;
        this.resolution = (_b = dynamicOptions.resolution) != null ? _b : 1;
        this._padding = (_c = dynamicOptions.padding) != null ? _c : 4;
        if (dynamicOptions.textureStyle) {
          this._textureStyle = dynamicOptions.textureStyle instanceof TextureStyle ? dynamicOptions.textureStyle : new TextureStyle(dynamicOptions.textureStyle);
        }
        this.fontMetrics = CanvasTextMetrics.measureFont(font);
        this.lineHeight = style.lineHeight || this.fontMetrics.fontSize || style.fontSize;
      }
      ensureCharacters(chars) {
        var _a, _b, _c, _d;
        const charList = CanvasTextMetrics.graphemeSegmenter(chars).filter((char) => !this._currentChars.includes(char)).filter((char, index, self) => self.indexOf(char) === index);
        if (!charList.length)
          return;
        this._currentChars = [...this._currentChars, ...charList];
        let pageData;
        if (this._currentPageIndex === -1) {
          pageData = this._nextPage();
        } else {
          pageData = this.pages[this._currentPageIndex];
        }
        let { canvas, context } = pageData.canvasAndContext;
        let textureSource = pageData.texture.source;
        const style = this._style;
        let currentX = this._currentX;
        let currentY = this._currentY;
        let currentMaxCharHeight = this._currentMaxCharHeight;
        const fontScale = this.baseRenderedFontSize / this.baseMeasurementFontSize;
        const padding = this._padding * fontScale;
        let skipTexture = false;
        const maxTextureWidth = canvas.width / this.resolution;
        const maxTextureHeight = canvas.height / this.resolution;
        for (let i = 0; i < charList.length; i++) {
          const char = charList[i];
          const metrics = CanvasTextMetrics.measureText(char, style, canvas, false);
          metrics.lineHeight = metrics.height;
          const width = metrics.width * fontScale;
          const textureGlyphWidth = Math.ceil((style.fontStyle === "italic" ? 2 : 1) * width);
          const height = metrics.height * fontScale;
          const paddedWidth = textureGlyphWidth + padding * 2;
          const paddedHeight = height + padding * 2;
          skipTexture = false;
          if (char !== "\n" && char !== "\r" && char !== "	" && char !== " ") {
            skipTexture = true;
            currentMaxCharHeight = Math.ceil(Math.max(paddedHeight, currentMaxCharHeight));
          }
          if (currentX + paddedWidth > maxTextureWidth) {
            currentY += currentMaxCharHeight;
            currentMaxCharHeight = paddedHeight;
            currentX = 0;
            if (currentY + currentMaxCharHeight > maxTextureHeight) {
              textureSource.update();
              const pageData2 = this._nextPage();
              canvas = pageData2.canvasAndContext.canvas;
              context = pageData2.canvasAndContext.context;
              textureSource = pageData2.texture.source;
              currentX = 0;
              currentY = 0;
              currentMaxCharHeight = 0;
            }
          }
          const xAdvance = width / fontScale - ((_b = (_a = style.dropShadow) == null ? void 0 : _a.distance) != null ? _b : 0) - ((_d = (_c = style._stroke) == null ? void 0 : _c.width) != null ? _d : 0);
          this.chars[char] = {
            id: char.codePointAt(0),
            xOffset: -this._padding,
            yOffset: -this._padding,
            xAdvance,
            kerning: {}
          };
          if (skipTexture) {
            this._drawGlyph(
              context,
              metrics,
              currentX + padding,
              currentY + padding,
              fontScale,
              style
            );
            const px = textureSource.width * fontScale;
            const py = textureSource.height * fontScale;
            const frame = new Rectangle(
              currentX / px * textureSource.width,
              currentY / py * textureSource.height,
              paddedWidth / px * textureSource.width,
              paddedHeight / py * textureSource.height
            );
            this.chars[char].texture = new Texture({
              source: textureSource,
              frame
            });
            currentX += Math.ceil(paddedWidth);
          }
        }
        textureSource.update();
        this._currentX = currentX;
        this._currentY = currentY;
        this._currentMaxCharHeight = currentMaxCharHeight;
        this._skipKerning && this._applyKerning(charList, context);
      }
      /**
       * @deprecated since 8.0.0
       * The map of base page textures (i.e., sheets of glyphs).
       */
      get pageTextures() {
        deprecation(v8_0_0, "BitmapFont.pageTextures is deprecated, please use BitmapFont.pages instead.");
        return this.pages;
      }
      _applyKerning(newChars, context) {
        const measureCache = this._measureCache;
        for (let i = 0; i < newChars.length; i++) {
          const first = newChars[i];
          for (let j = 0; j < this._currentChars.length; j++) {
            const second = this._currentChars[j];
            let c1 = measureCache[first];
            if (!c1)
              c1 = measureCache[first] = context.measureText(first).width;
            let c2 = measureCache[second];
            if (!c2)
              c2 = measureCache[second] = context.measureText(second).width;
            let total = context.measureText(first + second).width;
            let amount = total - (c1 + c2);
            if (amount) {
              this.chars[first].kerning[second] = amount;
            }
            total = context.measureText(first + second).width;
            amount = total - (c1 + c2);
            if (amount) {
              this.chars[second].kerning[first] = amount;
            }
          }
        }
      }
      _nextPage() {
        this._currentPageIndex++;
        const textureResolution = this.resolution;
        const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(
          this._textureSize,
          this._textureSize,
          textureResolution
        );
        this._setupContext(canvasAndContext.context, this._style, textureResolution);
        const resolution = textureResolution * (this.baseRenderedFontSize / this.baseMeasurementFontSize);
        const texture = new Texture({
          source: new ImageSource({
            resource: canvasAndContext.canvas,
            resolution,
            alphaMode: "premultiply-alpha-on-upload",
            autoGenerateMipmaps: this._mipmap
          })
        });
        if (this._textureStyle) {
          texture.source.style = this._textureStyle;
        }
        const pageData = {
          canvasAndContext,
          texture
        };
        this.pages[this._currentPageIndex] = pageData;
        return pageData;
      }
      // canvas style!
      _setupContext(context, style, resolution) {
        var _a;
        style.fontSize = this.baseRenderedFontSize;
        context.scale(resolution, resolution);
        context.font = fontStringFromTextStyle(style);
        style.fontSize = this.baseMeasurementFontSize;
        context.textBaseline = style.textBaseline;
        const stroke = style._stroke;
        const strokeThickness = (_a = stroke == null ? void 0 : stroke.width) != null ? _a : 0;
        if (stroke) {
          context.lineWidth = strokeThickness;
          context.lineJoin = stroke.join;
          context.miterLimit = stroke.miterLimit;
          context.strokeStyle = getCanvasFillStyle(stroke, context);
        }
        if (style._fill) {
          context.fillStyle = getCanvasFillStyle(style._fill, context);
        }
        if (style.dropShadow) {
          const shadowOptions = style.dropShadow;
          const rgb = Color.shared.setValue(shadowOptions.color).toArray();
          const dropShadowBlur = shadowOptions.blur * resolution;
          const dropShadowDistance = shadowOptions.distance * resolution;
          context.shadowColor = `rgba(${rgb[0] * 255},${rgb[1] * 255},${rgb[2] * 255},${shadowOptions.alpha})`;
          context.shadowBlur = dropShadowBlur;
          context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
          context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance;
        } else {
          context.shadowColor = "black";
          context.shadowBlur = 0;
          context.shadowOffsetX = 0;
          context.shadowOffsetY = 0;
        }
      }
      _drawGlyph(context, metrics, x, y, fontScale, style) {
        var _a;
        const char = metrics.text;
        const fontProperties = metrics.fontProperties;
        const stroke = style._stroke;
        const strokeThickness = ((_a = stroke == null ? void 0 : stroke.width) != null ? _a : 0) * fontScale;
        const tx = x + strokeThickness / 2;
        const ty = y - strokeThickness / 2;
        const descent = fontProperties.descent * fontScale;
        const lineHeight = metrics.lineHeight * fontScale;
        let removeShadow = false;
        if (style.stroke && strokeThickness) {
          removeShadow = true;
          context.strokeText(char, tx, ty + lineHeight - descent);
        }
        const { shadowBlur, shadowOffsetX, shadowOffsetY } = context;
        if (style._fill) {
          if (removeShadow) {
            context.shadowBlur = 0;
            context.shadowOffsetX = 0;
            context.shadowOffsetY = 0;
          }
          context.fillText(char, tx, ty + lineHeight - descent);
        }
        if (removeShadow) {
          context.shadowBlur = shadowBlur;
          context.shadowOffsetX = shadowOffsetX;
          context.shadowOffsetY = shadowOffsetY;
        }
      }
      destroy() {
        super.destroy();
        for (let i = 0; i < this.pages.length; i++) {
          const { canvasAndContext, texture } = this.pages[i];
          CanvasPool.returnCanvasAndContext(canvasAndContext);
          texture.destroy(true);
        }
        this.pages = null;
      }
    };
    _DynamicBitmapFont.defaultOptions = {
      textureSize: 512,
      style: new TextStyle(),
      mipmap: true
    };
    let DynamicBitmapFont = _DynamicBitmapFont;

    "use strict";
    function getBitmapTextLayout(chars, style, font, trimEnd) {
      const layoutData = {
        width: 0,
        height: 0,
        offsetY: 0,
        scale: style.fontSize / font.baseMeasurementFontSize,
        lines: [{
          width: 0,
          charPositions: [],
          spaceWidth: 0,
          spacesIndex: [],
          chars: []
        }]
      };
      layoutData.offsetY = font.baseLineOffset;
      let currentLine = layoutData.lines[0];
      let previousChar = null;
      let firstWord = true;
      const currentWord = {
        spaceWord: false,
        width: 0,
        start: 0,
        index: 0,
        // use index to not modify the array as we use it a lot!
        positions: [],
        chars: []
      };
      const scale = font.baseMeasurementFontSize / style.fontSize;
      const adjustedLetterSpacing = style.letterSpacing * scale;
      const adjustedWordWrapWidth = style.wordWrapWidth * scale;
      const adjustedLineHeight = style.lineHeight ? style.lineHeight * scale : font.lineHeight;
      const breakWords = style.wordWrap && style.breakWords;
      const nextWord = (word) => {
        const start = currentLine.width;
        for (let j = 0; j < currentWord.index; j++) {
          const position = word.positions[j];
          currentLine.chars.push(word.chars[j]);
          currentLine.charPositions.push(position + start);
        }
        currentLine.width += word.width;
        firstWord = false;
        currentWord.width = 0;
        currentWord.index = 0;
        currentWord.chars.length = 0;
      };
      const nextLine = () => {
        let index = currentLine.chars.length - 1;
        if (trimEnd) {
          let lastChar = currentLine.chars[index];
          while (lastChar === " ") {
            currentLine.width -= font.chars[lastChar].xAdvance;
            lastChar = currentLine.chars[--index];
          }
        }
        layoutData.width = Math.max(layoutData.width, currentLine.width);
        currentLine = {
          width: 0,
          charPositions: [],
          chars: [],
          spaceWidth: 0,
          spacesIndex: []
        };
        firstWord = true;
        layoutData.lines.push(currentLine);
        layoutData.height += adjustedLineHeight;
      };
      const checkIsOverflow = (lineWidth) => lineWidth - adjustedLetterSpacing > adjustedWordWrapWidth;
      for (let i = 0; i < chars.length + 1; i++) {
        let char;
        const isEnd = i === chars.length;
        if (!isEnd) {
          char = chars[i];
        }
        const charData = font.chars[char] || font.chars[" "];
        const isSpace = /(?:\s)/.test(char);
        const isWordBreak = isSpace || char === "\r" || char === "\n" || isEnd;
        if (isWordBreak) {
          const addWordToNextLine = !firstWord && style.wordWrap && checkIsOverflow(currentLine.width + currentWord.width);
          if (addWordToNextLine) {
            nextLine();
            nextWord(currentWord);
            if (!isEnd) {
              currentLine.charPositions.push(0);
            }
          } else {
            currentWord.start = currentLine.width;
            nextWord(currentWord);
            if (!isEnd) {
              currentLine.charPositions.push(0);
            }
          }
          if (char === "\r" || char === "\n") {
            nextLine();
          } else if (!isEnd) {
            const spaceWidth = charData.xAdvance + (charData.kerning[previousChar] || 0) + adjustedLetterSpacing;
            currentLine.width += spaceWidth;
            currentLine.spaceWidth = spaceWidth;
            currentLine.spacesIndex.push(currentLine.charPositions.length);
            currentLine.chars.push(char);
          }
        } else {
          const kerning = charData.kerning[previousChar] || 0;
          const nextCharWidth = charData.xAdvance + kerning + adjustedLetterSpacing;
          const addWordToNextLine = breakWords && checkIsOverflow(currentLine.width + currentWord.width + nextCharWidth);
          if (addWordToNextLine) {
            nextWord(currentWord);
            nextLine();
          }
          currentWord.positions[currentWord.index++] = currentWord.width + kerning;
          currentWord.chars.push(char);
          currentWord.width += nextCharWidth;
        }
        previousChar = char;
      }
      nextLine();
      if (style.align === "center") {
        alignCenter(layoutData);
      } else if (style.align === "right") {
        alignRight(layoutData);
      } else if (style.align === "justify") {
        alignJustify(layoutData);
      }
      return layoutData;
    }
    function alignCenter(measurementData) {
      for (let i = 0; i < measurementData.lines.length; i++) {
        const line = measurementData.lines[i];
        const offset = measurementData.width / 2 - line.width / 2;
        for (let j = 0; j < line.charPositions.length; j++) {
          line.charPositions[j] += offset;
        }
      }
    }
    function alignRight(measurementData) {
      for (let i = 0; i < measurementData.lines.length; i++) {
        const line = measurementData.lines[i];
        const offset = measurementData.width - line.width;
        for (let j = 0; j < line.charPositions.length; j++) {
          line.charPositions[j] += offset;
        }
      }
    }
    function alignJustify(measurementData) {
      const width = measurementData.width;
      for (let i = 0; i < measurementData.lines.length; i++) {
        const line = measurementData.lines[i];
        let indy = 0;
        let spaceIndex = line.spacesIndex[indy++];
        let offset = 0;
        const totalSpaces = line.spacesIndex.length;
        const newSpaceWidth = (width - line.width) / totalSpaces;
        const spaceWidth = newSpaceWidth;
        for (let j = 0; j < line.charPositions.length; j++) {
          if (j === spaceIndex) {
            spaceIndex = line.spacesIndex[indy++];
            offset += spaceWidth;
          }
          line.charPositions[j] += offset;
        }
      }
    }

    "use strict";
    function resolveCharacters(chars) {
      if (chars === "") {
        return [];
      }
      if (typeof chars === "string") {
        chars = [chars];
      }
      const result = [];
      for (let i = 0, j = chars.length; i < j; i++) {
        const item = chars[i];
        if (Array.isArray(item)) {
          if (item.length !== 2) {
            throw new Error(`[BitmapFont]: Invalid character range length, expecting 2 got ${item.length}.`);
          }
          if (item[0].length === 0 || item[1].length === 0) {
            throw new Error("[BitmapFont]: Invalid character delimiter.");
          }
          const startCode = item[0].charCodeAt(0);
          const endCode = item[1].charCodeAt(0);
          if (endCode < startCode) {
            throw new Error("[BitmapFont]: Invalid character range.");
          }
          for (let i2 = startCode, j2 = endCode; i2 <= j2; i2++) {
            result.push(String.fromCharCode(i2));
          }
        } else {
          result.push(...Array.from(item));
        }
      }
      if (result.length === 0) {
        throw new Error("[BitmapFont]: Empty set when resolving characters.");
      }
      return result;
    }

    "use strict";
    var __defProp$S = Object.defineProperty;
    var __getOwnPropSymbols$U = Object.getOwnPropertySymbols;
    var __hasOwnProp$U = Object.prototype.hasOwnProperty;
    var __propIsEnum$U = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$S = (obj, key, value) => key in obj ? __defProp$S(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$S = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$U.call(b, prop))
          __defNormalProp$S(a, prop, b[prop]);
      if (__getOwnPropSymbols$U)
        for (var prop of __getOwnPropSymbols$U(b)) {
          if (__propIsEnum$U.call(b, prop))
            __defNormalProp$S(a, prop, b[prop]);
        }
      return a;
    };
    let fontCount = 0;
    class BitmapFontManagerClass {
      constructor() {
        /**
         * This character set includes all the letters in the alphabet (both lower- and upper- case).
         * @type {string[][]}
         * @example
         * BitmapFont.from('ExampleFont', style, { chars: BitmapFont.ALPHA })
         */
        this.ALPHA = [["a", "z"], ["A", "Z"], " "];
        /**
         * This character set includes all decimal digits (from 0 to 9).
         * @type {string[][]}
         * @example
         * BitmapFont.from('ExampleFont', style, { chars: BitmapFont.NUMERIC })
         */
        this.NUMERIC = [["0", "9"]];
        /**
         * This character set is the union of `BitmapFont.ALPHA` and `BitmapFont.NUMERIC`.
         * @type {string[][]}
         */
        this.ALPHANUMERIC = [["a", "z"], ["A", "Z"], ["0", "9"], " "];
        /**
         * This character set consists of all the ASCII table.
         * @type {string[][]}
         * @see http://www.asciitable.com/
         */
        this.ASCII = [[" ", "~"]];
        /** Default options for installing a new BitmapFont. */
        this.defaultOptions = {
          chars: this.ALPHANUMERIC,
          resolution: 1,
          padding: 4,
          skipKerning: false,
          textureStyle: null
        };
        /** Cache for measured text layouts to avoid recalculating them multiple times. */
        this.measureCache = lru(1e3);
      }
      /**
       * Get a font for the specified text and style.
       * @param text - The text to get the font for
       * @param style - The style to use
       */
      getFont(text, style) {
        var _a;
        let fontFamilyKey = `${style.fontFamily}-bitmap`;
        let overrideFill = true;
        if (style._fill.fill && !style._stroke) {
          fontFamilyKey += style._fill.fill.styleKey;
          overrideFill = false;
        } else if (style._stroke || style.dropShadow) {
          fontFamilyKey = `${style.styleKey}-bitmap`;
          overrideFill = false;
        }
        if (!Cache.has(fontFamilyKey)) {
          const styleCopy = Object.create(style);
          styleCopy.lineHeight = 0;
          const fnt = new DynamicBitmapFont(__spreadValues$S({
            style: styleCopy,
            overrideFill,
            overrideSize: true
          }, this.defaultOptions));
          fontCount++;
          if (fontCount > 50) {
            warn("BitmapText", `You have dynamically created ${fontCount} bitmap fonts, this can be inefficient. Try pre installing your font styles using \`BitmapFont.install({name:"style1", style})\``);
          }
          fnt.once("destroy", () => {
            fontCount--;
            Cache.remove(fontFamilyKey);
          });
          Cache.set(
            fontFamilyKey,
            fnt
          );
        }
        const dynamicFont = Cache.get(fontFamilyKey);
        (_a = dynamicFont.ensureCharacters) == null ? void 0 : _a.call(dynamicFont, text);
        return dynamicFont;
      }
      /**
       * Get the layout of a text for the specified style.
       * @param text - The text to get the layout for
       * @param style - The style to use
       * @param trimEnd - Whether to ignore whitespaces at the end of each line
       */
      getLayout(text, style, trimEnd = true) {
        const bitmapFont = this.getFont(text, style);
        const id = `${text}-${style.styleKey}-${trimEnd}`;
        if (this.measureCache.has(id)) {
          return this.measureCache.get(id);
        }
        const segments = CanvasTextMetrics.graphemeSegmenter(text);
        const layoutData = getBitmapTextLayout(segments, style, bitmapFont, trimEnd);
        this.measureCache.set(id, layoutData);
        return layoutData;
      }
      /**
       * Measure the text using the specified style.
       * @param text - The text to measure
       * @param style - The style to use
       * @param trimEnd - Whether to ignore whitespaces at the end of each line
       */
      measureText(text, style, trimEnd = true) {
        return this.getLayout(text, style, trimEnd);
      }
      // eslint-disable-next-line max-len
      install(...args) {
        var _a, _b, _c, _d, _e;
        let options = args[0];
        if (typeof options === "string") {
          options = {
            name: options,
            style: args[1],
            chars: (_a = args[2]) == null ? void 0 : _a.chars,
            resolution: (_b = args[2]) == null ? void 0 : _b.resolution,
            padding: (_c = args[2]) == null ? void 0 : _c.padding,
            skipKerning: (_d = args[2]) == null ? void 0 : _d.skipKerning
          };
          deprecation(v8_0_0, "BitmapFontManager.install(name, style, options) is deprecated, use BitmapFontManager.install({name, style, ...options})");
        }
        const name = options == null ? void 0 : options.name;
        if (!name) {
          throw new Error("[BitmapFontManager] Property `name` is required.");
        }
        options = __spreadValues$S(__spreadValues$S({}, this.defaultOptions), options);
        const textStyle = options.style;
        const style = textStyle instanceof TextStyle ? textStyle : new TextStyle(textStyle);
        const overrideFill = (_e = options.dynamicFill) != null ? _e : this._canUseTintForStyle(style);
        const font = new DynamicBitmapFont({
          style,
          overrideFill,
          skipKerning: options.skipKerning,
          padding: options.padding,
          resolution: options.resolution,
          overrideSize: false,
          textureStyle: options.textureStyle
        });
        const flatChars = resolveCharacters(options.chars);
        font.ensureCharacters(flatChars.join(""));
        Cache.set(`${name}-bitmap`, font);
        font.once("destroy", () => Cache.remove(`${name}-bitmap`));
        return font;
      }
      /**
       * Uninstalls a bitmap font from the cache.
       * @param {string} name - The name of the bitmap font to uninstall.
       */
      uninstall(name) {
        const cacheKey = `${name}-bitmap`;
        const font = Cache.get(cacheKey);
        if (font) {
          font.destroy();
        }
      }
      /**
       * Determines if a style can use tinting instead of baking colors into the bitmap.
       * Tinting is more efficient as it allows reusing the same bitmap with different colors.
       * @param style - The text style to evaluate
       * @returns true if the style can use tinting, false if colors must be baked in
       * @private
       */
      _canUseTintForStyle(style) {
        return !style._stroke && (!style.dropShadow || style.dropShadow.color === 0) && !style._fill.fill && style._fill.color === 16777215;
      }
    }
    const BitmapFontManager = new BitmapFontManagerClass();

    "use strict";
    class BitmapTextGraphics extends Graphics {
      destroy() {
        if (this.context.customShader) {
          this.context.customShader.destroy();
        }
        super.destroy();
      }
    }
    class BitmapTextPipe {
      constructor(renderer) {
        this._renderer = renderer;
        this._managedBitmapTexts = new GCManagedHash({ renderer, type: "renderable", priority: -2, name: "bitmapText" });
      }
      validateRenderable(bitmapText) {
        const graphicsRenderable = this._getGpuBitmapText(bitmapText);
        return this._renderer.renderPipes.graphics.validateRenderable(graphicsRenderable);
      }
      addRenderable(bitmapText, instructionSet) {
        const graphicsRenderable = this._getGpuBitmapText(bitmapText);
        syncWithProxy(bitmapText, graphicsRenderable);
        if (bitmapText._didTextUpdate) {
          bitmapText._didTextUpdate = false;
          this._updateContext(bitmapText, graphicsRenderable);
        }
        this._renderer.renderPipes.graphics.addRenderable(graphicsRenderable, instructionSet);
        if (graphicsRenderable.context.customShader) {
          this._updateDistanceField(bitmapText);
        }
      }
      updateRenderable(bitmapText) {
        const graphicsRenderable = this._getGpuBitmapText(bitmapText);
        syncWithProxy(bitmapText, graphicsRenderable);
        this._renderer.renderPipes.graphics.updateRenderable(graphicsRenderable);
        if (graphicsRenderable.context.customShader) {
          this._updateDistanceField(bitmapText);
        }
      }
      _updateContext(bitmapText, proxyGraphics) {
        const { context } = proxyGraphics;
        const bitmapFont = BitmapFontManager.getFont(bitmapText.text, bitmapText._style);
        context.clear();
        if (bitmapFont.distanceField.type !== "none") {
          if (!context.customShader) {
            context.customShader = new SdfShader(this._renderer.limits.maxBatchableTextures);
          }
        }
        const chars = CanvasTextMetrics.graphemeSegmenter(bitmapText.text);
        const style = bitmapText._style;
        let currentY = bitmapFont.baseLineOffset;
        const bitmapTextLayout = getBitmapTextLayout(chars, style, bitmapFont, true);
        const padding = style.padding;
        const scale = bitmapTextLayout.scale;
        let tx = bitmapTextLayout.width;
        let ty = bitmapTextLayout.height + bitmapTextLayout.offsetY;
        if (style._stroke) {
          tx += style._stroke.width / scale;
          ty += style._stroke.width / scale;
        }
        context.translate(-bitmapText._anchor._x * tx - padding, -bitmapText._anchor._y * ty - padding).scale(scale, scale);
        const tint = bitmapFont.applyFillAsTint ? style._fill.color : 16777215;
        let fontSize = bitmapFont.fontMetrics.fontSize;
        let lineHeight = bitmapFont.lineHeight;
        if (style.lineHeight) {
          fontSize = style.fontSize / scale;
          lineHeight = style.lineHeight / scale;
        }
        let linePositionYShift = (lineHeight - fontSize) / 2;
        if (linePositionYShift - bitmapFont.baseLineOffset < 0) {
          linePositionYShift = 0;
        }
        for (let i = 0; i < bitmapTextLayout.lines.length; i++) {
          const line = bitmapTextLayout.lines[i];
          for (let j = 0; j < line.charPositions.length; j++) {
            const char = line.chars[j];
            const charData = bitmapFont.chars[char];
            if (charData == null ? void 0 : charData.texture) {
              const texture = charData.texture;
              context.texture(
                texture,
                tint ? tint : "black",
                Math.round(line.charPositions[j] + charData.xOffset),
                Math.round(currentY + charData.yOffset + linePositionYShift),
                texture.orig.width,
                texture.orig.height
              );
            }
          }
          currentY += lineHeight;
        }
      }
      _getGpuBitmapText(bitmapText) {
        return bitmapText._gpuData[this._renderer.uid] || this.initGpuText(bitmapText);
      }
      initGpuText(bitmapText) {
        const proxyRenderable = new BitmapTextGraphics();
        bitmapText._gpuData[this._renderer.uid] = proxyRenderable;
        this._updateContext(bitmapText, proxyRenderable);
        this._managedBitmapTexts.add(bitmapText);
        return proxyRenderable;
      }
      _updateDistanceField(bitmapText) {
        const context = this._getGpuBitmapText(bitmapText).context;
        const fontFamily = bitmapText._style.fontFamily;
        const dynamicFont = Cache.get(`${fontFamily}-bitmap`);
        const { a, b, c, d } = bitmapText.groupTransform;
        const dx = Math.sqrt(a * a + b * b);
        const dy = Math.sqrt(c * c + d * d);
        const worldScale = (Math.abs(dx) + Math.abs(dy)) / 2;
        const fontScale = dynamicFont.baseRenderedFontSize / bitmapText._style.fontSize;
        const distance = worldScale * dynamicFont.distanceField.range * (1 / fontScale);
        context.customShader.resources.localUniforms.uniforms.uDistance = distance;
      }
      destroy() {
        this._managedBitmapTexts.destroy();
        this._renderer = null;
        this._managedBitmapTexts = null;
      }
    }
    /** @ignore */
    BitmapTextPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "bitmapText"
    };
    function syncWithProxy(container, proxy) {
      proxy.groupTransform = container.groupTransform;
      proxy.groupColorAlpha = container.groupColorAlpha;
      proxy.groupColor = container.groupColor;
      proxy.groupBlendMode = container.groupBlendMode;
      proxy.globalDisplayStatus = container.globalDisplayStatus;
      proxy.groupTransform = container.groupTransform;
      proxy.localDisplayStatus = container.localDisplayStatus;
      proxy.groupAlpha = container.groupAlpha;
      proxy._roundPixels = container._roundPixels;
    }

    "use strict";
    extensions.add(BitmapTextPipe);

    "use strict";
    class BatchableHTMLText extends BatchableSprite {
      constructor() {
        super(...arguments);
        this.generatingTexture = false;
        this.currentKey = "--";
      }
      /** Destroys the BatchableHTMLText instance. Returns the texture promise to the renderer and cleans up references. */
      destroy() {
        this.texturePromise = null;
        this.generatingTexture = false;
        this.currentKey = "--";
        super.destroy();
      }
    }

    "use strict";
    class HTMLTextPipe {
      constructor(renderer) {
        this._renderer = renderer;
        renderer.runners.resolutionChange.add(this);
        this._managedTexts = new GCManagedHash({
          renderer,
          type: "renderable",
          onUnload: this.onTextUnload.bind(this),
          name: "htmlText"
        });
      }
      resolutionChange() {
        for (const key in this._managedTexts.items) {
          const text = this._managedTexts.items[key];
          if (text == null ? void 0 : text._autoResolution) {
            text.onViewUpdate();
          }
        }
      }
      validateRenderable(htmlText) {
        const gpuText = this._getGpuText(htmlText);
        const newKey = htmlText.styleKey;
        if (gpuText.currentKey !== newKey) {
          return true;
        }
        return false;
      }
      addRenderable(htmlText, instructionSet) {
        const batchableHTMLText = this._getGpuText(htmlText);
        if (htmlText._didTextUpdate) {
          const resolution = htmlText._autoResolution ? this._renderer.resolution : htmlText.resolution;
          if (batchableHTMLText.currentKey !== htmlText.styleKey || htmlText.resolution !== resolution) {
            this._updateGpuText(htmlText).catch((e) => {
              console.error(e);
            });
          }
          htmlText._didTextUpdate = false;
          updateTextBounds(batchableHTMLText, htmlText);
        }
        this._renderer.renderPipes.batch.addToBatch(batchableHTMLText, instructionSet);
      }
      updateRenderable(htmlText) {
        const batchableHTMLText = this._getGpuText(htmlText);
        batchableHTMLText._batcher.updateElement(batchableHTMLText);
      }
      async _updateGpuText(htmlText) {
        htmlText._didTextUpdate = false;
        const batchableHTMLText = this._getGpuText(htmlText);
        if (batchableHTMLText.generatingTexture)
          return;
        const oldTexturePromise = batchableHTMLText.texturePromise;
        batchableHTMLText.texturePromise = null;
        batchableHTMLText.generatingTexture = true;
        htmlText._resolution = htmlText._autoResolution ? this._renderer.resolution : htmlText.resolution;
        let texturePromise = this._renderer.htmlText.getTexturePromise(htmlText);
        if (oldTexturePromise) {
          texturePromise = texturePromise.finally(() => {
            this._renderer.htmlText.decreaseReferenceCount(batchableHTMLText.currentKey);
            this._renderer.htmlText.returnTexturePromise(oldTexturePromise);
          });
        }
        batchableHTMLText.texturePromise = texturePromise;
        batchableHTMLText.currentKey = htmlText.styleKey;
        batchableHTMLText.texture = await texturePromise;
        const renderGroup = htmlText.renderGroup || htmlText.parentRenderGroup;
        if (renderGroup) {
          renderGroup.structureDidChange = true;
        }
        batchableHTMLText.generatingTexture = false;
        updateTextBounds(batchableHTMLText, htmlText);
      }
      _getGpuText(htmlText) {
        return htmlText._gpuData[this._renderer.uid] || this.initGpuText(htmlText);
      }
      initGpuText(htmlText) {
        const batchableHTMLText = new BatchableHTMLText();
        batchableHTMLText.renderable = htmlText;
        batchableHTMLText.transform = htmlText.groupTransform;
        batchableHTMLText.texture = Texture.EMPTY;
        batchableHTMLText.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
        batchableHTMLText.roundPixels = this._renderer._roundPixels | htmlText._roundPixels;
        htmlText._resolution = htmlText._autoResolution ? this._renderer.resolution : htmlText.resolution;
        htmlText._gpuData[this._renderer.uid] = batchableHTMLText;
        this._managedTexts.add(htmlText);
        return batchableHTMLText;
      }
      onTextUnload(text) {
        const gpuData = text._gpuData[this._renderer.uid];
        if (!gpuData)
          return;
        const { htmlText } = this._renderer;
        htmlText.getReferenceCount(gpuData.currentKey) === null ? htmlText.returnTexturePromise(gpuData.texturePromise) : htmlText.decreaseReferenceCount(gpuData.currentKey);
      }
      destroy() {
        this._managedTexts.destroy();
        this._renderer = null;
      }
    }
    /** @ignore */
    HTMLTextPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "htmlText"
    };

    "use strict";
    function isSafari() {
      const { userAgent } = DOMAdapter.get().getNavigator();
      return /^((?!chrome|android).)*safari/i.test(userAgent);
    }

    "use strict";
    const nssvg = "http://www.w3.org/2000/svg";
    const nsxhtml = "http://www.w3.org/1999/xhtml";
    class HTMLTextRenderData {
      constructor() {
        this.svgRoot = document.createElementNS(nssvg, "svg");
        this.foreignObject = document.createElementNS(nssvg, "foreignObject");
        this.domElement = document.createElementNS(nsxhtml, "div");
        this.styleElement = document.createElementNS(nsxhtml, "style");
        const { foreignObject, svgRoot, styleElement, domElement } = this;
        foreignObject.setAttribute("width", "10000");
        foreignObject.setAttribute("height", "10000");
        foreignObject.style.overflow = "hidden";
        svgRoot.appendChild(foreignObject);
        foreignObject.appendChild(styleElement);
        foreignObject.appendChild(domElement);
        this.image = DOMAdapter.get().createImage();
      }
      destroy() {
        this.svgRoot.remove();
        this.foreignObject.remove();
        this.styleElement.remove();
        this.domElement.remove();
        this.image.src = "";
        this.image.remove();
        this.svgRoot = null;
        this.foreignObject = null;
        this.styleElement = null;
        this.domElement = null;
        this.image = null;
        this.canvasAndContext = null;
      }
    }

    "use strict";
    function extractFontFamilies(text, style) {
      const fontFamily = style.fontFamily;
      const fontFamilies = [];
      const dedupe = {};
      const regex = /font-family:([^;"\s]+)/g;
      const matches = text.match(regex);
      function addFontFamily(fontFamily2) {
        if (!dedupe[fontFamily2]) {
          fontFamilies.push(fontFamily2);
          dedupe[fontFamily2] = true;
        }
      }
      if (Array.isArray(fontFamily)) {
        for (let i = 0; i < fontFamily.length; i++) {
          addFontFamily(fontFamily[i]);
        }
      } else {
        addFontFamily(fontFamily);
      }
      if (matches) {
        matches.forEach((match) => {
          const fontFamily2 = match.split(":")[1].trim();
          addFontFamily(fontFamily2);
        });
      }
      for (const i in style.tagStyles) {
        const fontFamily2 = style.tagStyles[i].fontFamily;
        addFontFamily(fontFamily2);
      }
      return fontFamilies;
    }

    "use strict";
    async function loadFontAsBase64(url) {
      const response = await DOMAdapter.get().fetch(url);
      const blob = await response.blob();
      const reader = new FileReader();
      const dataSrc = await new Promise((resolve, reject) => {
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
      });
      return dataSrc;
    }

    "use strict";
    async function loadFontCSS(style, url) {
      const dataSrc = await loadFontAsBase64(url);
      return `@font-face {
        font-family: "${style.fontFamily}";
        font-weight: ${style.fontWeight};
        font-style: ${style.fontStyle};
        src: url('${dataSrc}');
    }`;
    }

    "use strict";
    const FontStylePromiseCache = /* @__PURE__ */ new Map();
    async function getFontCss(fontFamilies) {
      const fontPromises = fontFamilies.filter((fontFamily) => Cache.has(`${fontFamily}-and-url`)).map((fontFamily) => {
        if (!FontStylePromiseCache.has(fontFamily)) {
          const { entries } = Cache.get(`${fontFamily}-and-url`);
          const promises = [];
          entries.forEach((entry) => {
            const url = entry.url;
            const faces = entry.faces;
            const out = faces.map((face) => ({ weight: face.weight, style: face.style }));
            promises.push(
              ...out.map(
                (style) => loadFontCSS(
                  {
                    fontWeight: style.weight,
                    fontStyle: style.style,
                    fontFamily
                  },
                  url
                )
              )
            );
          });
          FontStylePromiseCache.set(
            fontFamily,
            Promise.all(promises).then((css) => css.join("\n"))
          );
        }
        return FontStylePromiseCache.get(fontFamily);
      });
      return (await Promise.all(fontPromises)).join("\n");
    }

    "use strict";
    function getSVGUrl(text, style, resolution, fontCSS, htmlTextData) {
      const { domElement, styleElement, svgRoot } = htmlTextData;
      domElement.innerHTML = `<style>${style.cssStyle}</style><div style='padding:0;'>${text}</div>`;
      domElement.setAttribute("style", `transform: scale(${resolution});transform-origin: top left; display: inline-block`);
      styleElement.textContent = fontCSS;
      const { width, height } = htmlTextData.image;
      svgRoot.setAttribute("width", width.toString());
      svgRoot.setAttribute("height", height.toString());
      return new XMLSerializer().serializeToString(svgRoot);
    }

    "use strict";
    function getTemporaryCanvasFromImage(image, resolution) {
      const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(
        image.width,
        image.height,
        resolution
      );
      const { context } = canvasAndContext;
      context.clearRect(0, 0, image.width, image.height);
      context.drawImage(image, 0, 0);
      return canvasAndContext;
    }

    "use strict";
    function loadSVGImage(image, url, delay) {
      return new Promise(async (resolve) => {
        if (delay) {
          await new Promise((resolve2) => setTimeout(resolve2, 100));
        }
        image.onload = () => {
          resolve();
        };
        image.src = `data:image/svg+xml;charset=utf8,${encodeURIComponent(url)}`;
        image.crossOrigin = "anonymous";
      });
    }

    "use strict";
    let tempHTMLTextRenderData;
    function measureHtmlText(text, style, fontStyleCSS, htmlTextRenderData) {
      htmlTextRenderData || (htmlTextRenderData = tempHTMLTextRenderData || (tempHTMLTextRenderData = new HTMLTextRenderData()));
      const { domElement, styleElement, svgRoot } = htmlTextRenderData;
      domElement.innerHTML = `<style>${style.cssStyle};</style><div style='padding:0'>${text}</div>`;
      domElement.setAttribute("style", "transform-origin: top left; display: inline-block");
      if (fontStyleCSS) {
        styleElement.textContent = fontStyleCSS;
      }
      document.body.appendChild(svgRoot);
      const contentBounds = domElement.getBoundingClientRect();
      svgRoot.remove();
      const doublePadding = style.padding * 2;
      return {
        width: contentBounds.width - doublePadding,
        height: contentBounds.height - doublePadding
      };
    }

    "use strict";
    class HTMLTextSystem {
      constructor(renderer) {
        this._activeTextures = {};
        this._renderer = renderer;
        this._createCanvas = renderer.type === RendererType.WEBGPU;
      }
      /**
       * @param options
       * @deprecated Use getTexturePromise instead
       */
      getTexture(options) {
        return this.getTexturePromise(options);
      }
      /**
       * Increases the reference count for a texture.
       * @param text - The HTMLText instance associated with the texture.
       */
      getManagedTexture(text) {
        const textKey = text.styleKey;
        if (this._activeTextures[textKey]) {
          this._increaseReferenceCount(textKey);
          return this._activeTextures[textKey].promise;
        }
        const promise = this._buildTexturePromise(text).then((texture) => {
          this._activeTextures[textKey].texture = texture;
          return texture;
        });
        this._activeTextures[textKey] = {
          texture: null,
          promise,
          usageCount: 1
        };
        return promise;
      }
      /**
       * Gets the current reference count for a texture associated with a text key.
       * @param textKey - The unique key identifying the text style configuration
       * @returns The number of Text instances currently using this texture
       */
      getReferenceCount(textKey) {
        var _a, _b;
        return (_b = (_a = this._activeTextures[textKey]) == null ? void 0 : _a.usageCount) != null ? _b : null;
      }
      _increaseReferenceCount(textKey) {
        this._activeTextures[textKey].usageCount++;
      }
      /**
       * Decreases the reference count for a texture.
       * If the count reaches zero, the texture is cleaned up.
       * @param textKey - The key associated with the HTMLText instance.
       */
      decreaseReferenceCount(textKey) {
        const activeTexture = this._activeTextures[textKey];
        if (!activeTexture)
          return;
        activeTexture.usageCount--;
        if (activeTexture.usageCount === 0) {
          if (activeTexture.texture) {
            this._cleanUp(activeTexture.texture);
          } else {
            activeTexture.promise.then((texture) => {
              activeTexture.texture = texture;
              this._cleanUp(activeTexture.texture);
            }).catch(() => {
              warn("HTMLTextSystem: Failed to clean texture");
            });
          }
          this._activeTextures[textKey] = null;
        }
      }
      /**
       * Returns a promise that resolves to a texture for the given HTMLText options.
       * @param options - The options for the HTMLText.
       * @returns A promise that resolves to a Texture.
       */
      getTexturePromise(options) {
        return this._buildTexturePromise(options);
      }
      async _buildTexturePromise(options) {
        const { text, style, resolution, textureStyle } = options;
        const htmlTextData = BigPool.get(HTMLTextRenderData);
        const fontFamilies = extractFontFamilies(text, style);
        const fontCSS = await getFontCss(fontFamilies);
        const measured = measureHtmlText(text, style, fontCSS, htmlTextData);
        const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
        const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
        const image = htmlTextData.image;
        const uvSafeOffset = 2;
        image.width = (width | 0) + uvSafeOffset;
        image.height = (height | 0) + uvSafeOffset;
        const svgURL = getSVGUrl(text, style, resolution, fontCSS, htmlTextData);
        await loadSVGImage(image, svgURL, isSafari() && fontFamilies.length > 0);
        const resource = image;
        let canvasAndContext;
        if (this._createCanvas) {
          canvasAndContext = getTemporaryCanvasFromImage(image, resolution);
        }
        const texture = getPo2TextureFromSource(
          canvasAndContext ? canvasAndContext.canvas : resource,
          image.width - uvSafeOffset,
          image.height - uvSafeOffset,
          resolution
        );
        if (textureStyle)
          texture.source.style = textureStyle;
        if (this._createCanvas) {
          this._renderer.texture.initSource(texture.source);
          CanvasPool.returnCanvasAndContext(canvasAndContext);
        }
        BigPool.return(htmlTextData);
        return texture;
      }
      returnTexturePromise(texturePromise) {
        texturePromise.then((texture) => {
          this._cleanUp(texture);
        }).catch(() => {
          warn("HTMLTextSystem: Failed to clean texture");
        });
      }
      _cleanUp(texture) {
        TexturePool.returnTexture(texture, true);
        texture.source.resource = null;
        texture.source.uploadMethodId = "unknown";
      }
      destroy() {
        this._renderer = null;
        for (const key in this._activeTextures) {
          if (this._activeTextures[key])
            this.returnTexturePromise(this._activeTextures[key].promise);
        }
        this._activeTextures = null;
      }
    }
    /** @ignore */
    HTMLTextSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "htmlText"
    };

    "use strict";
    extensions.add(HTMLTextSystem);
    extensions.add(HTMLTextPipe);

    "use strict";
    var __defProp$R = Object.defineProperty;
    var __getOwnPropSymbols$T = Object.getOwnPropertySymbols;
    var __hasOwnProp$T = Object.prototype.hasOwnProperty;
    var __propIsEnum$T = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$R = (obj, key, value) => key in obj ? __defProp$R(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$R = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$T.call(b, prop))
          __defNormalProp$R(a, prop, b[prop]);
      if (__getOwnPropSymbols$T)
        for (var prop of __getOwnPropSymbols$T(b)) {
          if (__propIsEnum$T.call(b, prop))
            __defNormalProp$R(a, prop, b[prop]);
        }
      return a;
    };
    const _MeshGeometry = class _MeshGeometry extends Geometry {
      constructor(...args) {
        var _a;
        let options = (_a = args[0]) != null ? _a : {};
        if (options instanceof Float32Array) {
          deprecation(v8_0_0, "use new MeshGeometry({ positions, uvs, indices }) instead");
          options = {
            positions: options,
            uvs: args[1],
            indices: args[2]
          };
        }
        options = __spreadValues$R(__spreadValues$R({}, _MeshGeometry.defaultOptions), options);
        const positions = options.positions || new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
        let uvs = options.uvs;
        if (!uvs) {
          if (options.positions) {
            uvs = new Float32Array(positions.length);
          } else {
            uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
          }
        }
        const indices = options.indices || new Uint32Array([0, 1, 2, 0, 2, 3]);
        const shrinkToFit = options.shrinkBuffersToFit;
        const positionBuffer = new Buffer({
          data: positions,
          label: "attribute-mesh-positions",
          shrinkToFit,
          usage: BufferUsage.VERTEX | BufferUsage.COPY_DST
        });
        const uvBuffer = new Buffer({
          data: uvs,
          label: "attribute-mesh-uvs",
          shrinkToFit,
          usage: BufferUsage.VERTEX | BufferUsage.COPY_DST
        });
        const indexBuffer = new Buffer({
          data: indices,
          label: "index-mesh-buffer",
          shrinkToFit,
          usage: BufferUsage.INDEX | BufferUsage.COPY_DST
        });
        super({
          attributes: {
            aPosition: {
              buffer: positionBuffer,
              format: "float32x2",
              stride: 2 * 4,
              offset: 0
            },
            aUV: {
              buffer: uvBuffer,
              format: "float32x2",
              stride: 2 * 4,
              offset: 0
            }
          },
          indexBuffer,
          topology: options.topology
        });
        this.batchMode = "auto";
      }
      /** The positions of the mesh. */
      get positions() {
        return this.attributes.aPosition.buffer.data;
      }
      /**
       * Set the positions of the mesh.
       * When setting the positions, its important that the uvs array is at least as long as the positions array.
       * otherwise the geometry will not be valid.
       * @param {Float32Array} value - The positions of the mesh.
       */
      set positions(value) {
        this.attributes.aPosition.buffer.data = value;
      }
      /** The UVs of the mesh. */
      get uvs() {
        return this.attributes.aUV.buffer.data;
      }
      /**
       * Set the UVs of the mesh.
       * Its important that the uvs array you set is at least as long as the positions array.
       * otherwise the geometry will not be valid.
       * @param {Float32Array} value - The UVs of the mesh.
       */
      set uvs(value) {
        this.attributes.aUV.buffer.data = value;
      }
      /** The indices of the mesh. */
      get indices() {
        return this.indexBuffer.data;
      }
      set indices(value) {
        this.indexBuffer.data = value;
      }
    };
    _MeshGeometry.defaultOptions = {
      topology: "triangle-list",
      shrinkBuffersToFit: false
    };
    let MeshGeometry = _MeshGeometry;

    "use strict";
    var __defProp$Q = Object.defineProperty;
    var __defProps$n = Object.defineProperties;
    var __getOwnPropDescs$n = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$S = Object.getOwnPropertySymbols;
    var __hasOwnProp$S = Object.prototype.hasOwnProperty;
    var __propIsEnum$S = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$Q = (obj, key, value) => key in obj ? __defProp$Q(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$Q = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$S.call(b, prop))
          __defNormalProp$Q(a, prop, b[prop]);
      if (__getOwnPropSymbols$S)
        for (var prop of __getOwnPropSymbols$S(b)) {
          if (__propIsEnum$S.call(b, prop))
            __defNormalProp$Q(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$n = (a, b) => __defProps$n(a, __getOwnPropDescs$n(b));
    const localUniformBit = {
      name: "local-uniform-bit",
      vertex: {
        header: (
          /* wgsl */
          `

            struct LocalUniforms {
                uTransformMatrix:mat3x3<f32>,
                uColor:vec4<f32>,
                uRound:f32,
            }

            @group(1) @binding(0) var<uniform> localUniforms : LocalUniforms;
        `
        ),
        main: (
          /* wgsl */
          `
            vColor *= localUniforms.uColor;
            modelMatrix *= localUniforms.uTransformMatrix;
        `
        ),
        end: (
          /* wgsl */
          `
            if(localUniforms.uRound == 1)
            {
                vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
            }
        `
        )
      }
    };
    const localUniformBitGroup2 = __spreadProps$n(__spreadValues$Q({}, localUniformBit), {
      vertex: __spreadProps$n(__spreadValues$Q({}, localUniformBit.vertex), {
        // replace the group!
        header: localUniformBit.vertex.header.replace("group(1)", "group(2)")
      })
    });
    const localUniformBitGl = {
      name: "local-uniform-bit",
      vertex: {
        header: (
          /* glsl */
          `

            uniform mat3 uTransformMatrix;
            uniform vec4 uColor;
            uniform float uRound;
        `
        ),
        main: (
          /* glsl */
          `
            vColor *= uColor;
            modelMatrix = uTransformMatrix;
        `
        ),
        end: (
          /* glsl */
          `
            if(uRound == 1.)
            {
                gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
            }
        `
        )
      }
    };

    "use strict";
    const tilingBit = {
      name: "tiling-bit",
      vertex: {
        header: (
          /* wgsl */
          `
            struct TilingUniforms {
                uMapCoord:mat3x3<f32>,
                uClampFrame:vec4<f32>,
                uClampOffset:vec2<f32>,
                uTextureTransform:mat3x3<f32>,
                uSizeAnchor:vec4<f32>
            };

            @group(2) @binding(0) var<uniform> tilingUniforms: TilingUniforms;
            @group(2) @binding(1) var uTexture: texture_2d<f32>;
            @group(2) @binding(2) var uSampler: sampler;
        `
        ),
        main: (
          /* wgsl */
          `
            uv = (tilingUniforms.uTextureTransform * vec3(uv, 1.0)).xy;

            position = (position - tilingUniforms.uSizeAnchor.zw) * tilingUniforms.uSizeAnchor.xy;
        `
        )
      },
      fragment: {
        header: (
          /* wgsl */
          `
            struct TilingUniforms {
                uMapCoord:mat3x3<f32>,
                uClampFrame:vec4<f32>,
                uClampOffset:vec2<f32>,
                uTextureTransform:mat3x3<f32>,
                uSizeAnchor:vec4<f32>
            };

            @group(2) @binding(0) var<uniform> tilingUniforms: TilingUniforms;
            @group(2) @binding(1) var uTexture: texture_2d<f32>;
            @group(2) @binding(2) var uSampler: sampler;
        `
        ),
        main: (
          /* wgsl */
          `

            var coord = vUV + ceil(tilingUniforms.uClampOffset - vUV);
            coord = (tilingUniforms.uMapCoord * vec3(coord, 1.0)).xy;
            var unclamped = coord;
            coord = clamp(coord, tilingUniforms.uClampFrame.xy, tilingUniforms.uClampFrame.zw);

            var bias = 0.;

            if(unclamped.x == coord.x && unclamped.y == coord.y)
            {
                bias = -32.;
            }

            outColor = textureSampleBias(uTexture, uSampler, coord, bias);
        `
        )
      }
    };
    const tilingBitGl = {
      name: "tiling-bit",
      vertex: {
        header: (
          /* glsl */
          `
            uniform mat3 uTextureTransform;
            uniform vec4 uSizeAnchor;

        `
        ),
        main: (
          /* glsl */
          `
            uv = (uTextureTransform * vec3(aUV, 1.0)).xy;

            position = (position - uSizeAnchor.zw) * uSizeAnchor.xy;
        `
        )
      },
      fragment: {
        header: (
          /* glsl */
          `
            uniform sampler2D uTexture;
            uniform mat3 uMapCoord;
            uniform vec4 uClampFrame;
            uniform vec2 uClampOffset;
        `
        ),
        main: (
          /* glsl */
          `

        vec2 coord = vUV + ceil(uClampOffset - vUV);
        coord = (uMapCoord * vec3(coord, 1.0)).xy;
        vec2 unclamped = coord;
        coord = clamp(coord, uClampFrame.xy, uClampFrame.zw);

        outColor = texture(uTexture, coord, unclamped == coord ? 0.0 : -32.0);// lod-bias very negative to force lod 0

        `
        )
      }
    };

    "use strict";
    let gpuProgram;
    let glProgram;
    class TilingSpriteShader extends Shader {
      constructor() {
        gpuProgram != null ? gpuProgram : gpuProgram = compileHighShaderGpuProgram({
          name: "tiling-sprite-shader",
          bits: [
            localUniformBit,
            tilingBit,
            roundPixelsBit
          ]
        });
        glProgram != null ? glProgram : glProgram = compileHighShaderGlProgram({
          name: "tiling-sprite-shader",
          bits: [
            localUniformBitGl,
            tilingBitGl,
            roundPixelsBitGl
          ]
        });
        const tilingUniforms = new UniformGroup({
          uMapCoord: { value: new Matrix(), type: "mat3x3<f32>" },
          uClampFrame: { value: new Float32Array([0, 0, 1, 1]), type: "vec4<f32>" },
          uClampOffset: { value: new Float32Array([0, 0]), type: "vec2<f32>" },
          uTextureTransform: { value: new Matrix(), type: "mat3x3<f32>" },
          uSizeAnchor: { value: new Float32Array([100, 100, 0.5, 0.5]), type: "vec4<f32>" }
        });
        super({
          glProgram,
          gpuProgram,
          resources: {
            localUniforms: new UniformGroup({
              uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
              uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
              uRound: { value: 0, type: "f32" }
            }),
            tilingUniforms,
            uTexture: Texture.EMPTY.source,
            uSampler: Texture.EMPTY.source.style
          }
        });
      }
      updateUniforms(width, height, matrix, anchorX, anchorY, texture) {
        const tilingUniforms = this.resources.tilingUniforms;
        const textureWidth = texture.width;
        const textureHeight = texture.height;
        const textureMatrix = texture.textureMatrix;
        const uTextureTransform = tilingUniforms.uniforms.uTextureTransform;
        uTextureTransform.set(
          matrix.a * textureWidth / width,
          matrix.b * textureWidth / height,
          matrix.c * textureHeight / width,
          matrix.d * textureHeight / height,
          matrix.tx / width,
          matrix.ty / height
        );
        uTextureTransform.invert();
        tilingUniforms.uniforms.uMapCoord = textureMatrix.mapCoord;
        tilingUniforms.uniforms.uClampFrame = textureMatrix.uClampFrame;
        tilingUniforms.uniforms.uClampOffset = textureMatrix.uClampOffset;
        tilingUniforms.uniforms.uTextureTransform = uTextureTransform;
        tilingUniforms.uniforms.uSizeAnchor[0] = width;
        tilingUniforms.uniforms.uSizeAnchor[1] = height;
        tilingUniforms.uniforms.uSizeAnchor[2] = anchorX;
        tilingUniforms.uniforms.uSizeAnchor[3] = anchorY;
        if (texture) {
          this.resources.uTexture = texture.source;
          this.resources.uSampler = texture.source.style;
        }
      }
    }

    "use strict";
    class QuadGeometry extends MeshGeometry {
      constructor() {
        super({
          positions: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
          uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
          indices: new Uint32Array([0, 1, 2, 0, 2, 3])
        });
      }
    }

    "use strict";
    function setPositions(tilingSprite, positions) {
      const anchorX = tilingSprite.anchor.x;
      const anchorY = tilingSprite.anchor.y;
      positions[0] = -anchorX * tilingSprite.width;
      positions[1] = -anchorY * tilingSprite.height;
      positions[2] = (1 - anchorX) * tilingSprite.width;
      positions[3] = -anchorY * tilingSprite.height;
      positions[4] = (1 - anchorX) * tilingSprite.width;
      positions[5] = (1 - anchorY) * tilingSprite.height;
      positions[6] = -anchorX * tilingSprite.width;
      positions[7] = (1 - anchorY) * tilingSprite.height;
    }

    "use strict";
    function applyMatrix(array, stride, offset, matrix) {
      let index = 0;
      const size = array.length / (stride || 2);
      const a = matrix.a;
      const b = matrix.b;
      const c = matrix.c;
      const d = matrix.d;
      const tx = matrix.tx;
      const ty = matrix.ty;
      offset *= stride;
      while (index < size) {
        const x = array[offset];
        const y = array[offset + 1];
        array[offset] = a * x + c * y + tx;
        array[offset + 1] = b * x + d * y + ty;
        offset += stride;
        index++;
      }
    }

    "use strict";
    function setUvs(tilingSprite, uvs) {
      const texture = tilingSprite.texture;
      const width = texture.frame.width;
      const height = texture.frame.height;
      let anchorX = 0;
      let anchorY = 0;
      if (tilingSprite.applyAnchorToTexture) {
        anchorX = tilingSprite.anchor.x;
        anchorY = tilingSprite.anchor.y;
      }
      uvs[0] = uvs[6] = -anchorX;
      uvs[2] = uvs[4] = 1 - anchorX;
      uvs[1] = uvs[3] = -anchorY;
      uvs[5] = uvs[7] = 1 - anchorY;
      const textureMatrix = Matrix.shared;
      textureMatrix.copyFrom(tilingSprite._tileTransform.matrix);
      textureMatrix.tx /= tilingSprite.width;
      textureMatrix.ty /= tilingSprite.height;
      textureMatrix.invert();
      textureMatrix.scale(tilingSprite.width / width, tilingSprite.height / height);
      applyMatrix(uvs, 2, 0, textureMatrix);
    }

    "use strict";
    const sharedQuad = new QuadGeometry();
    class TilingSpriteGpuData {
      constructor() {
        this.canBatch = true;
        this.geometry = new MeshGeometry({
          indices: sharedQuad.indices.slice(),
          positions: sharedQuad.positions.slice(),
          uvs: sharedQuad.uvs.slice()
        });
      }
      destroy() {
        var _a;
        this.geometry.destroy();
        (_a = this.shader) == null ? void 0 : _a.destroy();
      }
    }
    class TilingSpritePipe {
      constructor(renderer) {
        this._state = State.default2d;
        this._renderer = renderer;
        this._managedTilingSprites = new GCManagedHash({ renderer, type: "renderable", name: "tilingSprite" });
      }
      validateRenderable(renderable) {
        const tilingSpriteData = this._getTilingSpriteData(renderable);
        const couldBatch = tilingSpriteData.canBatch;
        this._updateCanBatch(renderable);
        const canBatch = tilingSpriteData.canBatch;
        if (canBatch && canBatch === couldBatch) {
          const { batchableMesh } = tilingSpriteData;
          return !batchableMesh._batcher.checkAndUpdateTexture(
            batchableMesh,
            renderable.texture
          );
        }
        return couldBatch !== canBatch;
      }
      addRenderable(tilingSprite, instructionSet) {
        const batcher = this._renderer.renderPipes.batch;
        this._updateCanBatch(tilingSprite);
        const tilingSpriteData = this._getTilingSpriteData(tilingSprite);
        const { geometry, canBatch } = tilingSpriteData;
        if (canBatch) {
          tilingSpriteData.batchableMesh || (tilingSpriteData.batchableMesh = new BatchableMesh());
          const batchableMesh = tilingSpriteData.batchableMesh;
          if (tilingSprite.didViewUpdate) {
            this._updateBatchableMesh(tilingSprite);
            batchableMesh.geometry = geometry;
            batchableMesh.renderable = tilingSprite;
            batchableMesh.transform = tilingSprite.groupTransform;
            batchableMesh.setTexture(tilingSprite._texture);
          }
          batchableMesh.roundPixels = this._renderer._roundPixels | tilingSprite._roundPixels;
          batcher.addToBatch(batchableMesh, instructionSet);
        } else {
          batcher.break(instructionSet);
          tilingSpriteData.shader || (tilingSpriteData.shader = new TilingSpriteShader());
          this.updateRenderable(tilingSprite);
          instructionSet.add(tilingSprite);
        }
      }
      execute(tilingSprite) {
        const { shader } = this._getTilingSpriteData(tilingSprite);
        shader.groups[0] = this._renderer.globalUniforms.bindGroup;
        const localUniforms = shader.resources.localUniforms.uniforms;
        localUniforms.uTransformMatrix = tilingSprite.groupTransform;
        localUniforms.uRound = this._renderer._roundPixels | tilingSprite._roundPixels;
        color32BitToUniform(
          tilingSprite.groupColorAlpha,
          localUniforms.uColor,
          0
        );
        this._state.blendMode = getAdjustedBlendModeBlend(tilingSprite.groupBlendMode, tilingSprite.texture._source);
        this._renderer.encoder.draw({
          geometry: sharedQuad,
          shader,
          state: this._state
        });
      }
      updateRenderable(tilingSprite) {
        const tilingSpriteData = this._getTilingSpriteData(tilingSprite);
        const { canBatch } = tilingSpriteData;
        if (canBatch) {
          const { batchableMesh } = tilingSpriteData;
          if (tilingSprite.didViewUpdate)
            this._updateBatchableMesh(tilingSprite);
          batchableMesh._batcher.updateElement(batchableMesh);
        } else if (tilingSprite.didViewUpdate) {
          const { shader } = tilingSpriteData;
          shader.updateUniforms(
            tilingSprite.width,
            tilingSprite.height,
            tilingSprite._tileTransform.matrix,
            tilingSprite.anchor.x,
            tilingSprite.anchor.y,
            tilingSprite.texture
          );
        }
      }
      _getTilingSpriteData(renderable) {
        return renderable._gpuData[this._renderer.uid] || this._initTilingSpriteData(renderable);
      }
      _initTilingSpriteData(tilingSprite) {
        const gpuData = new TilingSpriteGpuData();
        gpuData.renderable = tilingSprite;
        tilingSprite._gpuData[this._renderer.uid] = gpuData;
        this._managedTilingSprites.add(tilingSprite);
        return gpuData;
      }
      _updateBatchableMesh(tilingSprite) {
        const renderableData = this._getTilingSpriteData(tilingSprite);
        const { geometry } = renderableData;
        const style = tilingSprite.texture.source.style;
        if (style.addressMode !== "repeat") {
          style.addressMode = "repeat";
          style.update();
        }
        setUvs(tilingSprite, geometry.uvs);
        setPositions(tilingSprite, geometry.positions);
      }
      destroy() {
        this._managedTilingSprites.destroy();
        this._renderer = null;
      }
      _updateCanBatch(tilingSprite) {
        const renderableData = this._getTilingSpriteData(tilingSprite);
        const texture = tilingSprite.texture;
        let _nonPowOf2wrapping = true;
        if (this._renderer.type === RendererType.WEBGL) {
          _nonPowOf2wrapping = this._renderer.context.supports.nonPowOf2wrapping;
        }
        renderableData.canBatch = texture.textureMatrix.isSimple && (_nonPowOf2wrapping || texture.source.isPowerOfTwo);
        return renderableData.canBatch;
      }
    }
    /** @ignore */
    TilingSpritePipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "tilingSprite"
    };

    "use strict";
    extensions.add(TilingSpritePipe);

    "use strict";
    var __defProp$P = Object.defineProperty;
    var __getOwnPropSymbols$R = Object.getOwnPropertySymbols;
    var __hasOwnProp$R = Object.prototype.hasOwnProperty;
    var __propIsEnum$R = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$P = (obj, key, value) => key in obj ? __defProp$P(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$P = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$R.call(b, prop))
          __defNormalProp$P(a, prop, b[prop]);
      if (__getOwnPropSymbols$R)
        for (var prop of __getOwnPropSymbols$R(b)) {
          if (__propIsEnum$R.call(b, prop))
            __defNormalProp$P(a, prop, b[prop]);
        }
      return a;
    };
    const _PlaneGeometry = class _PlaneGeometry extends MeshGeometry {
      constructor(...args) {
        var _a;
        super({});
        let options = (_a = args[0]) != null ? _a : {};
        if (typeof options === "number") {
          deprecation(v8_0_0, "PlaneGeometry constructor changed please use { width, height, verticesX, verticesY } instead");
          options = {
            width: options,
            height: args[1],
            verticesX: args[2],
            verticesY: args[3]
          };
        }
        this.build(options);
      }
      /**
       * Refreshes plane coordinates
       * @param options - Options to be applied to plane geometry
       */
      build(options) {
        var _a, _b, _c, _d;
        options = __spreadValues$P(__spreadValues$P({}, _PlaneGeometry.defaultOptions), options);
        this.verticesX = (_a = this.verticesX) != null ? _a : options.verticesX;
        this.verticesY = (_b = this.verticesY) != null ? _b : options.verticesY;
        this.width = (_c = this.width) != null ? _c : options.width;
        this.height = (_d = this.height) != null ? _d : options.height;
        const total = this.verticesX * this.verticesY;
        const verts = [];
        const uvs = [];
        const indices = [];
        const verticesX = this.verticesX - 1;
        const verticesY = this.verticesY - 1;
        const sizeX = this.width / verticesX;
        const sizeY = this.height / verticesY;
        for (let i = 0; i < total; i++) {
          const x = i % this.verticesX;
          const y = i / this.verticesX | 0;
          verts.push(x * sizeX, y * sizeY);
          uvs.push(x / verticesX, y / verticesY);
        }
        const totalSub = verticesX * verticesY;
        for (let i = 0; i < totalSub; i++) {
          const xpos = i % verticesX;
          const ypos = i / verticesX | 0;
          const value = ypos * this.verticesX + xpos;
          const value2 = ypos * this.verticesX + xpos + 1;
          const value3 = (ypos + 1) * this.verticesX + xpos;
          const value4 = (ypos + 1) * this.verticesX + xpos + 1;
          indices.push(
            value,
            value2,
            value3,
            value2,
            value4,
            value3
          );
        }
        this.buffers[0].data = new Float32Array(verts);
        this.buffers[1].data = new Float32Array(uvs);
        this.indexBuffer.data = new Uint32Array(indices);
        this.buffers[0].update();
        this.buffers[1].update();
        this.indexBuffer.update();
      }
    };
    _PlaneGeometry.defaultOptions = {
      width: 100,
      height: 100,
      verticesX: 10,
      verticesY: 10
    };
    let PlaneGeometry = _PlaneGeometry;

    "use strict";
    var __defProp$O = Object.defineProperty;
    var __getOwnPropSymbols$Q = Object.getOwnPropertySymbols;
    var __hasOwnProp$Q = Object.prototype.hasOwnProperty;
    var __propIsEnum$Q = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$O = (obj, key, value) => key in obj ? __defProp$O(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$O = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$Q.call(b, prop))
          __defNormalProp$O(a, prop, b[prop]);
      if (__getOwnPropSymbols$Q)
        for (var prop of __getOwnPropSymbols$Q(b)) {
          if (__propIsEnum$Q.call(b, prop))
            __defNormalProp$O(a, prop, b[prop]);
        }
      return a;
    };
    const _NineSliceGeometry = class _NineSliceGeometry extends PlaneGeometry {
      constructor(options = {}) {
        options = __spreadValues$O(__spreadValues$O({}, _NineSliceGeometry.defaultOptions), options);
        super({
          width: options.width,
          height: options.height,
          verticesX: 4,
          verticesY: 4
        });
        this.update(options);
      }
      /**
       * Updates the NineSliceGeometry with the options.
       * @param options - The options of the NineSliceGeometry.
       */
      update(options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
        this.width = (_a = options.width) != null ? _a : this.width;
        this.height = (_b = options.height) != null ? _b : this.height;
        this._originalWidth = (_c = options.originalWidth) != null ? _c : this._originalWidth;
        this._originalHeight = (_d = options.originalHeight) != null ? _d : this._originalHeight;
        this._leftWidth = (_e = options.leftWidth) != null ? _e : this._leftWidth;
        this._rightWidth = (_f = options.rightWidth) != null ? _f : this._rightWidth;
        this._topHeight = (_g = options.topHeight) != null ? _g : this._topHeight;
        this._bottomHeight = (_h = options.bottomHeight) != null ? _h : this._bottomHeight;
        this._anchorX = (_i = options.anchor) == null ? void 0 : _i.x;
        this._anchorY = (_j = options.anchor) == null ? void 0 : _j.y;
        this.updateUvs();
        this.updatePositions();
      }
      /** Updates the positions of the vertices. */
      updatePositions() {
        const p = this.positions;
        const {
          width,
          height,
          _leftWidth,
          _rightWidth,
          _topHeight,
          _bottomHeight,
          _anchorX,
          _anchorY
        } = this;
        const w = _leftWidth + _rightWidth;
        const scaleW = width > w ? 1 : width / w;
        const h = _topHeight + _bottomHeight;
        const scaleH = height > h ? 1 : height / h;
        const scale = Math.min(scaleW, scaleH);
        const anchorOffsetX = _anchorX * width;
        const anchorOffsetY = _anchorY * height;
        p[0] = p[8] = p[16] = p[24] = -anchorOffsetX;
        p[2] = p[10] = p[18] = p[26] = _leftWidth * scale - anchorOffsetX;
        p[4] = p[12] = p[20] = p[28] = width - _rightWidth * scale - anchorOffsetX;
        p[6] = p[14] = p[22] = p[30] = width - anchorOffsetX;
        p[1] = p[3] = p[5] = p[7] = -anchorOffsetY;
        p[9] = p[11] = p[13] = p[15] = _topHeight * scale - anchorOffsetY;
        p[17] = p[19] = p[21] = p[23] = height - _bottomHeight * scale - anchorOffsetY;
        p[25] = p[27] = p[29] = p[31] = height - anchorOffsetY;
        this.getBuffer("aPosition").update();
      }
      /** Updates the UVs of the vertices. */
      updateUvs() {
        const uvs = this.uvs;
        uvs[0] = uvs[8] = uvs[16] = uvs[24] = 0;
        uvs[1] = uvs[3] = uvs[5] = uvs[7] = 0;
        uvs[6] = uvs[14] = uvs[22] = uvs[30] = 1;
        uvs[25] = uvs[27] = uvs[29] = uvs[31] = 1;
        const _uvw = 1 / this._originalWidth;
        const _uvh = 1 / this._originalHeight;
        uvs[2] = uvs[10] = uvs[18] = uvs[26] = _uvw * this._leftWidth;
        uvs[9] = uvs[11] = uvs[13] = uvs[15] = _uvh * this._topHeight;
        uvs[4] = uvs[12] = uvs[20] = uvs[28] = 1 - _uvw * this._rightWidth;
        uvs[17] = uvs[19] = uvs[21] = uvs[23] = 1 - _uvh * this._bottomHeight;
        this.getBuffer("aUV").update();
      }
    };
    /** The default options for the NineSliceGeometry. */
    _NineSliceGeometry.defaultOptions = {
      /** The width of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane. */
      width: 100,
      /** The height of the NineSlicePlane, setting this will actually modify the vertices and UV's of this plane. */
      height: 100,
      /** The width of the left column. */
      leftWidth: 10,
      /** The height of the top row. */
      topHeight: 10,
      /** The width of the right column. */
      rightWidth: 10,
      /** The height of the bottom row. */
      bottomHeight: 10,
      /** The original width of the texture */
      originalWidth: 100,
      /** The original height of the texture */
      originalHeight: 100
    };
    let NineSliceGeometry = _NineSliceGeometry;

    "use strict";
    class NineSliceSpriteGpuData extends BatchableMesh {
      constructor() {
        super();
        this.geometry = new NineSliceGeometry();
      }
      destroy() {
        this.geometry.destroy();
      }
    }
    class NineSliceSpritePipe {
      constructor(renderer) {
        this._renderer = renderer;
        this._managedSprites = new GCManagedHash({ renderer, type: "renderable", name: "nineSliceSprite" });
      }
      addRenderable(sprite, instructionSet) {
        const gpuSprite = this._getGpuSprite(sprite);
        if (sprite.didViewUpdate)
          this._updateBatchableSprite(sprite, gpuSprite);
        this._renderer.renderPipes.batch.addToBatch(gpuSprite, instructionSet);
      }
      updateRenderable(sprite) {
        const gpuSprite = this._getGpuSprite(sprite);
        if (sprite.didViewUpdate)
          this._updateBatchableSprite(sprite, gpuSprite);
        gpuSprite._batcher.updateElement(gpuSprite);
      }
      validateRenderable(sprite) {
        const gpuSprite = this._getGpuSprite(sprite);
        return !gpuSprite._batcher.checkAndUpdateTexture(
          gpuSprite,
          sprite._texture
        );
      }
      _updateBatchableSprite(sprite, batchableSprite) {
        batchableSprite.geometry.update(sprite);
        batchableSprite.setTexture(sprite._texture);
      }
      _getGpuSprite(sprite) {
        return sprite._gpuData[this._renderer.uid] || this._initGPUSprite(sprite);
      }
      _initGPUSprite(sprite) {
        const gpuData = sprite._gpuData[this._renderer.uid] = new NineSliceSpriteGpuData();
        const batchableMesh = gpuData;
        batchableMesh.renderable = sprite;
        batchableMesh.transform = sprite.groupTransform;
        batchableMesh.texture = sprite._texture;
        batchableMesh.roundPixels = this._renderer._roundPixels | sprite._roundPixels;
        this._managedSprites.add(sprite);
        if (!sprite.didViewUpdate) {
          this._updateBatchableSprite(sprite, batchableMesh);
        }
        return gpuData;
      }
      destroy() {
        this._managedSprites.destroy();
        this._renderer = null;
      }
    }
    /** @ignore */
    NineSliceSpritePipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "nineSliceSprite"
    };

    "use strict";
    extensions.add(NineSliceSpritePipe);

    "use strict";
    class FilterPipe {
      constructor(renderer) {
        this._renderer = renderer;
      }
      push(filterEffect, container, instructionSet) {
        const renderPipes = this._renderer.renderPipes;
        renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "filter",
          canBundle: false,
          action: "pushFilter",
          container,
          filterEffect
        });
      }
      pop(_filterEffect, _container, instructionSet) {
        this._renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "filter",
          action: "popFilter",
          canBundle: false
        });
      }
      execute(instruction) {
        if (instruction.action === "pushFilter") {
          this._renderer.filter.push(instruction);
        } else if (instruction.action === "popFilter") {
          this._renderer.filter.pop();
        }
      }
      destroy() {
        this._renderer = null;
      }
    }
    FilterPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "filter"
    };

    "use strict";
    var __defProp$N = Object.defineProperty;
    var __getOwnPropSymbols$P = Object.getOwnPropertySymbols;
    var __hasOwnProp$P = Object.prototype.hasOwnProperty;
    var __propIsEnum$P = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$N = (obj, key, value) => key in obj ? __defProp$N(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$N = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$P.call(b, prop))
          __defNormalProp$N(a, prop, b[prop]);
      if (__getOwnPropSymbols$P)
        for (var prop of __getOwnPropSymbols$P(b)) {
          if (__propIsEnum$P.call(b, prop))
            __defNormalProp$N(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$j = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$P.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$P)
        for (var prop of __getOwnPropSymbols$P(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$P.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const _Filter = class _Filter extends Shader {
      /**
       * @param options - The optional parameters of this filter.
       */
      constructor(options) {
        options = __spreadValues$N(__spreadValues$N({}, _Filter.defaultOptions), options);
        super(options);
        /** If enabled is true the filter is applied, if false it will not. */
        this.enabled = true;
        /**
         * The gpu state the filter requires to render.
         * @internal
         */
        this._state = State.for2d();
        this.blendMode = options.blendMode;
        this.padding = options.padding;
        if (typeof options.antialias === "boolean") {
          this.antialias = options.antialias ? "on" : "off";
        } else {
          this.antialias = options.antialias;
        }
        this.resolution = options.resolution;
        this.blendRequired = options.blendRequired;
        this.clipToViewport = options.clipToViewport;
        this.addResource("uTexture", 0, 1);
        if (options.blendRequired) {
          this.addResource("uBackTexture", 0, 3);
        }
      }
      /**
       * Applies the filter
       * @param filterManager - The renderer to retrieve the filter from
       * @param input - The input render target.
       * @param output - The target to output to.
       * @param clearMode - Should the output be cleared before rendering to it
       */
      apply(filterManager, input, output, clearMode) {
        filterManager.applyFilter(this, input, output, clearMode);
      }
      /**
       * Get the blend mode of the filter.
       * @default "normal"
       */
      get blendMode() {
        return this._state.blendMode;
      }
      /** Sets the blend mode of the filter. */
      set blendMode(value) {
        this._state.blendMode = value;
      }
      /**
       * A short hand function to create a filter based of a vertex and fragment shader src.
       * @param options
       * @returns A shiny new PixiJS filter!
       */
      static from(options) {
        const _a = options, { gpu, gl } = _a, rest = __objRest$j(_a, ["gpu", "gl"]);
        let gpuProgram;
        let glProgram;
        if (gpu) {
          gpuProgram = GpuProgram.from(gpu);
        }
        if (gl) {
          glProgram = GlProgram.from(gl);
        }
        return new _Filter(__spreadValues$N({
          gpuProgram,
          glProgram
        }, rest));
      }
    };
    /** The default filter settings */
    _Filter.defaultOptions = {
      blendMode: "normal",
      resolution: 1,
      padding: 0,
      antialias: "off",
      blendRequired: false,
      clipToViewport: true
    };
    let Filter = _Filter;

    var vertex$2 = "in vec2 aPosition;\nout vec2 vTextureCoord;\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nvec4 filterVertexPosition( void )\n{\n    vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n    \n    position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n    return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvoid main(void)\n{\n    gl_Position = filterVertexPosition();\n    vTextureCoord = filterTextureCoord();\n}\n";

    var fragment$5 = "in vec2 vTextureCoord;\nout vec4 finalColor;\nuniform sampler2D uTexture;\nvoid main() {\n    finalColor = texture(uTexture, vTextureCoord);\n}\n";

    var source$6 = "struct GlobalFilterUniforms {\n  uInputSize: vec4<f32>,\n  uInputPixel: vec4<f32>,\n  uInputClamp: vec4<f32>,\n  uOutputFrame: vec4<f32>,\n  uGlobalFrame: vec4<f32>,\n  uOutputTexture: vec4<f32>,\n};\n\n@group(0) @binding(0) var <uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler: sampler;\n\nstruct VSOutput {\n  @builtin(position) position: vec4<f32>,\n  @location(0) uv: vec2<f32>\n};\n\nfn filterVertexPosition(aPosition: vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord(aPosition: vec2<f32>) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\n@vertex\nfn mainVertex(\n  @location(0) aPosition: vec2<f32>,\n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition)\n  );\n}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n) -> @location(0) vec4<f32> {\n    return textureSample(uTexture, uSampler, uv);\n}\n";

    "use strict";
    class PassthroughFilter extends Filter {
      constructor() {
        const gpuProgram = GpuProgram.from({
          vertex: { source: source$6, entryPoint: "mainVertex" },
          fragment: { source: source$6, entryPoint: "mainFragment" },
          name: "passthrough-filter"
        });
        const glProgram = GlProgram.from({
          vertex: vertex$2,
          fragment: fragment$5,
          name: "passthrough-filter"
        });
        super({
          gpuProgram,
          glProgram
        });
      }
    }

    "use strict";

    "use strict";

    "use strict";
    function pointInTriangle(px, py, x1, y1, x2, y2, x3, y3) {
      const v2x = x3 - x1;
      const v2y = y3 - y1;
      const v1x = x2 - x1;
      const v1y = y2 - y1;
      const v0x = px - x1;
      const v0y = py - y1;
      const dot00 = v2x * v2x + v2y * v2y;
      const dot01 = v2x * v1x + v2y * v1y;
      const dot02 = v2x * v0x + v2y * v0y;
      const dot11 = v1x * v1x + v1y * v1y;
      const dot12 = v1x * v0x + v1y * v0y;
      const invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
      const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
      const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
      return u >= 0 && v >= 0 && u + v < 1;
    }

    "use strict";

    "use strict";

    "use strict";
    class Triangle {
      /**
       * @param x - The X coord of the first point.
       * @param y - The Y coord of the first point.
       * @param x2 - The X coord of the second point.
       * @param y2 - The Y coord of the second point.
       * @param x3 - The X coord of the third point.
       * @param y3 - The Y coord of the third point.
       */
      constructor(x = 0, y = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0) {
        /**
         * The type of the object, mainly used to avoid `instanceof` checks
         * @example
         * ```ts
         * // Check shape type
         * const shape = new Triangle(0, 0, 100, 0, 50, 100);
         * console.log(shape.type); // 'triangle'
         *
         * // Use in type guards
         * if (shape.type === 'triangle') {
         *     console.log(shape.x2, shape.y2);
         * }
         * ```
         * @readonly
         * @default 'triangle'
         * @see {@link SHAPE_PRIMITIVE} For all shape types
         */
        this.type = "triangle";
        this.x = x;
        this.y = y;
        this.x2 = x2;
        this.y2 = y2;
        this.x3 = x3;
        this.y3 = y3;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this triangle
       * @example
       * ```ts
       * // Basic containment check
       * const triangle = new Triangle(0, 0, 100, 0, 50, 100);
       * const isInside = triangle.contains(25, 25); // true
       * ```
       * @remarks
       * - Uses barycentric coordinate system
       * - Works with any triangle shape
       * @param x - The X coordinate of the point to test
       * @param y - The Y coordinate of the point to test
       * @returns Whether the x/y coordinates are within this Triangle
       * @see {@link Triangle.strokeContains} For checking stroke intersection
       * @see {@link Triangle.getBounds} For getting containing rectangle
       */
      contains(x, y) {
        const s = (this.x - this.x3) * (y - this.y3) - (this.y - this.y3) * (x - this.x3);
        const t = (this.x2 - this.x) * (y - this.y) - (this.y2 - this.y) * (x - this.x);
        if (s < 0 !== t < 0 && s !== 0 && t !== 0) {
          return false;
        }
        const d = (this.x3 - this.x2) * (y - this.y2) - (this.y3 - this.y2) * (x - this.x2);
        return d === 0 || d < 0 === s + t <= 0;
      }
      /**
       * Checks whether the x and y coordinates given are contained within this triangle including the stroke.
       * @example
       * ```ts
       * // Basic stroke check
       * const triangle = new Triangle(0, 0, 100, 0, 50, 100);
       * const isOnStroke = triangle.strokeContains(25, 25, 4); // 4px line width
       *
       * // Check with different alignments
       * const innerStroke = triangle.strokeContains(25, 25, 4, 1);   // Inside
       * const centerStroke = triangle.strokeContains(25, 25, 4, 0.5); // Centered
       * const outerStroke = triangle.strokeContains(25, 25, 4, 0);   // Outside
       * ```
       * @param pointX - The X coordinate of the point to test
       * @param pointY - The Y coordinate of the point to test
       * @param strokeWidth - The width of the line to check
       * @param _alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)
       * @returns Whether the x/y coordinates are within this triangle's stroke
       * @see {@link Triangle.contains} For checking fill containment
       * @see {@link Triangle.getBounds} For getting stroke bounds
       */
      strokeContains(pointX, pointY, strokeWidth, _alignment = 0.5) {
        const halfStrokeWidth = strokeWidth / 2;
        const halfStrokeWidthSquared = halfStrokeWidth * halfStrokeWidth;
        const { x, x2, x3, y, y2, y3 } = this;
        if (squaredDistanceToLineSegment(pointX, pointY, x, y, x2, y3) <= halfStrokeWidthSquared || squaredDistanceToLineSegment(pointX, pointY, x2, y2, x3, y3) <= halfStrokeWidthSquared || squaredDistanceToLineSegment(pointX, pointY, x3, y3, x, y) <= halfStrokeWidthSquared) {
          return true;
        }
        return false;
      }
      /**
       * Creates a clone of this Triangle
       * @example
       * ```ts
       * // Basic cloning
       * const original = new Triangle(0, 0, 100, 0, 50, 100);
       * const copy = original.clone();
       *
       * // Clone and modify
       * const modified = original.clone();
       * modified.x3 = 75;
       * modified.y3 = 150;
       *
       * // Verify independence
       * console.log(original.y3);  // 100
       * console.log(modified.y3);  // 150
       * ```
       * @returns A copy of the triangle
       * @see {@link Triangle.copyFrom} For copying into existing triangle
       * @see {@link Triangle.copyTo} For copying to another triangle
       */
      clone() {
        const triangle = new Triangle(
          this.x,
          this.y,
          this.x2,
          this.y2,
          this.x3,
          this.y3
        );
        return triangle;
      }
      /**
       * Copies another triangle to this one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Triangle(0, 0, 100, 0, 50, 100);
       * const target = new Triangle();
       * target.copyFrom(source);
       *
       * // Chain with other operations
       * const triangle = new Triangle()
       *     .copyFrom(source)
       *     .getBounds(rect);
       * ```
       * @param triangle - The triangle to copy from
       * @returns Returns itself
       * @see {@link Triangle.copyTo} For copying to another triangle
       * @see {@link Triangle.clone} For creating new triangle copy
       */
      copyFrom(triangle) {
        this.x = triangle.x;
        this.y = triangle.y;
        this.x2 = triangle.x2;
        this.y2 = triangle.y2;
        this.x3 = triangle.x3;
        this.y3 = triangle.y3;
        return this;
      }
      /**
       * Copies this triangle to another one.
       * @example
       * ```ts
       * // Basic copying
       * const source = new Triangle(0, 0, 100, 0, 50, 100);
       * const target = new Triangle();
       * source.copyTo(target);
       *
       * // Chain with other operations
       * const result = source
       *     .copyTo(new Triangle())
       *     .getBounds();
       * ```
       * @remarks
       * - Updates target triangle values
       * - Copies all point coordinates
       * - Returns target for chaining
       * - More efficient than clone()
       * @param triangle - The triangle to copy to
       * @returns Returns given parameter
       * @see {@link Triangle.copyFrom} For copying from another triangle
       * @see {@link Triangle.clone} For creating new triangle copy
       */
      copyTo(triangle) {
        triangle.copyFrom(this);
        return triangle;
      }
      /**
       * Returns the framing rectangle of the triangle as a Rectangle object
       * @example
       * ```ts
       * // Basic bounds calculation
       * const triangle = new Triangle(0, 0, 100, 0, 50, 100);
       * const bounds = triangle.getBounds();
       * // bounds: x=0, y=0, width=100, height=100
       *
       * // Reuse existing rectangle
       * const rect = new Rectangle();
       * triangle.getBounds(rect);
       * ```
       * @param out - Optional rectangle to store the result
       * @returns The framing rectangle
       * @see {@link Rectangle} For rectangle properties
       * @see {@link Triangle.contains} For checking if a point is inside
       */
      getBounds(out) {
        out || (out = new Rectangle());
        const minX = Math.min(this.x, this.x2, this.x3);
        const maxX = Math.max(this.x, this.x2, this.x3);
        const minY = Math.min(this.y, this.y2, this.y3);
        const maxY = Math.max(this.y, this.y2, this.y3);
        out.x = minX;
        out.y = minY;
        out.width = maxX - minX;
        out.height = maxY - minY;
        return out;
      }
    }

    "use strict";

    "use strict";
    const tempProjectionMatrix = new Matrix();
    function getGlobalRenderableBounds(renderables, bounds) {
      var _a;
      bounds.clear();
      const actualMatrix = bounds.matrix;
      for (let i = 0; i < renderables.length; i++) {
        const renderable = renderables[i];
        if (renderable.globalDisplayStatus < 7) {
          continue;
        }
        const renderGroup = (_a = renderable.renderGroup) != null ? _a : renderable.parentRenderGroup;
        if (renderGroup == null ? void 0 : renderGroup.isCachedAsTexture) {
          bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup.textureOffsetInverseTransform).append(renderable.worldTransform);
        } else if (renderGroup == null ? void 0 : renderGroup._parentCacheAsTextureRenderGroup) {
          bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup._parentCacheAsTextureRenderGroup.inverseWorldTransform).append(renderable.groupTransform);
        } else {
          bounds.matrix = renderable.worldTransform;
        }
        bounds.addBounds(renderable.bounds);
      }
      bounds.matrix = actualMatrix;
      return bounds;
    }

    "use strict";
    const quadGeometry = new Geometry({
      attributes: {
        aPosition: {
          buffer: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
          format: "float32x2",
          stride: 2 * 4,
          offset: 0
        }
      },
      indexBuffer: new Uint32Array([0, 1, 2, 0, 2, 3])
    });
    class FilterData {
      constructor() {
        /**
         * Indicates whether the filter should be skipped.
         * @type {boolean}
         */
        this.skip = false;
        /**
         * The texture to which the filter is applied.
         * @type {Texture}
         */
        this.inputTexture = null;
        /**
         * The back texture used for blending, if required.
         * @type {Texture | null}
         */
        this.backTexture = null;
        /**
         * The list of filters to be applied.
         * @type {Filter[]}
         */
        this.filters = null;
        /**
         * The bounds of the filter area.
         * @type {Bounds}
         */
        this.bounds = new Bounds();
        /**
         * The container to which the filter is applied.
         * @type {Container}
         */
        this.container = null;
        /**
         * Indicates whether blending is required for the filter.
         * @type {boolean}
         */
        this.blendRequired = false;
        /**
         * The render surface where the output of the filter is rendered.
         * @type {RenderSurface}
         */
        this.outputRenderSurface = null;
        /**
         * The global frame of the filter area.
         * @type {{ x: number, y: number, width: number, height: number }}
         */
        this.globalFrame = { x: 0, y: 0, width: 0, height: 0 };
        /** The first enabled filter index in the current filter list. */
        this.firstEnabledIndex = -1;
        /** The last enabled filter index in the current filter list. */
        this.lastEnabledIndex = -1;
      }
    }
    class FilterSystem {
      constructor(renderer) {
        this._filterStackIndex = 0;
        this._filterStack = [];
        this._filterGlobalUniforms = new UniformGroup({
          uInputSize: { value: new Float32Array(4), type: "vec4<f32>" },
          uInputPixel: { value: new Float32Array(4), type: "vec4<f32>" },
          uInputClamp: { value: new Float32Array(4), type: "vec4<f32>" },
          uOutputFrame: { value: new Float32Array(4), type: "vec4<f32>" },
          uGlobalFrame: { value: new Float32Array(4), type: "vec4<f32>" },
          uOutputTexture: { value: new Float32Array(4), type: "vec4<f32>" }
        });
        this._globalFilterBindGroup = new BindGroup({});
        this.renderer = renderer;
      }
      /**
       * The back texture of the currently active filter. Requires the filter to have `blendRequired` set to true.
       * @readonly
       */
      get activeBackTexture() {
        var _a;
        return (_a = this._activeFilterData) == null ? void 0 : _a.backTexture;
      }
      /**
       * Pushes a filter instruction onto the filter stack.
       * @param instruction - The instruction containing the filter effect and container.
       * @internal
       */
      push(instruction) {
        const renderer = this.renderer;
        const filters = instruction.filterEffect.filters;
        const filterData = this._pushFilterData();
        filterData.skip = false;
        filterData.filters = filters;
        filterData.container = instruction.container;
        filterData.outputRenderSurface = renderer.renderTarget.renderSurface;
        const colorTextureSource = renderer.renderTarget.renderTarget.colorTexture.source;
        const rootResolution = colorTextureSource.resolution;
        const rootAntialias = colorTextureSource.antialias;
        if (filters.every((filter) => !filter.enabled)) {
          filterData.skip = true;
          return;
        }
        const bounds = filterData.bounds;
        this._calculateFilterArea(instruction, bounds);
        this._calculateFilterBounds(filterData, renderer.renderTarget.rootViewPort, rootAntialias, rootResolution, 1);
        if (filterData.skip) {
          return;
        }
        const previousFilterData = this._getPreviousFilterData();
        const globalResolution = this._findFilterResolution(rootResolution);
        let offsetX = 0;
        let offsetY = 0;
        if (previousFilterData) {
          offsetX = previousFilterData.bounds.minX;
          offsetY = previousFilterData.bounds.minY;
        }
        this._calculateGlobalFrame(
          filterData,
          offsetX,
          offsetY,
          globalResolution,
          colorTextureSource.width,
          colorTextureSource.height
        );
        this._setupFilterTextures(filterData, bounds, renderer, previousFilterData);
      }
      /**
       * Applies filters to a texture.
       *
       * This method takes a texture and a list of filters, applies the filters to the texture,
       * and returns the resulting texture.
       * @param {object} params - The parameters for applying filters.
       * @param {Texture} params.texture - The texture to apply filters to.
       * @param {Filter[]} params.filters - The filters to apply.
       * @returns {Texture} The resulting texture after all filters have been applied.
       * @example
       *
       * ```ts
       * // Create a texture and a list of filters
       * const texture = new Texture(...);
       * const filters = [new BlurFilter(), new ColorMatrixFilter()];
       *
       * // Apply the filters to the texture
       * const resultTexture = filterSystem.applyToTexture({ texture, filters });
       *
       * // Use the resulting texture
       * sprite.texture = resultTexture;
       * ```
       *
       * Key Points:
       * 1. padding is not currently supported here - so clipping may occur with filters that use padding.
       * 2. If all filters are disabled or skipped, the original texture is returned.
       */
      generateFilteredTexture({ texture, filters }) {
        const filterData = this._pushFilterData();
        this._activeFilterData = filterData;
        filterData.skip = false;
        filterData.filters = filters;
        const colorTextureSource = texture.source;
        const rootResolution = colorTextureSource.resolution;
        const rootAntialias = colorTextureSource.antialias;
        if (filters.every((filter) => !filter.enabled)) {
          filterData.skip = true;
          return texture;
        }
        const bounds = filterData.bounds;
        bounds.addRect(texture.frame);
        this._calculateFilterBounds(filterData, bounds.rectangle, rootAntialias, rootResolution, 0);
        if (filterData.skip) {
          return texture;
        }
        const globalResolution = rootResolution;
        const offsetX = 0;
        const offsetY = 0;
        this._calculateGlobalFrame(
          filterData,
          offsetX,
          offsetY,
          globalResolution,
          colorTextureSource.width,
          colorTextureSource.height
        );
        filterData.outputRenderSurface = TexturePool.getOptimalTexture(
          bounds.width,
          bounds.height,
          filterData.resolution,
          filterData.antialias
        );
        filterData.backTexture = Texture.EMPTY;
        filterData.inputTexture = texture;
        const renderer = this.renderer;
        renderer.renderTarget.finishRenderPass();
        this._applyFiltersToTexture(filterData, true);
        const outputTexture = filterData.outputRenderSurface;
        outputTexture.source.alphaMode = "premultiplied-alpha";
        return outputTexture;
      }
      /** @internal */
      pop() {
        const renderer = this.renderer;
        const filterData = this._popFilterData();
        if (filterData.skip) {
          return;
        }
        renderer.globalUniforms.pop();
        renderer.renderTarget.finishRenderPass();
        this._activeFilterData = filterData;
        this._applyFiltersToTexture(filterData, false);
        if (filterData.blendRequired) {
          TexturePool.returnTexture(filterData.backTexture);
        }
        TexturePool.returnTexture(filterData.inputTexture);
      }
      /**
       * Copies the last render surface to a texture.
       * @param lastRenderSurface - The last render surface to copy from.
       * @param bounds - The bounds of the area to copy.
       * @param previousBounds - The previous bounds to use for offsetting the copy.
       */
      getBackTexture(lastRenderSurface, bounds, previousBounds) {
        const backgroundResolution = lastRenderSurface.colorTexture.source._resolution;
        const backTexture = TexturePool.getOptimalTexture(
          bounds.width,
          bounds.height,
          backgroundResolution,
          false
        );
        let x = bounds.minX;
        let y = bounds.minY;
        if (previousBounds) {
          x -= previousBounds.minX;
          y -= previousBounds.minY;
        }
        x = Math.floor(x * backgroundResolution);
        y = Math.floor(y * backgroundResolution);
        const width = Math.ceil(bounds.width * backgroundResolution);
        const height = Math.ceil(bounds.height * backgroundResolution);
        this.renderer.renderTarget.copyToTexture(
          lastRenderSurface,
          backTexture,
          { x, y },
          { width, height },
          { x: 0, y: 0 }
        );
        return backTexture;
      }
      /**
       * Applies a filter to a texture.
       * @param filter - The filter to apply.
       * @param input - The input texture.
       * @param output - The output render surface.
       * @param clear - Whether to clear the output surface before applying the filter.
       */
      applyFilter(filter, input, output, clear) {
        const renderer = this.renderer;
        const filterData = this._activeFilterData;
        const outputRenderSurface = filterData.outputRenderSurface;
        const isFinalTarget = outputRenderSurface === output;
        const rootResolution = renderer.renderTarget.rootRenderTarget.colorTexture.source._resolution;
        const resolution = this._findFilterResolution(rootResolution);
        let offsetX = 0;
        let offsetY = 0;
        if (isFinalTarget) {
          const offset = this._findPreviousFilterOffset();
          offsetX = offset.x;
          offsetY = offset.y;
        }
        this._updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear);
        const filterToApply = filter.enabled ? filter : this._getPassthroughFilter();
        this._setupBindGroupsAndRender(filterToApply, input, renderer);
      }
      /**
       * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_.
       *
       * Use `outputMatrix * vTextureCoord` in the shader.
       * @param outputMatrix - The matrix to output to.
       * @param {Sprite} sprite - The sprite to map to.
       * @returns The mapped matrix.
       */
      calculateSpriteMatrix(outputMatrix, sprite) {
        const data = this._activeFilterData;
        const mappedMatrix = outputMatrix.set(
          data.inputTexture._source.width,
          0,
          0,
          data.inputTexture._source.height,
          data.bounds.minX,
          data.bounds.minY
        );
        const worldTransform = sprite.worldTransform.copyTo(Matrix.shared);
        const renderGroup = sprite.renderGroup || sprite.parentRenderGroup;
        if (renderGroup && renderGroup.cacheToLocalTransform) {
          worldTransform.prepend(renderGroup.cacheToLocalTransform);
        }
        worldTransform.invert();
        mappedMatrix.prepend(worldTransform);
        mappedMatrix.scale(
          1 / sprite.texture.orig.width,
          1 / sprite.texture.orig.height
        );
        mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);
        return mappedMatrix;
      }
      destroy() {
        var _a;
        (_a = this._passthroughFilter) == null ? void 0 : _a.destroy(true);
        this._passthroughFilter = null;
      }
      _getPassthroughFilter() {
        var _a;
        (_a = this._passthroughFilter) != null ? _a : this._passthroughFilter = new PassthroughFilter();
        return this._passthroughFilter;
      }
      /**
       * Sets up the bind groups and renders the filter.
       * @param filter - The filter to apply
       * @param input - The input texture
       * @param renderer - The renderer instance
       */
      _setupBindGroupsAndRender(filter, input, renderer) {
        if (renderer.renderPipes.uniformBatch) {
          const batchUniforms = renderer.renderPipes.uniformBatch.getUboResource(this._filterGlobalUniforms);
          this._globalFilterBindGroup.setResource(batchUniforms, 0);
        } else {
          this._globalFilterBindGroup.setResource(this._filterGlobalUniforms, 0);
        }
        this._globalFilterBindGroup.setResource(input.source, 1);
        this._globalFilterBindGroup.setResource(input.source.style, 2);
        filter.groups[0] = this._globalFilterBindGroup;
        renderer.encoder.draw({
          geometry: quadGeometry,
          shader: filter,
          state: filter._state,
          topology: "triangle-list"
        });
        if (renderer.type === RendererType.WEBGL) {
          renderer.renderTarget.finishRenderPass();
        }
      }
      /**
       * Sets up the filter textures including input texture and back texture if needed.
       * @param filterData - The filter data to update
       * @param bounds - The bounds for the texture
       * @param renderer - The renderer instance
       * @param previousFilterData - The previous filter data for back texture calculation
       */
      _setupFilterTextures(filterData, bounds, renderer, previousFilterData) {
        filterData.backTexture = Texture.EMPTY;
        filterData.inputTexture = TexturePool.getOptimalTexture(
          bounds.width,
          bounds.height,
          filterData.resolution,
          filterData.antialias
        );
        if (filterData.blendRequired) {
          renderer.renderTarget.finishRenderPass();
          const renderTarget = renderer.renderTarget.getRenderTarget(filterData.outputRenderSurface);
          filterData.backTexture = this.getBackTexture(renderTarget, bounds, previousFilterData == null ? void 0 : previousFilterData.bounds);
        }
        renderer.renderTarget.bind(filterData.inputTexture, true);
        renderer.globalUniforms.push({
          offset: bounds
        });
      }
      /**
       * Calculates and sets the global frame for the filter.
       * @param filterData - The filter data to update
       * @param offsetX - The X offset
       * @param offsetY - The Y offset
       * @param globalResolution - The global resolution
       * @param sourceWidth - The source texture width
       * @param sourceHeight - The source texture height
       */
      _calculateGlobalFrame(filterData, offsetX, offsetY, globalResolution, sourceWidth, sourceHeight) {
        const globalFrame = filterData.globalFrame;
        globalFrame.x = offsetX * globalResolution;
        globalFrame.y = offsetY * globalResolution;
        globalFrame.width = sourceWidth * globalResolution;
        globalFrame.height = sourceHeight * globalResolution;
      }
      /**
       * Updates the filter uniforms with the current filter state.
       * @param input - The input texture
       * @param output - The output render surface
       * @param filterData - The current filter data
       * @param offsetX - The X offset for positioning
       * @param offsetY - The Y offset for positioning
       * @param resolution - The current resolution
       * @param isFinalTarget - Whether this is the final render target
       * @param clear - Whether to clear the output surface
       */
      _updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear) {
        const uniforms = this._filterGlobalUniforms.uniforms;
        const outputFrame = uniforms.uOutputFrame;
        const inputSize = uniforms.uInputSize;
        const inputPixel = uniforms.uInputPixel;
        const inputClamp = uniforms.uInputClamp;
        const globalFrame = uniforms.uGlobalFrame;
        const outputTexture = uniforms.uOutputTexture;
        if (isFinalTarget) {
          outputFrame[0] = filterData.bounds.minX - offsetX;
          outputFrame[1] = filterData.bounds.minY - offsetY;
        } else {
          outputFrame[0] = 0;
          outputFrame[1] = 0;
        }
        outputFrame[2] = input.frame.width;
        outputFrame[3] = input.frame.height;
        inputSize[0] = input.source.width;
        inputSize[1] = input.source.height;
        inputSize[2] = 1 / inputSize[0];
        inputSize[3] = 1 / inputSize[1];
        inputPixel[0] = input.source.pixelWidth;
        inputPixel[1] = input.source.pixelHeight;
        inputPixel[2] = 1 / inputPixel[0];
        inputPixel[3] = 1 / inputPixel[1];
        inputClamp[0] = 0.5 * inputPixel[2];
        inputClamp[1] = 0.5 * inputPixel[3];
        inputClamp[2] = input.frame.width * inputSize[2] - 0.5 * inputPixel[2];
        inputClamp[3] = input.frame.height * inputSize[3] - 0.5 * inputPixel[3];
        const rootTexture = this.renderer.renderTarget.rootRenderTarget.colorTexture;
        globalFrame[0] = offsetX * resolution;
        globalFrame[1] = offsetY * resolution;
        globalFrame[2] = rootTexture.source.width * resolution;
        globalFrame[3] = rootTexture.source.height * resolution;
        if (output instanceof Texture)
          output.source.resource = null;
        const renderTarget = this.renderer.renderTarget.getRenderTarget(output);
        this.renderer.renderTarget.bind(output, !!clear);
        if (output instanceof Texture) {
          outputTexture[0] = output.frame.width;
          outputTexture[1] = output.frame.height;
        } else {
          outputTexture[0] = renderTarget.width;
          outputTexture[1] = renderTarget.height;
        }
        outputTexture[2] = renderTarget.isRoot ? -1 : 1;
        this._filterGlobalUniforms.update();
      }
      /**
       * Finds the correct resolution by looking back through the filter stack.
       * @param rootResolution - The fallback root resolution to use
       * @returns The resolution from the previous filter or root resolution
       */
      _findFilterResolution(rootResolution) {
        let currentIndex = this._filterStackIndex - 1;
        while (currentIndex > 0 && this._filterStack[currentIndex].skip) {
          --currentIndex;
        }
        return currentIndex > 0 && this._filterStack[currentIndex].inputTexture ? this._filterStack[currentIndex].inputTexture.source._resolution : rootResolution;
      }
      /**
       * Finds the offset from the previous non-skipped filter in the stack.
       * @returns The offset coordinates from the previous filter
       */
      _findPreviousFilterOffset() {
        let offsetX = 0;
        let offsetY = 0;
        let lastIndex = this._filterStackIndex;
        while (lastIndex > 0) {
          lastIndex--;
          const prevFilterData = this._filterStack[lastIndex];
          if (!prevFilterData.skip) {
            offsetX = prevFilterData.bounds.minX;
            offsetY = prevFilterData.bounds.minY;
            break;
          }
        }
        return { x: offsetX, y: offsetY };
      }
      /**
       * Calculates the filter area bounds based on the instruction type.
       * @param instruction - The filter instruction
       * @param bounds - The bounds object to populate
       */
      _calculateFilterArea(instruction, bounds) {
        if (instruction.renderables) {
          getGlobalRenderableBounds(instruction.renderables, bounds);
        } else if (instruction.filterEffect.filterArea) {
          bounds.clear();
          bounds.addRect(instruction.filterEffect.filterArea);
          bounds.applyMatrix(instruction.container.worldTransform);
        } else {
          instruction.container.getFastGlobalBounds(true, bounds);
        }
        if (instruction.container) {
          const renderGroup = instruction.container.renderGroup || instruction.container.parentRenderGroup;
          const filterFrameTransform = renderGroup.cacheToLocalTransform;
          if (filterFrameTransform) {
            bounds.applyMatrix(filterFrameTransform);
          }
        }
      }
      _applyFiltersToTexture(filterData, clear) {
        const inputTexture = filterData.inputTexture;
        const bounds = filterData.bounds;
        const filters = filterData.filters;
        const firstEnabled = filterData.firstEnabledIndex;
        const lastEnabled = filterData.lastEnabledIndex;
        this._globalFilterBindGroup.setResource(inputTexture.source.style, 2);
        this._globalFilterBindGroup.setResource(filterData.backTexture.source, 3);
        if (firstEnabled === lastEnabled) {
          filters[firstEnabled].apply(this, inputTexture, filterData.outputRenderSurface, clear);
        } else {
          let flip = filterData.inputTexture;
          const tempTexture = TexturePool.getOptimalTexture(
            bounds.width,
            bounds.height,
            flip.source._resolution,
            false
          );
          let flop = tempTexture;
          for (let i = firstEnabled; i < lastEnabled; i++) {
            const filter = filters[i];
            if (!filter.enabled)
              continue;
            filter.apply(this, flip, flop, true);
            const t = flip;
            flip = flop;
            flop = t;
          }
          filters[lastEnabled].apply(this, flip, filterData.outputRenderSurface, clear);
          TexturePool.returnTexture(tempTexture);
        }
      }
      _calculateFilterBounds(filterData, viewPort, rootAntialias, rootResolution, paddingMultiplier) {
        var _a, _b;
        const renderer = this.renderer;
        const bounds = filterData.bounds;
        const filters = filterData.filters;
        let resolution = Infinity;
        let padding = 0;
        let antialias = true;
        let blendRequired = false;
        let enabled = false;
        let clipToViewport = true;
        let firstEnabledIndex = -1;
        let lastEnabledIndex = -1;
        for (let i = 0; i < filters.length; i++) {
          const filter = filters[i];
          if (!filter.enabled)
            continue;
          if (firstEnabledIndex === -1)
            firstEnabledIndex = i;
          lastEnabledIndex = i;
          resolution = Math.min(resolution, filter.resolution === "inherit" ? rootResolution : filter.resolution);
          padding += filter.padding;
          if (filter.antialias === "off") {
            antialias = false;
          } else if (filter.antialias === "inherit") {
            antialias && (antialias = rootAntialias);
          }
          if (!filter.clipToViewport) {
            clipToViewport = false;
          }
          const isCompatible = !!(filter.compatibleRenderers & renderer.type);
          if (!isCompatible) {
            enabled = false;
            break;
          }
          if (filter.blendRequired && !((_b = (_a = renderer.backBuffer) == null ? void 0 : _a.useBackBuffer) != null ? _b : true)) {
            warn("Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options.");
            enabled = false;
            break;
          }
          enabled = true;
          blendRequired || (blendRequired = filter.blendRequired);
        }
        if (!enabled) {
          filterData.skip = true;
          return;
        }
        if (clipToViewport) {
          bounds.fitBounds(0, viewPort.width / rootResolution, 0, viewPort.height / rootResolution);
        }
        bounds.scale(resolution).ceil().scale(1 / resolution).pad((padding | 0) * paddingMultiplier);
        if (!bounds.isPositive) {
          filterData.skip = true;
          return;
        }
        filterData.antialias = antialias;
        filterData.resolution = resolution;
        filterData.blendRequired = blendRequired;
        filterData.firstEnabledIndex = firstEnabledIndex;
        filterData.lastEnabledIndex = lastEnabledIndex;
      }
      _popFilterData() {
        this._filterStackIndex--;
        return this._filterStack[this._filterStackIndex];
      }
      _getPreviousFilterData() {
        let previousFilterData;
        let index = this._filterStackIndex - 1;
        while (index > 0) {
          index--;
          previousFilterData = this._filterStack[index];
          if (!previousFilterData.skip) {
            break;
          }
        }
        return previousFilterData;
      }
      _pushFilterData() {
        let filterData = this._filterStack[this._filterStackIndex];
        if (!filterData) {
          filterData = this._filterStack[this._filterStackIndex] = new FilterData();
        }
        this._filterStackIndex++;
        return filterData;
      }
    }
    /** @ignore */
    FilterSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "filter"
    };

    "use strict";
    extensions.add(FilterSystem);
    extensions.add(FilterPipe);

    "use strict";

    var webworkerAll = {
        __proto__: null
    };

    "use strict";
    const environments = [];
    extensions.handleByNamedList(ExtensionType.Environment, environments);
    async function loadEnvironmentExtensions(skip) {
      if (skip)
        return;
      for (let i = 0; i < environments.length; i++) {
        const env = environments[i];
        if (env.value.test()) {
          await env.value.load();
          return;
        }
      }
    }
    async function autoDetectEnvironment(add) {
      return loadEnvironmentExtensions(!add);
    }

    "use strict";
    let unsafeEval;
    function unsafeEvalSupported() {
      if (typeof unsafeEval === "boolean") {
        return unsafeEval;
      }
      try {
        const func = new Function("param1", "param2", "param3", "return param1[param2] === param3;");
        unsafeEval = func({ a: "b" }, "a", "b") === true;
      } catch (_e) {
        unsafeEval = false;
      }
      return unsafeEval;
    }

    "use strict";
    var CLEAR = /* @__PURE__ */ ((CLEAR2) => {
      CLEAR2[CLEAR2["NONE"] = 0] = "NONE";
      CLEAR2[CLEAR2["COLOR"] = 16384] = "COLOR";
      CLEAR2[CLEAR2["STENCIL"] = 1024] = "STENCIL";
      CLEAR2[CLEAR2["DEPTH"] = 256] = "DEPTH";
      CLEAR2[CLEAR2["COLOR_DEPTH"] = 16640] = "COLOR_DEPTH";
      CLEAR2[CLEAR2["COLOR_STENCIL"] = 17408] = "COLOR_STENCIL";
      CLEAR2[CLEAR2["DEPTH_STENCIL"] = 1280] = "DEPTH_STENCIL";
      CLEAR2[CLEAR2["ALL"] = 17664] = "ALL";
      return CLEAR2;
    })(CLEAR || {});

    "use strict";
    class SystemRunner {
      /**
       * @param name - The function name that will be executed on the listeners added to this Runner.
       */
      constructor(name) {
        this.items = [];
        this._name = name;
      }
      /* jsdoc/check-param-names */
      /**
       * Dispatch/Broadcast Runner to all listeners added to the queue.
       * @param {...any} params - (optional) parameters to pass to each listener
       */
      /* jsdoc/check-param-names */
      emit(a0, a1, a2, a3, a4, a5, a6, a7) {
        const { name, items } = this;
        for (let i = 0, len = items.length; i < len; i++) {
          items[i][name](a0, a1, a2, a3, a4, a5, a6, a7);
        }
        return this;
      }
      /**
       * Add a listener to the Runner
       *
       * Runners do not need to have scope or functions passed to them.
       * All that is required is to pass the listening object and ensure that it has contains a function that has the same name
       * as the name provided to the Runner when it was created.
       *
       * Eg A listener passed to this Runner will require a 'complete' function.
       *
       * ```ts
       * import { Runner } from 'pixi.js';
       *
       * const complete = new Runner('complete');
       * ```
       *
       * The scope used will be the object itself.
       * @param {any} item - The object that will be listening.
       */
      add(item) {
        if (item[this._name]) {
          this.remove(item);
          this.items.push(item);
        }
        return this;
      }
      /**
       * Remove a single listener from the dispatch queue.
       * @param {any} item - The listener that you would like to remove.
       */
      remove(item) {
        const index = this.items.indexOf(item);
        if (index !== -1) {
          this.items.splice(index, 1);
        }
        return this;
      }
      /**
       * Check to see if the listener is already in the Runner
       * @param {any} item - The listener that you would like to check.
       */
      contains(item) {
        return this.items.indexOf(item) !== -1;
      }
      /** Remove all listeners from the Runner */
      removeAll() {
        this.items.length = 0;
        return this;
      }
      /** Remove all references, don't use after this. */
      destroy() {
        this.removeAll();
        this.items = null;
        this._name = null;
      }
      /**
       * `true` if there are no this Runner contains no listeners
       * @readonly
       */
      get empty() {
        return this.items.length === 0;
      }
      /**
       * The name of the runner.
       * @readonly
       */
      get name() {
        return this._name;
      }
    }

    "use strict";
    var __defProp$M = Object.defineProperty;
    var __getOwnPropSymbols$O = Object.getOwnPropertySymbols;
    var __hasOwnProp$O = Object.prototype.hasOwnProperty;
    var __propIsEnum$O = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$M = (obj, key, value) => key in obj ? __defProp$M(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$M = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$O.call(b, prop))
          __defNormalProp$M(a, prop, b[prop]);
      if (__getOwnPropSymbols$O)
        for (var prop of __getOwnPropSymbols$O(b)) {
          if (__propIsEnum$O.call(b, prop))
            __defNormalProp$M(a, prop, b[prop]);
        }
      return a;
    };
    const defaultRunners = [
      "init",
      "destroy",
      "contextChange",
      "resolutionChange",
      "resetState",
      "renderEnd",
      "renderStart",
      "render",
      "update",
      "postrender",
      "prerender"
    ];
    const _AbstractRenderer = class _AbstractRenderer extends EventEmitter {
      /**
       * Set up a system with a collection of SystemClasses and runners.
       * Systems are attached dynamically to this class when added.
       * @param config - the config for the system manager
       */
      constructor(config) {
        var _a;
        super();
        /** The current tick of the renderer. */
        this.tick = 0;
        /** @internal */
        this.uid = uid$1("renderer");
        /** @internal */
        this.runners = /* @__PURE__ */ Object.create(null);
        /** @internal */
        this.renderPipes = /* @__PURE__ */ Object.create(null);
        this._initOptions = {};
        this._systemsHash = /* @__PURE__ */ Object.create(null);
        this.type = config.type;
        this.name = config.name;
        this.config = config;
        const combinedRunners = [...defaultRunners, ...(_a = this.config.runners) != null ? _a : []];
        this._addRunners(...combinedRunners);
        this._unsafeEvalCheck();
      }
      /**
       * Initialize the renderer.
       * @param options - The options to use to create the renderer.
       */
      async init(options = {}) {
        const skip = options.skipExtensionImports === true ? true : options.manageImports === false;
        await loadEnvironmentExtensions(skip);
        this._addSystems(this.config.systems);
        this._addPipes(this.config.renderPipes, this.config.renderPipeAdaptors);
        for (const systemName in this._systemsHash) {
          const system = this._systemsHash[systemName];
          const defaultSystemOptions = system.constructor.defaultOptions;
          options = __spreadValues$M(__spreadValues$M({}, defaultSystemOptions), options);
        }
        options = __spreadValues$M(__spreadValues$M({}, _AbstractRenderer.defaultOptions), options);
        this._roundPixels = options.roundPixels ? 1 : 0;
        for (let i = 0; i < this.runners.init.items.length; i++) {
          await this.runners.init.items[i].init(options);
        }
        this._initOptions = options;
      }
      render(args, deprecated) {
        var _a, _b;
        this.tick++;
        let options = args;
        if (options instanceof Container) {
          options = { container: options };
          if (deprecated) {
            deprecation(v8_0_0, "passing a second argument is deprecated, please use render options instead");
            options.target = deprecated.renderTexture;
          }
        }
        options.target || (options.target = this.view.renderTarget);
        if (options.target === this.view.renderTarget) {
          this._lastObjectRendered = options.container;
          (_a = options.clearColor) != null ? _a : options.clearColor = this.background.colorRgba;
          (_b = options.clear) != null ? _b : options.clear = this.background.clearBeforeRender;
        }
        if (options.clearColor) {
          const isRGBAArray = Array.isArray(options.clearColor) && options.clearColor.length === 4;
          options.clearColor = isRGBAArray ? options.clearColor : Color.shared.setValue(options.clearColor).toArray();
        }
        if (!options.transform) {
          options.container.updateLocalTransform();
          options.transform = options.container.localTransform;
        }
        if (!options.container.visible) {
          return;
        }
        options.container.enableRenderGroup();
        this.runners.prerender.emit(options);
        this.runners.renderStart.emit(options);
        this.runners.render.emit(options);
        this.runners.renderEnd.emit(options);
        this.runners.postrender.emit(options);
      }
      /**
       * Resizes the WebGL view to the specified width and height.
       * @param desiredScreenWidth - The desired width of the screen.
       * @param desiredScreenHeight - The desired height of the screen.
       * @param resolution - The resolution / device pixel ratio of the renderer.
       */
      resize(desiredScreenWidth, desiredScreenHeight, resolution) {
        const previousResolution = this.view.resolution;
        this.view.resize(desiredScreenWidth, desiredScreenHeight, resolution);
        this.emit("resize", this.view.screen.width, this.view.screen.height, this.view.resolution);
        if (resolution !== void 0 && resolution !== previousResolution) {
          this.runners.resolutionChange.emit(resolution);
        }
      }
      /**
       * Clears the render target.
       * @param options - The options to use when clearing the render target.
       * @param options.target - The render target to clear.
       * @param options.clearColor - The color to clear with.
       * @param options.clear - The clear mode to use.
       * @advanced
       */
      clear(options = {}) {
        var _a;
        const renderer = this;
        options.target || (options.target = renderer.renderTarget.renderTarget);
        options.clearColor || (options.clearColor = this.background.colorRgba);
        (_a = options.clear) != null ? _a : options.clear = CLEAR.ALL;
        const { clear, clearColor, target } = options;
        Color.shared.setValue(clearColor != null ? clearColor : this.background.colorRgba);
        renderer.renderTarget.clear(target, clear, Color.shared.toArray());
      }
      /** The resolution / device pixel ratio of the renderer. */
      get resolution() {
        return this.view.resolution;
      }
      set resolution(value) {
        this.view.resolution = value;
        this.runners.resolutionChange.emit(value);
      }
      /**
       * Same as view.width, actual number of pixels in the canvas by horizontal.
       * @type {number}
       * @readonly
       * @default 800
       */
      get width() {
        return this.view.texture.frame.width;
      }
      /**
       * Same as view.height, actual number of pixels in the canvas by vertical.
       * @default 600
       */
      get height() {
        return this.view.texture.frame.height;
      }
      // NOTE: this was `view` in v7
      /**
       * The canvas element that everything is drawn to.
       * @type {environment.ICanvas}
       */
      get canvas() {
        return this.view.canvas;
      }
      /**
       * the last object rendered by the renderer. Useful for other plugins like interaction managers
       * @readonly
       */
      get lastObjectRendered() {
        return this._lastObjectRendered;
      }
      /**
       * Flag if we are rendering to the screen vs renderTexture
       * @readonly
       * @default true
       */
      get renderingToScreen() {
        const renderer = this;
        return renderer.renderTarget.renderingToScreen;
      }
      /**
       * Measurements of the screen. (0, 0, screenWidth, screenHeight).
       *
       * Its safe to use as filterArea or hitArea for the whole stage.
       */
      get screen() {
        return this.view.screen;
      }
      /**
       * Create a bunch of runners based of a collection of ids
       * @param runnerIds - the runner ids to add
       */
      _addRunners(...runnerIds) {
        runnerIds.forEach((runnerId) => {
          this.runners[runnerId] = new SystemRunner(runnerId);
        });
      }
      _addSystems(systems) {
        let i;
        for (i in systems) {
          const val = systems[i];
          this._addSystem(val.value, val.name);
        }
      }
      /**
       * Add a new system to the renderer.
       * @param ClassRef - Class reference
       * @param name - Property name for system, if not specified
       *        will use a static `name` property on the class itself. This
       *        name will be assigned as s property on the Renderer so make
       *        sure it doesn't collide with properties on Renderer.
       * @returns Return instance of renderer
       */
      _addSystem(ClassRef, name) {
        const system = new ClassRef(this);
        if (this[name]) {
          throw new Error(`Whoops! The name "${name}" is already in use`);
        }
        this[name] = system;
        this._systemsHash[name] = system;
        for (const i in this.runners) {
          this.runners[i].add(system);
        }
        return this;
      }
      _addPipes(pipes, pipeAdaptors) {
        const adaptors = pipeAdaptors.reduce((acc, adaptor) => {
          acc[adaptor.name] = adaptor.value;
          return acc;
        }, {});
        pipes.forEach((pipe) => {
          const PipeClass = pipe.value;
          const name = pipe.name;
          const Adaptor = adaptors[name];
          this.renderPipes[name] = new PipeClass(
            this,
            Adaptor ? new Adaptor() : null
          );
          this.runners.destroy.add(this.renderPipes[name]);
        });
      }
      destroy(options = false) {
        this.runners.destroy.items.reverse();
        this.runners.destroy.emit(options);
        if (options === true || typeof options === "object" && options.releaseGlobalResources) {
          GlobalResourceRegistry.release();
        }
        Object.values(this.runners).forEach((runner) => {
          runner.destroy();
        });
        this._systemsHash = null;
        this.renderPipes = null;
      }
      /**
       * Generate a texture from a container.
       * @param options - options or container target to use when generating the texture
       * @returns a texture
       */
      generateTexture(options) {
        return this.textureGenerator.generateTexture(options);
      }
      /**
       * Whether the renderer will round coordinates to whole pixels when rendering.
       * Can be overridden on a per scene item basis.
       */
      get roundPixels() {
        return !!this._roundPixels;
      }
      /**
       * Overridable function by `pixi.js/unsafe-eval` to silence
       * throwing an error if platform doesn't support unsafe-evals.
       * @private
       * @ignore
       */
      _unsafeEvalCheck() {
        if (!unsafeEvalSupported()) {
          throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
        }
      }
      /**
       * Resets the rendering state of the renderer.
       * This is useful when you want to use the WebGL context directly and need to ensure PixiJS's internal state
       * stays synchronized. When modifying the WebGL context state externally, calling this method before the next Pixi
       * render will reset all internal caches and ensure it executes correctly.
       *
       * This is particularly useful when combining PixiJS with other rendering engines like Three.js:
       * ```js
       * // Reset Three.js state
       * threeRenderer.resetState();
       *
       * // Render a Three.js scene
       * threeRenderer.render(threeScene, threeCamera);
       *
       * // Reset PixiJS state since Three.js modified the WebGL context
       * pixiRenderer.resetState();
       *
       * // Now render Pixi content
       * pixiRenderer.render(pixiScene);
       * ```
       * @advanced
       */
      resetState() {
        this.runners.resetState.emit();
      }
    };
    /** The default options for the renderer. */
    _AbstractRenderer.defaultOptions = {
      /**
       * Default resolution / device pixel ratio of the renderer.
       * @default 1
       */
      resolution: 1,
      /**
       * Should the `failIfMajorPerformanceCaveat` flag be enabled as a context option used in the `isWebGLSupported`
       * function. If set to true, a WebGL renderer can fail to be created if the browser thinks there could be
       * performance issues when using WebGL.
       *
       * In PixiJS v6 this has changed from true to false by default, to allow WebGL to work in as many
       * scenarios as possible. However, some users may have a poor experience, for example, if a user has a gpu or
       * driver version blacklisted by the
       * browser.
       *
       * If your application requires high performance rendering, you may wish to set this to false.
       * We recommend one of two options if you decide to set this flag to false:
       *
       * 1: Use the Canvas renderer as a fallback in case high performance WebGL is
       *    not supported.
       *
       * 2: Call `isWebGLSupported` (which if found in the utils package) in your code before attempting to create a
       *    PixiJS renderer, and show an error message to the user if the function returns false, explaining that their
       *    device & browser combination does not support high performance WebGL.
       *    This is a much better strategy than trying to create a PixiJS renderer and finding it then fails.
       * @default false
       */
      failIfMajorPerformanceCaveat: false,
      /**
       * Should round pixels be forced when rendering?
       * @default false
       */
      roundPixels: false
    };
    let AbstractRenderer = _AbstractRenderer;

    "use strict";
    let _isWebGLSupported;
    function isWebGLSupported(failIfMajorPerformanceCaveat) {
      if (_isWebGLSupported !== void 0)
        return _isWebGLSupported;
      _isWebGLSupported = (() => {
        var _a;
        const contextOptions = {
          stencil: true,
          failIfMajorPerformanceCaveat: failIfMajorPerformanceCaveat != null ? failIfMajorPerformanceCaveat : AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat
        };
        try {
          if (!DOMAdapter.get().getWebGLRenderingContext()) {
            return false;
          }
          const canvas = DOMAdapter.get().createCanvas();
          let gl = canvas.getContext("webgl", contextOptions);
          const success = !!((_a = gl == null ? void 0 : gl.getContextAttributes()) == null ? void 0 : _a.stencil);
          if (gl) {
            const loseContext = gl.getExtension("WEBGL_lose_context");
            if (loseContext) {
              loseContext.loseContext();
            }
          }
          gl = null;
          return success;
        } catch (_e) {
          return false;
        }
      })();
      return _isWebGLSupported;
    }

    "use strict";
    let _isWebGPUSupported;
    async function isWebGPUSupported(options = {}) {
      if (_isWebGPUSupported !== void 0)
        return _isWebGPUSupported;
      _isWebGPUSupported = await (async () => {
        const gpu = DOMAdapter.get().getNavigator().gpu;
        if (!gpu) {
          return false;
        }
        try {
          const adapter = await gpu.requestAdapter(options);
          await adapter.requestDevice();
          return true;
        } catch (_e) {
          return false;
        }
      })();
      return _isWebGPUSupported;
    }

    "use strict";
    var __defProp$L = Object.defineProperty;
    var __getOwnPropSymbols$N = Object.getOwnPropertySymbols;
    var __hasOwnProp$N = Object.prototype.hasOwnProperty;
    var __propIsEnum$N = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$L = (obj, key, value) => key in obj ? __defProp$L(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$L = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$N.call(b, prop))
          __defNormalProp$L(a, prop, b[prop]);
      if (__getOwnPropSymbols$N)
        for (var prop of __getOwnPropSymbols$N(b)) {
          if (__propIsEnum$N.call(b, prop))
            __defNormalProp$L(a, prop, b[prop]);
        }
      return a;
    };
    const renderPriority = ["webgl", "webgpu", "canvas"];
    async function autoDetectRenderer(options) {
      var _a;
      let preferredOrder = [];
      if (options.preference) {
        preferredOrder.push(options.preference);
        renderPriority.forEach((item) => {
          if (item !== options.preference) {
            preferredOrder.push(item);
          }
        });
      } else {
        preferredOrder = renderPriority.slice();
      }
      let RendererClass;
      let finalOptions = {};
      for (let i = 0; i < preferredOrder.length; i++) {
        const rendererType = preferredOrder[i];
        if (rendererType === "webgpu" && await isWebGPUSupported()) {
          const { WebGPURenderer } = await Promise.resolve().then(function () { return WebGPURenderer$1; });
          RendererClass = WebGPURenderer;
          finalOptions = __spreadValues$L(__spreadValues$L({}, options), options.webgpu);
          break;
        } else if (rendererType === "webgl" && isWebGLSupported(
          (_a = options.failIfMajorPerformanceCaveat) != null ? _a : AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat
        )) {
          const { WebGLRenderer } = await Promise.resolve().then(function () { return WebGLRenderer$1; });
          RendererClass = WebGLRenderer;
          finalOptions = __spreadValues$L(__spreadValues$L({}, options), options.webgl);
          break;
        } else if (rendererType === "canvas") {
          finalOptions = __spreadValues$L({}, options);
          throw new Error("CanvasRenderer is not yet implemented");
        }
      }
      delete finalOptions.webgpu;
      delete finalOptions.webgl;
      if (!RendererClass) {
        throw new Error("No available renderer for the current environment");
      }
      const renderer = new RendererClass();
      await renderer.init(finalOptions);
      return renderer;
    }

    "use strict";
    const DATA_URI = /^\s*data:(?:([\w-]+)\/([\w+.-]+))?(?:;charset=([\w-]+))?(?:;(base64))?,(.*)/i;
    const VERSION = "8.15.0";

    "use strict";
    class ApplicationInitHook {
      static init() {
        var _a;
        (_a = globalThis.__PIXI_APP_INIT__) == null ? void 0 : _a.call(globalThis, this, VERSION);
      }
      static destroy() {
      }
    }
    /** @ignore */
    ApplicationInitHook.extension = ExtensionType.Application;
    class RendererInitHook {
      constructor(renderer) {
        this._renderer = renderer;
      }
      init() {
        var _a;
        (_a = globalThis.__PIXI_RENDERER_INIT__) == null ? void 0 : _a.call(globalThis, this._renderer, VERSION);
      }
      destroy() {
        this._renderer = null;
      }
    }
    /** @ignore */
    RendererInitHook.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "initHook",
      priority: -10
    };

    "use strict";
    var __defProp$K = Object.defineProperty;
    var __getOwnPropSymbols$M = Object.getOwnPropertySymbols;
    var __hasOwnProp$M = Object.prototype.hasOwnProperty;
    var __propIsEnum$M = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$K = (obj, key, value) => key in obj ? __defProp$K(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$K = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$M.call(b, prop))
          __defNormalProp$K(a, prop, b[prop]);
      if (__getOwnPropSymbols$M)
        for (var prop of __getOwnPropSymbols$M(b)) {
          if (__propIsEnum$M.call(b, prop))
            __defNormalProp$K(a, prop, b[prop]);
        }
      return a;
    };
    const _Application = class _Application {
      constructor(...args) {
        /**
         * The root display container for your application.
         * All visual elements should be added to this container or its children.
         * @example
         * ```js
         * // Create a sprite and add it to the stage
         * const sprite = Sprite.from('image.png');
         * app.stage.addChild(sprite);
         *
         * // Create a container for grouping objects
         * const container = new Container();
         * app.stage.addChild(container);
         * ```
         */
        this.stage = new Container();
        if (args[0] !== void 0) {
          deprecation(v8_0_0, "Application constructor options are deprecated, please use Application.init() instead.");
        }
      }
      /**
       * Initializes the PixiJS application with the specified options.
       *
       * This method must be called after creating a new Application instance.
       * @param options - Configuration options for the application and renderer
       * @returns A promise that resolves when initialization is complete
       * @example
       * ```js
       * const app = new Application();
       *
       * // Initialize with custom options
       * await app.init({
       *     width: 800,
       *     height: 600,
       *     backgroundColor: 0x1099bb,
       *     preference: 'webgl', // or 'webgpu'
       * });
       * ```
       */
      async init(options) {
        options = __spreadValues$K({}, options);
        this.stage || (this.stage = new Container());
        this.renderer = await autoDetectRenderer(options);
        _Application._plugins.forEach((plugin) => {
          plugin.init.call(this, options);
        });
      }
      /**
       * Renders the current stage to the screen.
       *
       * When using the default setup with {@link TickerPlugin} (enabled by default), you typically don't need to call
       * this method directly as rendering is handled automatically.
       *
       * Only use this method if you've disabled the {@link TickerPlugin} or need custom
       * render timing control.
       * @example
       * ```js
       * // Example 1: Default setup (TickerPlugin handles rendering)
       * const app = new Application();
       * await app.init();
       * // No need to call render() - TickerPlugin handles it
       *
       * // Example 2: Custom rendering loop (if TickerPlugin is disabled)
       * const app = new Application();
       * await app.init({ autoStart: false }); // Disable automatic rendering
       *
       * function animate() {
       *     app.render();
       *     requestAnimationFrame(animate);
       * }
       * animate();
       * ```
       */
      render() {
        this.renderer.render({ container: this.stage });
      }
      /**
       * Reference to the renderer's canvas element. This is the HTML element
       * that displays your application's graphics.
       * @readonly
       * @type {HTMLCanvasElement}
       * @example
       * ```js
       * // Create a new application
       * const app = new Application();
       * // Initialize the application
       * await app.init({...});
       * // Add canvas to the page
       * document.body.appendChild(app.canvas);
       *
       * // Access the canvas directly
       * console.log(app.canvas); // HTMLCanvasElement
       * ```
       */
      get canvas() {
        return this.renderer.canvas;
      }
      /**
       * Reference to the renderer's canvas element.
       * @type {HTMLCanvasElement}
       * @deprecated since 8.0.0
       * @see {@link Application#canvas}
       */
      get view() {
        deprecation(v8_0_0, "Application.view is deprecated, please use Application.canvas instead.");
        return this.renderer.canvas;
      }
      /**
       * Reference to the renderer's screen rectangle. This represents the visible area of your application.
       *
       * It's commonly used for:
       * - Setting filter areas for full-screen effects
       * - Defining hit areas for screen-wide interaction
       * - Determining the visible bounds of your application
       * @readonly
       * @example
       * ```js
       * // Use as filter area for a full-screen effect
       * const blurFilter = new BlurFilter();
       * sprite.filterArea = app.screen;
       *
       * // Use as hit area for screen-wide interaction
       * const screenSprite = new Sprite();
       * screenSprite.hitArea = app.screen;
       *
       * // Get screen dimensions
       * console.log(app.screen.width, app.screen.height);
       * ```
       * @see {@link Rectangle} For all available properties and methods
       */
      get screen() {
        return this.renderer.screen;
      }
      /**
       * Destroys the application and all of its resources.
       *
       * This method should be called when you want to completely
       * clean up the application and free all associated memory.
       * @param rendererDestroyOptions - Options for destroying the renderer:
       *  - `false` or `undefined`: Preserves the canvas element (default)
       *  - `true`: Removes the canvas element
       *  - `{ removeView: boolean }`: Object with removeView property to control canvas removal
       * @param options - Options for destroying the application:
       *  - `false` or `undefined`: Basic cleanup (default)
       *  - `true`: Complete cleanup including children
       *  - Detailed options object:
       *    - `children`: Remove children
       *    - `texture`: Destroy textures
       *    - `textureSource`: Destroy texture sources
       *    - `context`: Destroy WebGL context
       * @example
       * ```js
       * // Basic cleanup
       * app.destroy();
       *
       * // Remove canvas and do complete cleanup
       * app.destroy(true, true);
       *
       * // Remove canvas with explicit options
       * app.destroy({ removeView: true }, true);
       *
       * // Detailed cleanup with specific options
       * app.destroy(
       *     { removeView: true },
       *     {
       *         children: true,
       *         texture: true,
       *         textureSource: true,
       *         context: true
       *     }
       * );
       * ```
       * > [!WARNING] After calling destroy, the application instance should no longer be used.
       * > All properties will be null and further operations will throw errors.
       */
      destroy(rendererDestroyOptions = false, options = false) {
        const plugins = _Application._plugins.slice(0);
        plugins.reverse();
        plugins.forEach((plugin) => {
          plugin.destroy.call(this);
        });
        this.stage.destroy(options);
        this.stage = null;
        this.renderer.destroy(rendererDestroyOptions);
        this.renderer = null;
      }
    };
    /**
     * Collection of installed plugins.
     * @internal
     */
    _Application._plugins = [];
    let Application = _Application;
    extensions.handleByList(ExtensionType.Application, Application._plugins);
    extensions.add(ApplicationInitHook);

    "use strict";

    "use strict";

    "use strict";
    class BitmapFont extends AbstractBitmapFont {
      constructor(options, url) {
        var _a;
        super();
        const { textures, data } = options;
        Object.keys(data.pages).forEach((key) => {
          const pageData = data.pages[parseInt(key, 10)];
          const texture = textures[pageData.id];
          this.pages.push({ texture });
        });
        Object.keys(data.chars).forEach((key) => {
          var _a2;
          const charData = data.chars[key];
          const {
            frame: textureFrame,
            source: textureSource,
            rotate: textureRotate
          } = textures[charData.page];
          const frame = groupD8.transformRectCoords(
            charData,
            textureFrame,
            textureRotate,
            new Rectangle()
          );
          const texture = new Texture({
            frame,
            orig: new Rectangle(0, 0, charData.width, charData.height),
            source: textureSource,
            rotate: textureRotate
          });
          this.chars[key] = {
            id: key.codePointAt(0),
            xOffset: charData.xOffset,
            yOffset: charData.yOffset,
            xAdvance: charData.xAdvance,
            kerning: (_a2 = charData.kerning) != null ? _a2 : {},
            texture
          };
        });
        this.baseRenderedFontSize = data.fontSize;
        this.baseMeasurementFontSize = data.fontSize;
        this.fontMetrics = {
          ascent: 0,
          descent: 0,
          fontSize: data.fontSize
        };
        this.baseLineOffset = data.baseLineOffset;
        this.lineHeight = data.lineHeight;
        this.fontFamily = data.fontFamily;
        this.distanceField = (_a = data.distanceField) != null ? _a : {
          type: "none",
          range: 0
        };
        this.url = url;
      }
      /** Destroys the BitmapFont object. */
      destroy() {
        super.destroy();
        for (let i = 0; i < this.pages.length; i++) {
          const { texture } = this.pages[i];
          texture.destroy(true);
        }
        this.pages = null;
      }
      /**
       * Generates and installs a bitmap font with the specified options.
       * The font will be cached and available for use in BitmapText objects.
       * @param options - Setup options for font generation
       * @returns Installed font instance
       * @example
       * ```ts
       * // Install a basic font
       * BitmapFont.install({
       *     name: 'Title',
       *     style: {
       *         fontFamily: 'Arial',
       *         fontSize: 32,
       *         fill: '#ffffff'
       *     }
       * });
       *
       * // Install with advanced options
       * BitmapFont.install({
       *     name: 'Custom',
       *     style: {
       *         fontFamily: 'Arial',
       *         fontSize: 24,
       *         fill: '#00ff00',
       *         stroke: { color: '#000000', width: 2 }
       *     },
       *     chars: [['a', 'z'], ['A', 'Z'], ['0', '9']],
       *     resolution: 2,
       *     padding: 4,
       *     textureStyle: {
       *         scaleMode: 'nearest'
       *     }
       * });
       * ```
       */
      static install(options) {
        BitmapFontManager.install(options);
      }
      /**
       * Uninstalls a bitmap font from the cache.
       * This frees up memory and resources associated with the font.
       * @param name - The name of the bitmap font to uninstall
       * @example
       * ```ts
       * // Remove a font when it's no longer needed
       * BitmapFont.uninstall('MyCustomFont');
       *
       * // Clear multiple fonts
       * ['Title', 'Heading', 'Body'].forEach(BitmapFont.uninstall);
       * ```
       */
      static uninstall(name) {
        BitmapFontManager.uninstall(name);
      }
    }

    "use strict";
    const bitmapFontTextParser = {
      test(data) {
        return typeof data === "string" && data.startsWith("info face=");
      },
      parse(txt) {
        var _a, _b, _c;
        const items = txt.match(/^[a-z]+\s+.+$/gm);
        const rawData = {
          info: [],
          common: [],
          page: [],
          char: [],
          chars: [],
          kerning: [],
          kernings: [],
          distanceField: []
        };
        for (const i in items) {
          const name = items[i].match(/^[a-z]+/gm)[0];
          const attributeList = items[i].match(/[a-zA-Z]+=([^\s"']+|"([^"]*)")/gm);
          const itemData = {};
          for (const i2 in attributeList) {
            const split = attributeList[i2].split("=");
            const key = split[0];
            const strValue = split[1].replace(/"/gm, "");
            const floatValue = parseFloat(strValue);
            const value = isNaN(floatValue) ? strValue : floatValue;
            itemData[key] = value;
          }
          rawData[name].push(itemData);
        }
        const font = {
          chars: {},
          pages: [],
          lineHeight: 0,
          fontSize: 0,
          fontFamily: "",
          distanceField: null,
          baseLineOffset: 0
        };
        const [info] = rawData.info;
        const [common] = rawData.common;
        const [distanceField] = (_a = rawData.distanceField) != null ? _a : [];
        if (distanceField) {
          font.distanceField = {
            range: parseInt(distanceField.distanceRange, 10),
            type: distanceField.fieldType
          };
        }
        font.fontSize = parseInt(info.size, 10);
        font.fontFamily = info.face;
        font.lineHeight = parseInt(common.lineHeight, 10);
        const page = rawData.page;
        for (let i = 0; i < page.length; i++) {
          font.pages.push({
            id: parseInt(page[i].id, 10) || 0,
            file: page[i].file
          });
        }
        const map = {};
        font.baseLineOffset = font.lineHeight - parseInt(common.base, 10);
        const char = rawData.char;
        for (let i = 0; i < char.length; i++) {
          const charNode = char[i];
          const id = parseInt(charNode.id, 10);
          let letter = (_c = (_b = charNode.letter) != null ? _b : charNode.char) != null ? _c : String.fromCharCode(id);
          if (letter === "space")
            letter = " ";
          map[id] = letter;
          font.chars[letter] = {
            id,
            // texture deets..
            page: parseInt(charNode.page, 10) || 0,
            x: parseInt(charNode.x, 10),
            y: parseInt(charNode.y, 10),
            width: parseInt(charNode.width, 10),
            height: parseInt(charNode.height, 10),
            xOffset: parseInt(charNode.xoffset, 10),
            yOffset: parseInt(charNode.yoffset, 10),
            xAdvance: parseInt(charNode.xadvance, 10),
            kerning: {}
          };
        }
        const kerning = rawData.kerning || [];
        for (let i = 0; i < kerning.length; i++) {
          const first = parseInt(kerning[i].first, 10);
          const second = parseInt(kerning[i].second, 10);
          const amount = parseInt(kerning[i].amount, 10);
          font.chars[map[second]].kerning[map[first]] = amount;
        }
        return font;
      }
    };

    "use strict";
    const bitmapFontXMLParser = {
      test(data) {
        const xml = data;
        return typeof xml !== "string" && "getElementsByTagName" in xml && xml.getElementsByTagName("page").length && xml.getElementsByTagName("info")[0].getAttribute("face") !== null;
      },
      parse(xml) {
        var _a, _b;
        const data = {
          chars: {},
          pages: [],
          lineHeight: 0,
          fontSize: 0,
          fontFamily: "",
          distanceField: null,
          baseLineOffset: 0
        };
        const info = xml.getElementsByTagName("info")[0];
        const common = xml.getElementsByTagName("common")[0];
        const distanceField = xml.getElementsByTagName("distanceField")[0];
        if (distanceField) {
          data.distanceField = {
            type: distanceField.getAttribute("fieldType"),
            range: parseInt(distanceField.getAttribute("distanceRange"), 10)
          };
        }
        const page = xml.getElementsByTagName("page");
        const char = xml.getElementsByTagName("char");
        const kerning = xml.getElementsByTagName("kerning");
        data.fontSize = parseInt(info.getAttribute("size"), 10);
        data.fontFamily = info.getAttribute("face");
        data.lineHeight = parseInt(common.getAttribute("lineHeight"), 10);
        for (let i = 0; i < page.length; i++) {
          data.pages.push({
            id: parseInt(page[i].getAttribute("id"), 10) || 0,
            file: page[i].getAttribute("file")
          });
        }
        const map = {};
        data.baseLineOffset = data.lineHeight - parseInt(common.getAttribute("base"), 10);
        for (let i = 0; i < char.length; i++) {
          const charNode = char[i];
          const id = parseInt(charNode.getAttribute("id"), 10);
          let letter = (_b = (_a = charNode.getAttribute("letter")) != null ? _a : charNode.getAttribute("char")) != null ? _b : String.fromCharCode(id);
          if (letter === "space")
            letter = " ";
          map[id] = letter;
          data.chars[letter] = {
            id,
            // texture deets..
            page: parseInt(charNode.getAttribute("page"), 10) || 0,
            x: parseInt(charNode.getAttribute("x"), 10),
            y: parseInt(charNode.getAttribute("y"), 10),
            width: parseInt(charNode.getAttribute("width"), 10),
            height: parseInt(charNode.getAttribute("height"), 10),
            // render deets..
            xOffset: parseInt(charNode.getAttribute("xoffset"), 10),
            yOffset: parseInt(charNode.getAttribute("yoffset"), 10),
            // + baseLineOffset,
            xAdvance: parseInt(charNode.getAttribute("xadvance"), 10),
            kerning: {}
          };
        }
        for (let i = 0; i < kerning.length; i++) {
          const first = parseInt(kerning[i].getAttribute("first"), 10);
          const second = parseInt(kerning[i].getAttribute("second"), 10);
          const amount = parseInt(kerning[i].getAttribute("amount"), 10);
          data.chars[map[second]].kerning[map[first]] = amount;
        }
        return data;
      }
    };

    "use strict";
    const bitmapFontXMLStringParser = {
      test(data) {
        if (typeof data === "string" && data.match(/<font(\s|>)/)) {
          return bitmapFontXMLParser.test(DOMAdapter.get().parseXML(data));
        }
        return false;
      },
      parse(data) {
        return bitmapFontXMLParser.parse(DOMAdapter.get().parseXML(data));
      }
    };

    "use strict";
    const validExtensions = [".xml", ".fnt"];
    const bitmapFontCachePlugin = {
      extension: {
        type: ExtensionType.CacheParser,
        name: "cacheBitmapFont"
      },
      test: (asset) => asset instanceof BitmapFont,
      getCacheableAssets(keys, asset) {
        const out = {};
        keys.forEach((key) => {
          out[key] = asset;
          out[`${key}-bitmap`] = asset;
        });
        out[`${asset.fontFamily}-bitmap`] = asset;
        return out;
      }
    };
    const loadBitmapFont = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.Normal
      },
      /** used for deprecation purposes */
      name: "loadBitmapFont",
      id: "bitmap-font",
      test(url) {
        return validExtensions.includes(path.extname(url).toLowerCase());
      },
      async testParse(data) {
        return bitmapFontTextParser.test(data) || bitmapFontXMLStringParser.test(data);
      },
      async parse(asset, data, loader) {
        const bitmapFontData = bitmapFontTextParser.test(asset) ? bitmapFontTextParser.parse(asset) : bitmapFontXMLStringParser.parse(asset);
        const { src } = data;
        const { pages } = bitmapFontData;
        const textureUrls = [];
        const textureOptions = bitmapFontData.distanceField ? {
          scaleMode: "linear",
          alphaMode: "premultiply-alpha-on-upload",
          autoGenerateMipmaps: false,
          resolution: 1
        } : {};
        for (let i = 0; i < pages.length; ++i) {
          const pageFile = pages[i].file;
          let imagePath = path.join(path.dirname(src), pageFile);
          imagePath = copySearchParams(imagePath, src);
          textureUrls.push({
            src: imagePath,
            data: textureOptions
          });
        }
        const loadedTextures = await loader.load(textureUrls);
        const textures = textureUrls.map((url) => loadedTextures[url.src]);
        const bitmapFont = new BitmapFont({
          data: bitmapFontData,
          textures
        }, src);
        return bitmapFont;
      },
      async load(url, _options) {
        const response = await DOMAdapter.get().fetch(url);
        return await response.text();
      },
      async unload(bitmapFont, _resolvedAsset, loader) {
        await Promise.all(bitmapFont.pages.map((page) => loader.unload(page.texture.source._sourceOrigin)));
        bitmapFont.destroy();
      }
    };

    "use strict";
    class BackgroundLoader {
      /**
       * @param loader
       * @param verbose - should the loader log to the console
       */
      constructor(loader, verbose = false) {
        this._loader = loader;
        this._assetList = [];
        this._isLoading = false;
        this._maxConcurrent = 1;
        this.verbose = verbose;
      }
      /**
       * Adds assets to the background loading queue. Assets are loaded one at a time to minimize
       * performance impact.
       * @param assetUrls - Array of resolved assets to load in the background
       * @example
       * ```ts
       * // Add assets to background load queue
       * backgroundLoader.add([
       *     { src: 'images/level1/bg.png' },
       *     { src: 'images/level1/characters.json' }
       * ]);
       *
       * // Assets will load sequentially in the background
       * // The loader automatically pauses when high-priority loads occur
       * // e.g. Assets.load() is called
       * ```
       * @remarks
       * - Assets are loaded one at a time to minimize performance impact
       * - Loading automatically pauses when Assets.load() is called
       * - No progress tracking is available for background loading
       * - Assets are cached as they complete loading
       * @internal
       */
      add(assetUrls) {
        assetUrls.forEach((a) => {
          this._assetList.push(a);
        });
        if (this.verbose) {
          console.log("[BackgroundLoader] assets: ", this._assetList);
        }
        if (this._isActive && !this._isLoading) {
          void this._next();
        }
      }
      /**
       * Loads the next set of assets. Will try to load as many assets as it can at the same time.
       *
       * The max assets it will try to load at one time will be 4.
       */
      async _next() {
        if (this._assetList.length && this._isActive) {
          this._isLoading = true;
          const toLoad = [];
          const toLoadAmount = Math.min(this._assetList.length, this._maxConcurrent);
          for (let i = 0; i < toLoadAmount; i++) {
            toLoad.push(this._assetList.pop());
          }
          await this._loader.load(toLoad);
          this._isLoading = false;
          void this._next();
        }
      }
      /**
       * Controls the active state of the background loader. When active, the loader will
       * continue processing its queue. When inactive, loading is paused.
       * @returns Whether the background loader is currently active
       * @example
       * ```ts
       * // Pause background loading
       * backgroundLoader.active = false;
       *
       * // Resume background loading
       * backgroundLoader.active = true;
       *
       * // Check current state
       * console.log(backgroundLoader.active); // true/false
       *
       * // Common use case: Pause during intensive operations
       * backgroundLoader.active = false;  // Pause background loading
       * ... // Perform high-priority tasks
       * backgroundLoader.active = true;   // Resume background loading
       * ```
       * @remarks
       * - Setting to true resumes loading immediately
       * - Setting to false pauses after current asset completes
       * - Background loading is automatically paused during `Assets.load()`
       * - Assets already being loaded will complete even when set to false
       */
      get active() {
        return this._isActive;
      }
      set active(value) {
        if (this._isActive === value)
          return;
        this._isActive = value;
        if (value && !this._isLoading) {
          void this._next();
        }
      }
    }

    "use strict";
    const cacheTextureArray = {
      extension: {
        type: ExtensionType.CacheParser,
        name: "cacheTextureArray"
      },
      test: (asset) => Array.isArray(asset) && asset.every((t) => t instanceof Texture),
      getCacheableAssets: (keys, asset) => {
        const out = {};
        keys.forEach((key) => {
          asset.forEach((item, i) => {
            out[key + (i === 0 ? "" : i + 1)] = item;
          });
        });
        return out;
      }
    };

    "use strict";
    async function testImageFormat(imageData) {
      if ("Image" in globalThis) {
        return new Promise((resolve) => {
          const image = new Image();
          image.onload = () => {
            resolve(true);
          };
          image.onerror = () => {
            resolve(false);
          };
          image.src = imageData;
        });
      }
      if ("createImageBitmap" in globalThis && "fetch" in globalThis) {
        try {
          const blob = await (await fetch(imageData)).blob();
          await createImageBitmap(blob);
        } catch (_e) {
          return false;
        }
        return true;
      }
      return false;
    }

    "use strict";
    const detectAvif = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 1
      },
      test: async () => testImageFormat(
        // eslint-disable-next-line max-len
        "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
      ),
      add: async (formats) => [...formats, "avif"],
      remove: async (formats) => formats.filter((f) => f !== "avif")
    };

    "use strict";
    const imageFormats = ["png", "jpg", "jpeg"];
    const detectDefaults = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: -1
      },
      test: () => Promise.resolve(true),
      add: async (formats) => [...formats, ...imageFormats],
      remove: async (formats) => formats.filter((f) => !imageFormats.includes(f))
    };

    "use strict";
    const inWorker = "WorkerGlobalScope" in globalThis && globalThis instanceof globalThis.WorkerGlobalScope;
    function testVideoFormat(mimeType) {
      if (inWorker) {
        return false;
      }
      const video = document.createElement("video");
      return video.canPlayType(mimeType) !== "";
    }

    "use strict";
    const detectMp4 = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 0
      },
      test: async () => testVideoFormat("video/mp4"),
      add: async (formats) => [...formats, "mp4", "m4v"],
      remove: async (formats) => formats.filter((f) => f !== "mp4" && f !== "m4v")
    };

    "use strict";
    const detectOgv = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 0
      },
      test: async () => testVideoFormat("video/ogg"),
      add: async (formats) => [...formats, "ogv"],
      remove: async (formats) => formats.filter((f) => f !== "ogv")
    };

    "use strict";
    const detectWebm = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 0
      },
      test: async () => testVideoFormat("video/webm"),
      add: async (formats) => [...formats, "webm"],
      remove: async (formats) => formats.filter((f) => f !== "webm")
    };

    "use strict";
    const detectWebp = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 0
      },
      test: async () => testImageFormat(
        "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA="
      ),
      add: async (formats) => [...formats, "webp"],
      remove: async (formats) => formats.filter((f) => f !== "webp")
    };

    "use strict";
    var __defProp$J = Object.defineProperty;
    var __defProps$m = Object.defineProperties;
    var __getOwnPropDescs$m = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$L = Object.getOwnPropertySymbols;
    var __hasOwnProp$L = Object.prototype.hasOwnProperty;
    var __propIsEnum$L = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$J = (obj, key, value) => key in obj ? __defProp$J(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$J = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$L.call(b, prop))
          __defNormalProp$J(a, prop, b[prop]);
      if (__getOwnPropSymbols$L)
        for (var prop of __getOwnPropSymbols$L(b)) {
          if (__propIsEnum$L.call(b, prop))
            __defNormalProp$J(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$m = (a, b) => __defProps$m(a, __getOwnPropDescs$m(b));
    const _Loader = class _Loader {
      constructor() {
        /**
         * Options for loading assets with the loader.
         * These options will be used as defaults for all load calls made with this loader instance.
         * They can be overridden by passing options directly to the load method.
         * @example
         * ```ts
         * // Create a loader with custom default options
         * const loader = new Loader();
         * loader.loadOptions = {
         *   strategy: 'skip', // Default strategy to 'skip'
         *   retryCount: 5,   // Default retry count to 5
         *   retryDelay: 500, // Default retry delay to 500ms
         * };
         *
         * // This load call will use the loader's default options
         * await loader.load('image1.png');
         */
        this.loadOptions = __spreadValues$J({}, _Loader.defaultOptions);
        this._parsers = [];
        this._parsersValidated = false;
        /**
         * All loader parsers registered
         * @type {assets.LoaderParser[]}
         */
        this.parsers = new Proxy(this._parsers, {
          set: (target, key, value) => {
            this._parsersValidated = false;
            target[key] = value;
            return true;
          }
        });
        /** Cache loading promises that ae currently active */
        this.promiseCache = {};
      }
      /** function used for testing */
      reset() {
        this._parsersValidated = false;
        this.promiseCache = {};
      }
      /**
       * Used internally to generate a promise for the asset to be loaded.
       * @param url - The URL to be loaded
       * @param data - any custom additional information relevant to the asset being loaded
       * @returns - a promise that will resolve to an Asset for example a Texture of a JSON object
       */
      _getLoadPromiseAndParser(url, data) {
        const result = {
          promise: null,
          parser: null
        };
        result.promise = (async () => {
          var _a, _b;
          let asset = null;
          let parser = null;
          if (data.parser || data.loadParser) {
            parser = this._parserHash[data.parser || data.loadParser];
            if (data.loadParser) {
              warn(
                `[Assets] "loadParser" is deprecated, use "parser" instead for ${url}`
              );
            }
            if (!parser) {
              warn(
                `[Assets] specified load parser "${data.parser || data.loadParser}" not found while loading ${url}`
              );
            }
          }
          if (!parser) {
            for (let i = 0; i < this.parsers.length; i++) {
              const parserX = this.parsers[i];
              if (parserX.load && ((_a = parserX.test) == null ? void 0 : _a.call(parserX, url, data, this))) {
                parser = parserX;
                break;
              }
            }
            if (!parser) {
              warn(`[Assets] ${url} could not be loaded as we don't know how to parse it, ensure the correct parser has been added`);
              return null;
            }
          }
          asset = await parser.load(url, data, this);
          result.parser = parser;
          for (let i = 0; i < this.parsers.length; i++) {
            const parser2 = this.parsers[i];
            if (parser2.parse) {
              if (parser2.parse && await ((_b = parser2.testParse) == null ? void 0 : _b.call(parser2, asset, data, this))) {
                asset = await parser2.parse(asset, data, this) || asset;
                result.parser = parser2;
              }
            }
          }
          return asset;
        })();
        return result;
      }
      async load(assetsToLoadIn, onProgressOrOptions) {
        if (!this._parsersValidated) {
          this._validateParsers();
        }
        const options = typeof onProgressOrOptions === "function" ? __spreadProps$m(__spreadValues$J(__spreadValues$J({}, _Loader.defaultOptions), this.loadOptions), { onProgress: onProgressOrOptions }) : __spreadValues$J(__spreadValues$J(__spreadValues$J({}, _Loader.defaultOptions), this.loadOptions), onProgressOrOptions || {});
        const { onProgress, onError, strategy, retryCount, retryDelay } = options;
        let count = 0;
        const assets = {};
        const singleAsset = isSingleItem(assetsToLoadIn);
        const assetsToLoad = convertToList(assetsToLoadIn, (item) => ({
          alias: [item],
          src: item,
          data: {}
        }));
        const total = assetsToLoad.reduce((sum, asset) => sum + (asset.progressSize || 1), 0);
        const promises = assetsToLoad.map(async (asset) => {
          const url = path.toAbsolute(asset.src);
          if (assets[asset.src])
            return;
          await this._loadAssetWithRetry(url, asset, { onProgress, onError, strategy, retryCount, retryDelay }, assets);
          count += asset.progressSize || 1;
          if (onProgress)
            onProgress(count / total);
        });
        await Promise.all(promises);
        return singleAsset ? assets[assetsToLoad[0].src] : assets;
      }
      /**
       * Unloads one or more assets. Any unloaded assets will be destroyed, freeing up memory for your app.
       * The parser that created the asset, will be the one that unloads it.
       * @example
       * // Single asset:
       * const asset = await Loader.load('cool.png');
       *
       * await Loader.unload('cool.png');
       *
       * console.log(asset.destroyed); // true
       * @param assetsToUnloadIn - urls that you want to unload, or a single one!
       */
      async unload(assetsToUnloadIn) {
        const assetsToUnload = convertToList(assetsToUnloadIn, (item) => ({
          alias: [item],
          src: item
        }));
        const promises = assetsToUnload.map(async (asset) => {
          var _a, _b;
          const url = path.toAbsolute(asset.src);
          const loadPromise = this.promiseCache[url];
          if (loadPromise) {
            const loadedAsset = await loadPromise.promise;
            delete this.promiseCache[url];
            await ((_b = (_a = loadPromise.parser) == null ? void 0 : _a.unload) == null ? void 0 : _b.call(_a, loadedAsset, asset, this));
          }
        });
        await Promise.all(promises);
      }
      /** validates our parsers, right now it only checks for name conflicts but we can add more here as required! */
      _validateParsers() {
        this._parsersValidated = true;
        this._parserHash = this._parsers.filter((parser) => parser.name || parser.id).reduce((hash, parser) => {
          if (!parser.name && !parser.id) {
            warn(`[Assets] parser should have an id`);
          } else if (hash[parser.name] || hash[parser.id]) {
            warn(`[Assets] parser id conflict "${parser.id}"`);
          }
          hash[parser.name] = parser;
          if (parser.id)
            hash[parser.id] = parser;
          return hash;
        }, {});
      }
      async _loadAssetWithRetry(url, asset, options, assets) {
        let attempt = 0;
        const { onError, strategy, retryCount, retryDelay } = options;
        const wait = (ms) => new Promise((r) => setTimeout(r, ms));
        while (true) {
          try {
            if (!this.promiseCache[url]) {
              this.promiseCache[url] = this._getLoadPromiseAndParser(url, asset);
            }
            assets[asset.src] = await this.promiseCache[url].promise;
            return;
          } catch (e) {
            delete this.promiseCache[url];
            delete assets[asset.src];
            attempt++;
            const isLast = strategy !== "retry" || attempt > retryCount;
            if (strategy === "retry" && !isLast) {
              if (onError)
                onError(e, asset);
              await wait(retryDelay);
              continue;
            }
            if (strategy === "skip") {
              if (onError)
                onError(e, asset);
              return;
            }
            if (onError)
              onError(e, asset);
            const error = new Error(`[Loader.load] Failed to load ${url}.
${e}`);
            if (e instanceof Error && e.stack) {
              error.stack = e.stack;
            }
            throw error;
          }
        }
      }
    };
    /**
     * Default options for loading assets
     * @example
     * ```ts
     * // Change default load options globally
     * Loader.defaultOptions = {
     *   strategy: 'skip', // Change default strategy to 'skip'
     *   retryCount: 5,   // Change default retry count to 5
     *   retryDelay: 500, // Change default retry delay to 500ms
     * };
     * ```
     */
    _Loader.defaultOptions = {
      onProgress: void 0,
      onError: void 0,
      strategy: "throw",
      retryCount: 3,
      retryDelay: 250
    };
    let Loader = _Loader;

    "use strict";
    function checkDataUrl(url, mimes) {
      if (Array.isArray(mimes)) {
        for (const mime of mimes) {
          if (url.startsWith(`data:${mime}`))
            return true;
        }
        return false;
      }
      return url.startsWith(`data:${mimes}`);
    }

    "use strict";
    function checkExtension(url, extension) {
      const tempURL = url.split("?")[0];
      const ext = path.extname(tempURL).toLowerCase();
      if (Array.isArray(extension)) {
        return extension.includes(ext);
      }
      return ext === extension;
    }

    "use strict";
    const validJSONExtension = ".json";
    const validJSONMIME = "application/json";
    const loadJson = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.Low
      },
      /** used for deprecation purposes */
      name: "loadJson",
      id: "json",
      test(url) {
        return checkDataUrl(url, validJSONMIME) || checkExtension(url, validJSONExtension);
      },
      async load(url) {
        const response = await DOMAdapter.get().fetch(url);
        const json = await response.json();
        return json;
      }
    };

    "use strict";
    const validTXTExtension = ".txt";
    const validTXTMIME = "text/plain";
    const loadTxt = {
      /** used for deprecation purposes */
      name: "loadTxt",
      id: "text",
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.Low,
        name: "loadTxt"
      },
      test(url) {
        return checkDataUrl(url, validTXTMIME) || checkExtension(url, validTXTExtension);
      },
      async load(url) {
        const response = await DOMAdapter.get().fetch(url);
        const txt = await response.text();
        return txt;
      }
    };

    "use strict";
    var __defProp$I = Object.defineProperty;
    var __defProps$l = Object.defineProperties;
    var __getOwnPropDescs$l = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$K = Object.getOwnPropertySymbols;
    var __hasOwnProp$K = Object.prototype.hasOwnProperty;
    var __propIsEnum$K = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$I = (obj, key, value) => key in obj ? __defProp$I(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$I = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$K.call(b, prop))
          __defNormalProp$I(a, prop, b[prop]);
      if (__getOwnPropSymbols$K)
        for (var prop of __getOwnPropSymbols$K(b)) {
          if (__propIsEnum$K.call(b, prop))
            __defNormalProp$I(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$l = (a, b) => __defProps$l(a, __getOwnPropDescs$l(b));
    const validWeights = [
      "normal",
      "bold",
      "100",
      "200",
      "300",
      "400",
      "500",
      "600",
      "700",
      "800",
      "900"
    ];
    const validFontExtensions = [".ttf", ".otf", ".woff", ".woff2"];
    const validFontMIMEs = [
      "font/ttf",
      "font/otf",
      "font/woff",
      "font/woff2"
    ];
    const CSS_IDENT_TOKEN_REGEX = /^(--|-?[A-Z_])[0-9A-Z_-]*$/i;
    function getFontFamilyName(url) {
      const ext = path.extname(url);
      const name = path.basename(url, ext);
      const nameWithSpaces = name.replace(/(-|_)/g, " ");
      const nameTokens = nameWithSpaces.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1));
      let valid = nameTokens.length > 0;
      for (const token of nameTokens) {
        if (!token.match(CSS_IDENT_TOKEN_REGEX)) {
          valid = false;
          break;
        }
      }
      let fontFamilyName = nameTokens.join(" ");
      if (!valid) {
        fontFamilyName = `"${fontFamilyName.replace(/[\\"]/g, "\\$&")}"`;
      }
      return fontFamilyName;
    }
    const validURICharactersRegex = /^[0-9A-Za-z%:/?#\[\]@!\$&'()\*\+,;=\-._~]*$/;
    function encodeURIWhenNeeded(uri) {
      if (validURICharactersRegex.test(uri)) {
        return uri;
      }
      return encodeURI(uri);
    }
    const loadWebFont = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.Low
      },
      /** used for deprecation purposes */
      name: "loadWebFont",
      id: "web-font",
      test(url) {
        return checkDataUrl(url, validFontMIMEs) || checkExtension(url, validFontExtensions);
      },
      async load(url, options) {
        var _a, _b, _c, _d, _e, _f;
        const fonts = DOMAdapter.get().getFontFaceSet();
        if (fonts) {
          const fontFaces = [];
          const name = (_b = (_a = options.data) == null ? void 0 : _a.family) != null ? _b : getFontFamilyName(url);
          const weights = (_e = (_d = (_c = options.data) == null ? void 0 : _c.weights) == null ? void 0 : _d.filter((weight) => validWeights.includes(weight))) != null ? _e : ["normal"];
          const data = (_f = options.data) != null ? _f : {};
          for (let i = 0; i < weights.length; i++) {
            const weight = weights[i];
            const font = new FontFace(name, `url(${encodeURIWhenNeeded(url)})`, __spreadProps$l(__spreadValues$I({}, data), {
              weight
            }));
            await font.load();
            fonts.add(font);
            fontFaces.push(font);
          }
          if (Cache.has(`${name}-and-url`)) {
            const cached = Cache.get(`${name}-and-url`);
            cached.entries.push({ url, faces: fontFaces });
          } else {
            Cache.set(`${name}-and-url`, {
              entries: [{ url, faces: fontFaces }]
            });
          }
          return fontFaces.length === 1 ? fontFaces[0] : fontFaces;
        }
        warn("[loadWebFont] FontFace API is not supported. Skipping loading font");
        return null;
      },
      unload(font) {
        const fonts = Array.isArray(font) ? font : [font];
        const fontFamily = fonts[0].family;
        const cached = Cache.get(`${fontFamily}-and-url`);
        const entry = cached.entries.find((f) => f.faces.some((t) => fonts.indexOf(t) !== -1));
        entry.faces = entry.faces.filter((f) => fonts.indexOf(f) === -1);
        if (entry.faces.length === 0) {
          cached.entries = cached.entries.filter((f) => f !== entry);
        }
        fonts.forEach((t) => {
          DOMAdapter.get().getFontFaceSet().delete(t);
        });
        if (cached.entries.length === 0) {
          Cache.remove(`${fontFamily}-and-url`);
        }
      }
    };

    "use strict";
    function getResolutionOfUrl(url, defaultValue = 1) {
      var _a;
      const resolution = (_a = Resolver.RETINA_PREFIX) == null ? void 0 : _a.exec(url);
      if (resolution) {
        return parseFloat(resolution[1]);
      }
      return defaultValue;
    }

    "use strict";
    function createTexture(source, loader, url) {
      source.label = url;
      source._sourceOrigin = url;
      const texture = new Texture({
        source,
        label: url
      });
      const unload = () => {
        delete loader.promiseCache[url];
        if (Cache.has(url)) {
          Cache.remove(url);
        }
      };
      texture.source.once("destroy", () => {
        if (loader.promiseCache[url]) {
          warn("[Assets] A TextureSource managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the TextureSource.");
          unload();
        }
      });
      texture.once("destroy", () => {
        if (!source.destroyed) {
          warn("[Assets] A Texture managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the Texture.");
          unload();
        }
      });
      return texture;
    }

    "use strict";
    var __defProp$H = Object.defineProperty;
    var __getOwnPropSymbols$J = Object.getOwnPropertySymbols;
    var __hasOwnProp$J = Object.prototype.hasOwnProperty;
    var __propIsEnum$J = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$H = (obj, key, value) => key in obj ? __defProp$H(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$H = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$J.call(b, prop))
          __defNormalProp$H(a, prop, b[prop]);
      if (__getOwnPropSymbols$J)
        for (var prop of __getOwnPropSymbols$J(b)) {
          if (__propIsEnum$J.call(b, prop))
            __defNormalProp$H(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$i = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$J.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$J)
        for (var prop of __getOwnPropSymbols$J(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$J.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const validSVGExtension = ".svg";
    const validSVGMIME = "image/svg+xml";
    const loadSvg = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.Low,
        name: "loadSVG"
      },
      /** used for deprecation purposes */
      name: "loadSVG",
      id: "svg",
      config: {
        crossOrigin: "anonymous",
        parseAsGraphicsContext: false
      },
      test(url) {
        return checkDataUrl(url, validSVGMIME) || checkExtension(url, validSVGExtension);
      },
      async load(url, asset, loader) {
        var _a, _b;
        if ((_b = (_a = asset.data) == null ? void 0 : _a.parseAsGraphicsContext) != null ? _b : this.config.parseAsGraphicsContext) {
          return loadAsGraphics(url);
        }
        return loadAsTexture(url, asset, loader, this.config.crossOrigin);
      },
      unload(asset) {
        asset.destroy(true);
      }
    };
    async function loadAsTexture(url, asset, loader, crossOrigin) {
      var _a, _b, _c, _d, _e, _f;
      const response = await DOMAdapter.get().fetch(url);
      const image = DOMAdapter.get().createImage();
      image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(await response.text())}`;
      image.crossOrigin = crossOrigin;
      await image.decode();
      const width = (_b = (_a = asset.data) == null ? void 0 : _a.width) != null ? _b : image.width;
      const height = (_d = (_c = asset.data) == null ? void 0 : _c.height) != null ? _d : image.height;
      const resolution = ((_e = asset.data) == null ? void 0 : _e.resolution) || getResolutionOfUrl(url);
      const canvasWidth = Math.ceil(width * resolution);
      const canvasHeight = Math.ceil(height * resolution);
      const canvas = DOMAdapter.get().createCanvas(canvasWidth, canvasHeight);
      const context = canvas.getContext("2d");
      context.imageSmoothingEnabled = true;
      context.imageSmoothingQuality = "high";
      context.drawImage(image, 0, 0, width * resolution, height * resolution);
      const _g = (_f = asset.data) != null ? _f : {}, { parseAsGraphicsContext: _p } = _g, rest = __objRest$i(_g, ["parseAsGraphicsContext"]);
      const base = new ImageSource(__spreadValues$H({
        resource: canvas,
        alphaMode: "premultiply-alpha-on-upload",
        resolution
      }, rest));
      return createTexture(base, loader, url);
    }
    async function loadAsGraphics(url) {
      const response = await DOMAdapter.get().fetch(url);
      const svgSource = await response.text();
      const context = new GraphicsContext();
      context.svg(svgSource);
      return context;
    }

    const WORKER_CODE$3 = "(function () {\n    'use strict';\n\n    const WHITE_PNG = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=\";\n    async function checkImageBitmap() {\n      try {\n        if (typeof createImageBitmap !== \"function\")\n          return false;\n        const response = await fetch(WHITE_PNG);\n        const imageBlob = await response.blob();\n        const imageBitmap = await createImageBitmap(imageBlob);\n        return imageBitmap.width === 1 && imageBitmap.height === 1;\n      } catch (_e) {\n        return false;\n      }\n    }\n    void checkImageBitmap().then((result) => {\n      self.postMessage(result);\n    });\n\n})();\n";
    let WORKER_URL$3 = null;
    let WorkerInstance$3 = class WorkerInstance
    {
        constructor()
        {
            if (!WORKER_URL$3)
            {
                WORKER_URL$3 = URL.createObjectURL(new Blob([WORKER_CODE$3], { type: 'application/javascript' }));
            }
            this.worker = new Worker(WORKER_URL$3);
        }
    };
    WorkerInstance$3.revokeObjectURL = function revokeObjectURL()
    {
        if (WORKER_URL$3)
        {
            URL.revokeObjectURL(WORKER_URL$3);
            WORKER_URL$3 = null;
        }
    };

    const WORKER_CODE$2 = "(function () {\n    'use strict';\n\n    async function loadImageBitmap(url, alphaMode) {\n      const response = await fetch(url);\n      if (!response.ok) {\n        throw new Error(`[WorkerManager.loadImageBitmap] Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n      }\n      const imageBlob = await response.blob();\n      return alphaMode === \"premultiplied-alpha\" ? createImageBitmap(imageBlob, { premultiplyAlpha: \"none\" }) : createImageBitmap(imageBlob);\n    }\n    self.onmessage = async (event) => {\n      try {\n        const imageBitmap = await loadImageBitmap(event.data.data[0], event.data.data[1]);\n        self.postMessage({\n          data: imageBitmap,\n          uuid: event.data.uuid,\n          id: event.data.id\n        }, [imageBitmap]);\n      } catch (e) {\n        self.postMessage({\n          error: e,\n          uuid: event.data.uuid,\n          id: event.data.id\n        });\n      }\n    };\n\n})();\n";
    let WORKER_URL$2 = null;
    let WorkerInstance$2 = class WorkerInstance
    {
        constructor()
        {
            if (!WORKER_URL$2)
            {
                WORKER_URL$2 = URL.createObjectURL(new Blob([WORKER_CODE$2], { type: 'application/javascript' }));
            }
            this.worker = new Worker(WORKER_URL$2);
        }
    };
    WorkerInstance$2.revokeObjectURL = function revokeObjectURL()
    {
        if (WORKER_URL$2)
        {
            URL.revokeObjectURL(WORKER_URL$2);
            WORKER_URL$2 = null;
        }
    };

    "use strict";
    let UUID = 0;
    let MAX_WORKERS;
    class WorkerManagerClass {
      constructor() {
        /** Whether the worker manager has been initialized */
        this._initialized = false;
        /** Current number of created workers (used to enforce MAX_WORKERS limit) */
        this._createdWorkers = 0;
        this._workerPool = [];
        this._queue = [];
        this._resolveHash = {};
      }
      /**
       * Checks if ImageBitmap is supported in the current environment.
       *
       * This method uses a dedicated worker to test ImageBitmap support
       * and caches the result for subsequent calls.
       * @returns Promise that resolves to true if ImageBitmap is supported, false otherwise
       */
      isImageBitmapSupported() {
        if (this._isImageBitmapSupported !== void 0)
          return this._isImageBitmapSupported;
        this._isImageBitmapSupported = new Promise((resolve) => {
          const { worker } = new WorkerInstance$3();
          worker.addEventListener("message", (event) => {
            worker.terminate();
            WorkerInstance$3.revokeObjectURL();
            resolve(event.data);
          });
        });
        return this._isImageBitmapSupported;
      }
      /**
       * Loads an image as an ImageBitmap using a web worker.
       * @param src - The source URL or path of the image to load
       * @param asset - Optional resolved asset containing additional texture source options
       * @returns Promise that resolves to the loaded ImageBitmap
       * @example
       * ```typescript
       * const bitmap = await WorkerManager.loadImageBitmap('image.png');
       * const bitmapWithOptions = await WorkerManager.loadImageBitmap('image.png', asset);
       * ```
       */
      loadImageBitmap(src, asset) {
        var _a;
        return this._run("loadImageBitmap", [src, (_a = asset == null ? void 0 : asset.data) == null ? void 0 : _a.alphaMode]);
      }
      /**
       * Initializes the worker pool if not already initialized.
       * Currently a no-op but reserved for future initialization logic.
       */
      async _initWorkers() {
        if (this._initialized)
          return;
        this._initialized = true;
      }
      /**
       * Gets an available worker from the pool or creates a new one if needed.
       *
       * Workers are created up to the MAX_WORKERS limit (based on navigator.hardwareConcurrency).
       * Each worker is configured with a message handler for processing results.
       * @returns Available worker or undefined if pool is at capacity and no workers are free
       */
      _getWorker() {
        if (MAX_WORKERS === void 0) {
          MAX_WORKERS = navigator.hardwareConcurrency || 4;
        }
        let worker = this._workerPool.pop();
        if (!worker && this._createdWorkers < MAX_WORKERS) {
          this._createdWorkers++;
          worker = new WorkerInstance$2().worker;
          worker.addEventListener("message", (event) => {
            this._complete(event.data);
            this._returnWorker(event.target);
            this._next();
          });
        }
        return worker;
      }
      /**
       * Returns a worker to the pool after completing a task.
       * @param worker - The worker to return to the pool
       */
      _returnWorker(worker) {
        this._workerPool.push(worker);
      }
      /**
       * Handles completion of a worker task by resolving or rejecting the corresponding promise.
       * @param data - Result data from the worker containing uuid, data, and optional error
       */
      _complete(data) {
        if (!this._resolveHash[data.uuid]) {
          return;
        }
        if (data.error !== void 0) {
          this._resolveHash[data.uuid].reject(data.error);
        } else {
          this._resolveHash[data.uuid].resolve(data.data);
        }
        delete this._resolveHash[data.uuid];
      }
      /**
       * Executes a task using the worker pool system.
       *
       * Queues the task and processes it when a worker becomes available.
       * @param id - Identifier for the type of task to run
       * @param args - Arguments to pass to the worker
       * @returns Promise that resolves with the worker's result
       */
      async _run(id, args) {
        await this._initWorkers();
        const promise = new Promise((resolve, reject) => {
          this._queue.push({ id, arguments: args, resolve, reject });
        });
        this._next();
        return promise;
      }
      /**
       * Processes the next item in the queue if workers are available.
       *
       * This method is called after worker initialization and when workers
       * complete tasks to continue processing the queue.
       */
      _next() {
        if (!this._queue.length)
          return;
        const worker = this._getWorker();
        if (!worker) {
          return;
        }
        const toDo = this._queue.pop();
        const id = toDo.id;
        this._resolveHash[UUID] = { resolve: toDo.resolve, reject: toDo.reject };
        worker.postMessage({
          data: toDo.arguments,
          uuid: UUID++,
          id
        });
      }
      /**
       * Resets the worker manager, terminating all workers and clearing the queue.
       *
       * This method:
       * - Terminates all active workers
       * - Rejects all pending promises with an error
       * - Clears all internal state
       * - Resets initialization flags
       *
       * This should be called when the worker manager is no longer needed
       * to prevent memory leaks and ensure proper cleanup.
       * @example
       * ```typescript
       * // Clean up when shutting down
       * WorkerManager.reset();
       * ```
       */
      reset() {
        this._workerPool.forEach((worker) => worker.terminate());
        this._workerPool.length = 0;
        Object.values(this._resolveHash).forEach(({ reject }) => {
          reject == null ? void 0 : reject(new Error("WorkerManager has been reset before completion"));
        });
        this._resolveHash = {};
        this._queue.length = 0;
        this._initialized = false;
        this._createdWorkers = 0;
      }
    }
    const WorkerManager = new WorkerManagerClass();

    "use strict";
    var __defProp$G = Object.defineProperty;
    var __getOwnPropSymbols$I = Object.getOwnPropertySymbols;
    var __hasOwnProp$I = Object.prototype.hasOwnProperty;
    var __propIsEnum$I = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$G = (obj, key, value) => key in obj ? __defProp$G(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$G = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$I.call(b, prop))
          __defNormalProp$G(a, prop, b[prop]);
      if (__getOwnPropSymbols$I)
        for (var prop of __getOwnPropSymbols$I(b)) {
          if (__propIsEnum$I.call(b, prop))
            __defNormalProp$G(a, prop, b[prop]);
        }
      return a;
    };
    const validImageExtensions = [".jpeg", ".jpg", ".png", ".webp", ".avif"];
    const validImageMIMEs = [
      "image/jpeg",
      "image/png",
      "image/webp",
      "image/avif"
    ];
    async function loadImageBitmap(url, asset) {
      var _a;
      const response = await DOMAdapter.get().fetch(url);
      if (!response.ok) {
        throw new Error(`[loadImageBitmap] Failed to fetch ${url}: ${response.status} ${response.statusText}`);
      }
      const imageBlob = await response.blob();
      return ((_a = asset == null ? void 0 : asset.data) == null ? void 0 : _a.alphaMode) === "premultiplied-alpha" ? createImageBitmap(imageBlob, { premultiplyAlpha: "none" }) : createImageBitmap(imageBlob);
    }
    const loadTextures = {
      /** used for deprecation purposes */
      name: "loadTextures",
      id: "texture",
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.High,
        name: "loadTextures"
      },
      config: {
        preferWorkers: true,
        preferCreateImageBitmap: true,
        crossOrigin: "anonymous"
      },
      test(url) {
        return checkDataUrl(url, validImageMIMEs) || checkExtension(url, validImageExtensions);
      },
      async load(url, asset, loader) {
        var _a;
        let src = null;
        if (globalThis.createImageBitmap && this.config.preferCreateImageBitmap) {
          if (this.config.preferWorkers && await WorkerManager.isImageBitmapSupported()) {
            src = await WorkerManager.loadImageBitmap(url, asset);
          } else {
            src = await loadImageBitmap(url, asset);
          }
        } else {
          src = await new Promise((resolve, reject) => {
            src = DOMAdapter.get().createImage();
            src.crossOrigin = this.config.crossOrigin;
            src.src = url;
            if (src.complete) {
              resolve(src);
            } else {
              src.onload = () => {
                resolve(src);
              };
              src.onerror = reject;
            }
          });
        }
        const base = new ImageSource(__spreadValues$G({
          resource: src,
          alphaMode: "premultiply-alpha-on-upload",
          resolution: ((_a = asset.data) == null ? void 0 : _a.resolution) || getResolutionOfUrl(url)
        }, asset.data));
        return createTexture(base, loader, url);
      },
      unload(texture) {
        texture.destroy(true);
      }
    };

    "use strict";
    var __defProp$F = Object.defineProperty;
    var __defProps$k = Object.defineProperties;
    var __getOwnPropDescs$k = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$H = Object.getOwnPropertySymbols;
    var __hasOwnProp$H = Object.prototype.hasOwnProperty;
    var __propIsEnum$H = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$F = (obj, key, value) => key in obj ? __defProp$F(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$F = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$H.call(b, prop))
          __defNormalProp$F(a, prop, b[prop]);
      if (__getOwnPropSymbols$H)
        for (var prop of __getOwnPropSymbols$H(b)) {
          if (__propIsEnum$H.call(b, prop))
            __defNormalProp$F(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$k = (a, b) => __defProps$k(a, __getOwnPropDescs$k(b));
    const potentialVideoExtensions = [".mp4", ".m4v", ".webm", ".ogg", ".ogv", ".h264", ".avi", ".mov"];
    let validVideoExtensions;
    let validVideoMIMEs;
    function crossOrigin(element, url, crossorigin) {
      if (crossorigin === void 0 && !url.startsWith("data:")) {
        element.crossOrigin = determineCrossOrigin(url);
      } else if (crossorigin !== false) {
        element.crossOrigin = typeof crossorigin === "string" ? crossorigin : "anonymous";
      }
    }
    function preloadVideo(element) {
      return new Promise((resolve, reject) => {
        element.addEventListener("canplaythrough", loaded);
        element.addEventListener("error", error);
        element.load();
        function loaded() {
          cleanup();
          resolve();
        }
        function error(err) {
          cleanup();
          reject(err);
        }
        function cleanup() {
          element.removeEventListener("canplaythrough", loaded);
          element.removeEventListener("error", error);
        }
      });
    }
    function determineCrossOrigin(url, loc = globalThis.location) {
      if (url.startsWith("data:")) {
        return "";
      }
      loc || (loc = globalThis.location);
      const parsedUrl = new URL(url, document.baseURI);
      if (parsedUrl.hostname !== loc.hostname || parsedUrl.port !== loc.port || parsedUrl.protocol !== loc.protocol) {
        return "anonymous";
      }
      return "";
    }
    function getBrowserSupportedVideoExtensions() {
      const supportedExtensions = [];
      const supportedMimes = [];
      for (const ext of potentialVideoExtensions) {
        const mimeType = VideoSource.MIME_TYPES[ext.substring(1)] || `video/${ext.substring(1)}`;
        if (testVideoFormat(mimeType)) {
          supportedExtensions.push(ext);
          if (!supportedMimes.includes(mimeType)) {
            supportedMimes.push(mimeType);
          }
        }
      }
      return {
        validVideoExtensions: supportedExtensions,
        validVideoMime: supportedMimes
      };
    }
    const loadVideoTextures = {
      /** used for deprecation purposes */
      name: "loadVideo",
      id: "video",
      extension: {
        type: ExtensionType.LoadParser,
        name: "loadVideo"
      },
      test(url) {
        if (!validVideoExtensions || !validVideoMIMEs) {
          const { validVideoExtensions: ve, validVideoMime: vm } = getBrowserSupportedVideoExtensions();
          validVideoExtensions = ve;
          validVideoMIMEs = vm;
        }
        const isValidDataUrl = checkDataUrl(url, validVideoMIMEs);
        const isValidExtension = checkExtension(url, validVideoExtensions);
        return isValidDataUrl || isValidExtension;
      },
      async load(url, asset, loader) {
        var _a, _b;
        const options = __spreadValues$F(__spreadProps$k(__spreadValues$F({}, VideoSource.defaultOptions), {
          resolution: ((_a = asset.data) == null ? void 0 : _a.resolution) || getResolutionOfUrl(url),
          alphaMode: ((_b = asset.data) == null ? void 0 : _b.alphaMode) || await detectVideoAlphaMode()
        }), asset.data);
        const videoElement = document.createElement("video");
        const attributeMap = {
          preload: options.autoLoad !== false ? "auto" : void 0,
          "webkit-playsinline": options.playsinline !== false ? "" : void 0,
          playsinline: options.playsinline !== false ? "" : void 0,
          muted: options.muted === true ? "" : void 0,
          loop: options.loop === true ? "" : void 0,
          autoplay: options.autoPlay !== false ? "" : void 0
        };
        Object.keys(attributeMap).forEach((key) => {
          const value = attributeMap[key];
          if (value !== void 0)
            videoElement.setAttribute(key, value);
        });
        if (options.muted === true) {
          videoElement.muted = true;
        }
        crossOrigin(videoElement, url, options.crossorigin);
        const sourceElement = document.createElement("source");
        let mime;
        if (options.mime) {
          mime = options.mime;
        } else if (url.startsWith("data:")) {
          mime = url.slice(5, url.indexOf(";"));
        } else if (!url.startsWith("blob:")) {
          const ext = url.split("?")[0].slice(url.lastIndexOf(".") + 1).toLowerCase();
          mime = VideoSource.MIME_TYPES[ext] || `video/${ext}`;
        }
        sourceElement.src = url;
        if (mime) {
          sourceElement.type = mime;
        }
        return new Promise((resolve) => {
          const onCanPlay = async () => {
            const base = new VideoSource(__spreadProps$k(__spreadValues$F({}, options), { resource: videoElement }));
            videoElement.removeEventListener("canplay", onCanPlay);
            if (asset.data.preload) {
              await preloadVideo(videoElement);
            }
            resolve(createTexture(base, loader, url));
          };
          if (options.preload && !options.autoPlay) {
            videoElement.load();
          }
          videoElement.addEventListener("canplay", onCanPlay);
          videoElement.appendChild(sourceElement);
        });
      },
      unload(texture) {
        texture.destroy(true);
      }
    };

    "use strict";
    const resolveTextureUrl = {
      extension: {
        type: ExtensionType.ResolveParser,
        name: "resolveTexture"
      },
      test: loadTextures.test,
      parse: (value) => {
        var _a, _b;
        return {
          resolution: parseFloat((_b = (_a = Resolver.RETINA_PREFIX.exec(value)) == null ? void 0 : _a[1]) != null ? _b : "1"),
          format: value.split(".").pop(),
          src: value
        };
      }
    };

    "use strict";
    const resolveJsonUrl = {
      extension: {
        type: ExtensionType.ResolveParser,
        priority: -2,
        name: "resolveJson"
      },
      test: (value) => Resolver.RETINA_PREFIX.test(value) && value.endsWith(".json"),
      parse: resolveTextureUrl.parse
    };

    "use strict";
    var __defProp$E = Object.defineProperty;
    var __getOwnPropSymbols$G = Object.getOwnPropertySymbols;
    var __hasOwnProp$G = Object.prototype.hasOwnProperty;
    var __propIsEnum$G = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$E = (obj, key, value) => key in obj ? __defProp$E(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$E = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$G.call(b, prop))
          __defNormalProp$E(a, prop, b[prop]);
      if (__getOwnPropSymbols$G)
        for (var prop of __getOwnPropSymbols$G(b)) {
          if (__propIsEnum$G.call(b, prop))
            __defNormalProp$E(a, prop, b[prop]);
        }
      return a;
    };
    class AssetsClass {
      constructor() {
        this._detections = [];
        this._initialized = false;
        this.resolver = new Resolver();
        this.loader = new Loader();
        this.cache = Cache;
        this._backgroundLoader = new BackgroundLoader(this.loader);
        this._backgroundLoader.active = true;
        this.reset();
      }
      /**
       * Initializes the Assets class with configuration options. While not required,
       * calling this before loading assets is recommended to set up default behaviors.
       * @param options - Configuration options for the Assets system
       * @example
       * ```ts
       * // Basic initialization (optional as Assets.load will call this automatically)
       * await Assets.init();
       *
       * // With CDN configuration
       * await Assets.init({
       *     basePath: 'https://my-cdn.com/assets/',
       *     defaultSearchParams: { version: '1.0.0' }
       * });
       *
       * // With manifest and preferences
       * await Assets.init({
       *     manifest: {
       *         bundles: [{
       *             name: 'game-screen',
       *             assets: [
       *                 {
       *                     alias: 'hero',
       *                     src: 'hero.{png,webp}',
       *                     data: { scaleMode: SCALE_MODES.NEAREST }
       *                 },
       *                 {
       *                     alias: 'map',
       *                     src: 'map.json'
       *                 }
       *             ]
       *         }]
       *     },
       *     // Optimize for device capabilities
       *     texturePreference: {
       *         resolution: window.devicePixelRatio,
       *         format: ['webp', 'png']
       *     },
       *     // Set global preferences
       *     preferences: {
       *         crossOrigin: 'anonymous',
       *     }
       * });
       *
       * // Load assets after initialization
       * const heroTexture = await Assets.load('hero');
       * ```
       * @remarks
       * - Can be called only once; subsequent calls will be ignored with a warning
       * - Format detection runs automatically unless `skipDetections` is true
       * - The manifest can be a URL to a JSON file or an inline object
       * @see {@link AssetInitOptions} For all available initialization options
       * @see {@link AssetsManifest} For manifest format details
       */
      async init(options = {}) {
        var _a, _b, _c;
        if (this._initialized) {
          warn("[Assets]AssetManager already initialized, did you load before calling this Assets.init()?");
          return;
        }
        this._initialized = true;
        if (options.defaultSearchParams) {
          this.resolver.setDefaultSearchParams(options.defaultSearchParams);
        }
        if (options.basePath) {
          this.resolver.basePath = options.basePath;
        }
        if (options.bundleIdentifier) {
          this.resolver.setBundleIdentifier(options.bundleIdentifier);
        }
        if (options.manifest) {
          let manifest = options.manifest;
          if (typeof manifest === "string") {
            manifest = await this.load(manifest);
          }
          this.resolver.addManifest(manifest);
        }
        const resolutionPref = (_b = (_a = options.texturePreference) == null ? void 0 : _a.resolution) != null ? _b : 1;
        const resolution = typeof resolutionPref === "number" ? [resolutionPref] : resolutionPref;
        const formats = await this._detectFormats({
          preferredFormats: (_c = options.texturePreference) == null ? void 0 : _c.format,
          skipDetections: options.skipDetections,
          detections: this._detections
        });
        this.resolver.prefer({
          params: {
            format: formats,
            resolution
          }
        });
        if (options.preferences) {
          this.setPreferences(options.preferences);
        }
        if (options.loadOptions) {
          this.loader.loadOptions = __spreadValues$E(__spreadValues$E({}, this.loader.loadOptions), options.loadOptions);
        }
      }
      /**
       * Registers assets with the Assets resolver. This method maps keys (aliases) to asset sources,
       * allowing you to load assets using friendly names instead of direct URLs.
       * @param assets - The unresolved assets to add to the resolver
       * @example
       * ```ts
       * // Basic usage - single asset
       * Assets.add({
       *     alias: 'myTexture',
       *     src: 'assets/texture.png'
       * });
       * const texture = await Assets.load('myTexture');
       *
       * // Multiple aliases for the same asset
       * Assets.add({
       *     alias: ['hero', 'player'],
       *     src: 'hero.png'
       * });
       * const hero1 = await Assets.load('hero');
       * const hero2 = await Assets.load('player'); // Same texture
       *
       * // Multiple format support
       * Assets.add({
       *     alias: 'character',
       *     src: 'character.{webp,png}' // Will choose best format
       * });
       * Assets.add({
       *     alias: 'character',
       *     src: ['character.webp', 'character.png'], // Explicitly specify formats
       * });
       *
       * // With texture options
       * Assets.add({
       *     alias: 'sprite',
       *     src: 'sprite.png',
       *     data: { scaleMode: 'nearest' }
       * });
       *
       * // Multiple assets at once
       * Assets.add([
       *     { alias: 'bg', src: 'background.png' },
       *     { alias: 'music', src: 'music.mp3' },
       *     { alias: 'spritesheet', src: 'sheet.json', data: { ignoreMultiPack: false } }
       * ]);
       * ```
       * @remarks
       * - Assets are resolved when loaded, not when added
       * - Multiple formats use the best available format for the browser
       * - Adding with same alias overwrites previous definition
       * - The `data` property is passed to the asset loader
       * @see {@link Resolver} For details on asset resolution
       * @see {@link LoaderParser} For asset-specific data options
       * @advanced
       */
      add(assets) {
        this.resolver.add(assets);
      }
      async load(urls, onProgress) {
        if (!this._initialized) {
          await this.init();
        }
        const singleAsset = isSingleItem(urls);
        const urlArray = convertToList(urls).map((url) => {
          if (typeof url !== "string") {
            const aliases = this.resolver.getAlias(url);
            if (aliases.some((alias) => !this.resolver.hasKey(alias))) {
              this.add(url);
            }
            return Array.isArray(aliases) ? aliases[0] : aliases;
          }
          if (!this.resolver.hasKey(url))
            this.add({ alias: url, src: url });
          return url;
        });
        const resolveResults = this.resolver.resolve(urlArray);
        const out = await this._mapLoadToResolve(resolveResults, onProgress);
        return singleAsset ? out[urlArray[0]] : out;
      }
      /**
       * Registers a bundle of assets that can be loaded as a group. Bundles are useful for organizing
       * assets into logical groups, such as game levels or UI screens.
       * @param bundleId - Unique identifier for the bundle
       * @param assets - Assets to include in the bundle
       * @example
       * ```ts
       * // Add a bundle using array format
       * Assets.addBundle('animals', [
       *     { alias: 'bunny', src: 'bunny.png' },
       *     { alias: 'chicken', src: 'chicken.png' },
       *     { alias: 'thumper', src: 'thumper.png' },
       * ]);
       *
       * // Add a bundle using object format
       * Assets.addBundle('animals', {
       *     bunny: 'bunny.png',
       *     chicken: 'chicken.png',
       *     thumper: 'thumper.png',
       * });
       *
       * // Add a bundle with advanced options
       * Assets.addBundle('ui', [
       *     {
       *         alias: 'button',
       *         src: 'button.{webp,png}',
       *         data: { scaleMode: 'nearest' }
       *     },
       *     {
       *         alias: ['logo', 'brand'],  // Multiple aliases
       *         src: 'logo.svg',
       *         data: { resolution: 2 }
       *     }
       * ]);
       *
       * // Load the bundle
       * await Assets.loadBundle('animals');
       *
       * // Use the loaded assets
       * const bunny = Sprite.from('bunny');
       * const chicken = Sprite.from('chicken');
       * ```
       * @remarks
       * - Bundle IDs must be unique
       * - Assets in bundles are not loaded until `loadBundle` is called
       * - Bundles can be background loaded using `backgroundLoadBundle`
       * - Assets in bundles can be loaded individually using their aliases
       * @see {@link Assets.loadBundle} For loading bundles
       * @see {@link Assets.backgroundLoadBundle} For background loading bundles
       * @see {@link Assets.unloadBundle} For unloading bundles
       * @see {@link AssetsManifest} For manifest format details
       */
      addBundle(bundleId, assets) {
        this.resolver.addBundle(bundleId, assets);
      }
      /**
       * Loads a bundle or multiple bundles of assets. Bundles are collections of related assets
       * that can be loaded together.
       * @param bundleIds - Single bundle ID or array of bundle IDs to load
       * @param onProgress - Optional callback for load progress (0.0 to 1.0)
       * @returns Promise that resolves with the loaded bundle assets
       * @example
       * ```ts
       * // Define bundles in your manifest
       * const manifest = {
       *     bundles: [
       *         {
       *             name: 'load-screen',
       *             assets: [
       *                 {
       *                     alias: 'background',
       *                     src: 'sunset.png',
       *                 },
       *                 {
       *                     alias: 'bar',
       *                     src: 'load-bar.{png,webp}', // use an array of individual assets
       *                 },
       *             ],
       *         },
       *         {
       *             name: 'game-screen',
       *             assets: [
       *                 {
       *                     alias: 'character',
       *                     src: 'robot.png',
       *                 },
       *                 {
       *                     alias: 'enemy',
       *                     src: 'bad-guy.png',
       *                 },
       *             ],
       *         },
       *     ]
       * };
       *
       * // Initialize with manifest
       * await Assets.init({ manifest });
       *
       * // Or add bundles programmatically
       * Assets.addBundle('load-screen', [...]);
       * Assets.loadBundle('load-screen');
       *
       * // Load a single bundle
       * await Assets.loadBundle('load-screen');
       * const bg = Sprite.from('background'); // Uses alias from bundle
       *
       * // Load multiple bundles
       * await Assets.loadBundle([
       *     'load-screen',
       *     'game-screen'
       * ]);
       *
       * // Load with progress tracking
       * await Assets.loadBundle('game-screen', (progress) => {
       *     console.log(`Loading: ${Math.round(progress * 100)}%`);
       * });
       * ```
       * @remarks
       * - Bundle assets are cached automatically
       * - Bundles can be pre-loaded using `backgroundLoadBundle`
       * - Assets in bundles can be accessed by their aliases
       * - Progress callback receives values from 0.0 to 1.0
       * @throws {Error} If the bundle ID doesn't exist in the manifest
       * @see {@link Assets.addBundle} For adding bundles programmatically
       * @see {@link Assets.backgroundLoadBundle} For background loading bundles
       * @see {@link Assets.unloadBundle} For unloading bundles
       * @see {@link AssetsManifest} For manifest format details
       */
      async loadBundle(bundleIds, onProgress) {
        if (!this._initialized) {
          await this.init();
        }
        let singleAsset = false;
        if (typeof bundleIds === "string") {
          singleAsset = true;
          bundleIds = [bundleIds];
        }
        const resolveResults = this.resolver.resolveBundle(bundleIds);
        const out = {};
        const keys = Object.keys(resolveResults);
        let total = 0;
        const counts = [];
        const _onProgress = () => {
          onProgress == null ? void 0 : onProgress(counts.reduce((a, b) => a + b, 0) / total);
        };
        const promises = keys.map((bundleId, i) => {
          const resolveResult = resolveResults[bundleId];
          const values = Object.values(resolveResult);
          const totalAssetsToLoad = [...new Set(values.flat())];
          const progressSize = totalAssetsToLoad.reduce((sum, asset) => sum + (asset.progressSize || 1), 0);
          counts.push(0);
          total += progressSize;
          return this._mapLoadToResolve(resolveResult, (e) => {
            counts[i] = e * progressSize;
            _onProgress();
          }).then((resolveResult2) => {
            out[bundleId] = resolveResult2;
          });
        });
        await Promise.all(promises);
        return singleAsset ? out[bundleIds[0]] : out;
      }
      /**
       * Initiates background loading of assets. This allows assets to be loaded passively while other operations
       * continue, making them instantly available when needed later.
       *
       * Background loading is useful for:
       * - Preloading game levels while in a menu
       * - Loading non-critical assets during gameplay
       * - Reducing visible loading screens
       * @param urls - Single URL/alias or array of URLs/aliases to load in the background
       * @example
       * ```ts
       * // Basic background loading
       * Assets.backgroundLoad('images/level2-assets.png');
       *
       * // Background load multiple assets
       * Assets.backgroundLoad([
       *     'images/sprite1.png',
       *     'images/sprite2.png',
       *     'images/background.png'
       * ]);
       *
       * // Later, when you need the assets
       * const textures = await Assets.load([
       *     'images/sprite1.png',
       *     'images/sprite2.png'
       * ]); // Resolves immediately if background loading completed
       * ```
       * @remarks
       * - Background loading happens one asset at a time to avoid blocking the main thread
       * - Loading can be interrupted safely by calling `Assets.load()`
       * - Assets are cached as they complete loading
       * - No progress tracking is available for background loading
       */
      async backgroundLoad(urls) {
        if (!this._initialized) {
          await this.init();
        }
        if (typeof urls === "string") {
          urls = [urls];
        }
        const resolveResults = this.resolver.resolve(urls);
        this._backgroundLoader.add(Object.values(resolveResults));
      }
      /**
       * Initiates background loading of asset bundles. Similar to backgroundLoad but works with
       * predefined bundles of assets.
       *
       * Perfect for:
       * - Preloading level bundles during gameplay
       * - Loading UI assets during splash screens
       * - Preparing assets for upcoming game states
       * @param bundleIds - Single bundle ID or array of bundle IDs to load in the background
       * @example
       * ```ts
       * // Define bundles in your manifest
       * await Assets.init({
       *     manifest: {
       *         bundles: [
       *             {
       *               name: 'home',
       *               assets: [
       *                 {
       *                     alias: 'background',
       *                     src: 'images/home-bg.png',
       *                 },
       *                 {
       *                     alias: 'logo',
       *                     src: 'images/logo.png',
       *                 }
       *              ]
       *            },
       *            {
       *             name: 'level-1',
       *             assets: [
       *                 {
       *                     alias: 'background',
       *                     src: 'images/level1/bg.png',
       *                 },
       *                 {
       *                     alias: 'sprites',
       *                     src: 'images/level1/sprites.json'
       *                 }
       *             ]
       *         }]
       *     }
       * });
       *
       * // Load the home screen assets right away
       * await Assets.loadBundle('home');
       * showHomeScreen();
       *
       * // Start background loading while showing home screen
       * Assets.backgroundLoadBundle('level-1');
       *
       * // When player starts level, load completes faster
       * await Assets.loadBundle('level-1');
       * hideHomeScreen();
       * startLevel();
       * ```
       * @remarks
       * - Bundle assets are loaded one at a time
       * - Loading can be interrupted safely by calling `Assets.loadBundle()`
       * - Assets are cached as they complete loading
       * - Requires bundles to be registered via manifest or `addBundle`
       * @see {@link Assets.addBundle} For adding bundles programmatically
       * @see {@link Assets.loadBundle} For immediate bundle loading
       * @see {@link AssetsManifest} For manifest format details
       */
      async backgroundLoadBundle(bundleIds) {
        if (!this._initialized) {
          await this.init();
        }
        if (typeof bundleIds === "string") {
          bundleIds = [bundleIds];
        }
        const resolveResults = this.resolver.resolveBundle(bundleIds);
        Object.values(resolveResults).forEach((resolveResult) => {
          this._backgroundLoader.add(Object.values(resolveResult));
        });
      }
      /**
       * Only intended for development purposes.
       * This will wipe the resolver and caches.
       * You will need to reinitialize the Asset
       * @internal
       */
      reset() {
        this.resolver.reset();
        this.loader.reset();
        this.cache.reset();
        this._initialized = false;
      }
      get(keys) {
        if (typeof keys === "string") {
          return Cache.get(keys);
        }
        const assets = {};
        for (let i = 0; i < keys.length; i++) {
          assets[i] = Cache.get(keys[i]);
        }
        return assets;
      }
      /**
       * helper function to map resolved assets back to loaded assets
       * @param resolveResults - the resolve results from the resolver
       * @param progressOrLoadOptions - the progress callback or load options
       */
      async _mapLoadToResolve(resolveResults, progressOrLoadOptions) {
        const resolveArray = [...new Set(Object.values(resolveResults))];
        this._backgroundLoader.active = false;
        const loadedAssets = await this.loader.load(resolveArray, progressOrLoadOptions);
        this._backgroundLoader.active = true;
        const out = {};
        resolveArray.forEach((resolveResult) => {
          const asset = loadedAssets[resolveResult.src];
          const keys = [resolveResult.src];
          if (resolveResult.alias) {
            keys.push(...resolveResult.alias);
          }
          keys.forEach((key) => {
            out[key] = asset;
          });
          Cache.set(keys, asset);
        });
        return out;
      }
      /**
       * Unloads assets and releases them from memory. This method ensures proper cleanup of
       * loaded assets when they're no longer needed.
       * @param urls - Single URL/alias or array of URLs/aliases to unload
       * @example
       * ```ts
       * // Unload a single asset
       * await Assets.unload('images/sprite.png');
       *
       * // Unload using an alias
       * await Assets.unload('hero'); // Unloads the asset registered with 'hero' alias
       *
       * // Unload multiple assets
       * await Assets.unload([
       *     'images/background.png',
       *     'images/character.png',
       *     'hero'
       * ]);
       *
       * // Unload and handle creation of new instances
       * await Assets.unload('hero');
       * const newHero = await Assets.load('hero'); // Will load fresh from source
       * ```
       * @remarks
       * > [!WARNING]
       * > Make sure assets aren't being used before unloading:
       * > - Remove sprites using the texture
       * > - Clear any references to the asset
       * > - Textures will be destroyed and can't be used after unloading
       * @throws {Error} If the asset is not found in cache
       */
      async unload(urls) {
        if (!this._initialized) {
          await this.init();
        }
        const urlArray = convertToList(urls).map((url) => typeof url !== "string" ? url.src : url);
        const resolveResults = this.resolver.resolve(urlArray);
        await this._unloadFromResolved(resolveResults);
      }
      /**
       * Unloads all assets in a bundle. Use this to free memory when a bundle's assets
       * are no longer needed, such as when switching game levels.
       * @param bundleIds - Single bundle ID or array of bundle IDs to unload
       * @example
       * ```ts
       * // Define and load a bundle
       * Assets.addBundle('level-1', {
       *     background: 'level1/bg.png',
       *     sprites: 'level1/sprites.json',
       *     music: 'level1/music.mp3'
       * });
       *
       * // Load the bundle
       * const level1 = await Assets.loadBundle('level-1');
       *
       * // Use the assets
       * const background = Sprite.from(level1.background);
       *
       * // When done with the level, unload everything
       * await Assets.unloadBundle('level-1');
       * // background sprite is now invalid!
       *
       * // Unload multiple bundles
       * await Assets.unloadBundle([
       *     'level-1',
       *     'level-2',
       *     'ui-elements'
       * ]);
       * ```
       * @remarks
       * > [!WARNING]
       * > - All assets in the bundle will be destroyed
       * > - Bundle needs to be reloaded to use assets again
       * > - Make sure no sprites or other objects are using the assets
       * @throws {Error} If the bundle is not found
       * @see {@link Assets.addBundle} For adding bundles
       * @see {@link Assets.loadBundle} For loading bundles
       */
      async unloadBundle(bundleIds) {
        if (!this._initialized) {
          await this.init();
        }
        bundleIds = convertToList(bundleIds);
        const resolveResults = this.resolver.resolveBundle(bundleIds);
        const promises = Object.keys(resolveResults).map((bundleId) => this._unloadFromResolved(resolveResults[bundleId]));
        await Promise.all(promises);
      }
      async _unloadFromResolved(resolveResult) {
        const resolveArray = Object.values(resolveResult);
        resolveArray.forEach((resolveResult2) => {
          Cache.remove(resolveResult2.src);
        });
        await this.loader.unload(resolveArray);
      }
      /**
       * Detects the supported formats for the browser, and returns an array of supported formats, respecting
       * the users preferred formats order.
       * @param options - the options to use when detecting formats
       * @param options.preferredFormats - the preferred formats to use
       * @param options.skipDetections - if we should skip the detections altogether
       * @param options.detections - the detections to use
       * @returns - the detected formats
       */
      async _detectFormats(options) {
        let formats = [];
        if (options.preferredFormats) {
          formats = Array.isArray(options.preferredFormats) ? options.preferredFormats : [options.preferredFormats];
        }
        for (const detection of options.detections) {
          if (options.skipDetections || await detection.test()) {
            formats = await detection.add(formats);
          } else if (!options.skipDetections) {
            formats = await detection.remove(formats);
          }
        }
        formats = formats.filter((format, index) => formats.indexOf(format) === index);
        return formats;
      }
      /**
       * All the detection parsers currently added to the Assets class.
       * @advanced
       */
      get detections() {
        return this._detections;
      }
      /**
       * Sets global preferences for asset loading behavior. This method configures how assets
       * are loaded and processed across all parsers.
       * @param preferences - Asset loading preferences
       * @example
       * ```ts
       * // Basic preferences
       * Assets.setPreferences({
       *     crossOrigin: 'anonymous',
       *     parseAsGraphicsContext: false
       * });
       * ```
       * @remarks
       * Preferences are applied to all compatible parsers and affect future asset loading.
       * Common preferences include:
       * - `crossOrigin`: CORS setting for loaded assets
       * - `preferWorkers`: Whether to use web workers for loading textures
       * - `preferCreateImageBitmap`: Use `createImageBitmap` for texture creation. Turning this off will use the `Image` constructor instead.
       * @see {@link AssetsPreferences} For all available preferences
       */
      setPreferences(preferences) {
        this.loader.parsers.forEach((parser) => {
          if (!parser.config)
            return;
          Object.keys(parser.config).filter((key) => key in preferences).forEach((key) => {
            parser.config[key] = preferences[key];
          });
        });
      }
    }
    const Assets = new AssetsClass();
    extensions.handleByList(ExtensionType.LoadParser, Assets.loader.parsers).handleByList(ExtensionType.ResolveParser, Assets.resolver.parsers).handleByList(ExtensionType.CacheParser, Assets.cache.parsers).handleByList(ExtensionType.DetectionParser, Assets.detections);
    extensions.add(
      cacheTextureArray,
      detectDefaults,
      detectAvif,
      detectWebp,
      detectMp4,
      detectOgv,
      detectWebm,
      loadJson,
      loadTxt,
      loadWebFont,
      loadSvg,
      loadTextures,
      loadVideoTextures,
      loadBitmapFont,
      bitmapFontCachePlugin,
      resolveTextureUrl,
      resolveJsonUrl
    );
    const assetKeyMap = {
      loader: ExtensionType.LoadParser,
      resolver: ExtensionType.ResolveParser,
      cache: ExtensionType.CacheParser,
      detection: ExtensionType.DetectionParser
    };
    extensions.handle(ExtensionType.Asset, (extension) => {
      const ref = extension.ref;
      Object.entries(assetKeyMap).filter(([key]) => !!ref[key]).forEach(([key, type]) => {
        var _a;
        return extensions.add(Object.assign(
          ref[key],
          // Allow the function to optionally define it's own
          // ExtensionMetadata, the use cases here is priority for LoaderParsers
          { extension: (_a = ref[key].extension) != null ? _a : type }
        ));
      });
    }, (extension) => {
      const ref = extension.ref;
      Object.keys(assetKeyMap).filter((key) => !!ref[key]).forEach((key) => extensions.remove(ref[key]));
    });

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";
    const detectBasis = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 3
      },
      test: async () => {
        if (await isWebGPUSupported())
          return true;
        if (isWebGLSupported())
          return true;
        return false;
      },
      add: async (formats) => [...formats, "basis"],
      remove: async (formats) => formats.filter((f) => f !== "basis")
    };

    "use strict";
    class CompressedSource extends TextureSource {
      constructor(options) {
        super(options);
        this.uploadMethodId = "compressed";
        this.resource = options.resource;
        this.mipLevelCount = this.resource.length;
      }
    }

    "use strict";
    let supportedGLCompressedTextureFormats;
    function getSupportedGlCompressedTextureFormats() {
      if (supportedGLCompressedTextureFormats)
        return supportedGLCompressedTextureFormats;
      const canvas = DOMAdapter.get().createCanvas(1, 1);
      const gl = canvas.getContext("webgl");
      if (!gl) {
        return [];
      }
      supportedGLCompressedTextureFormats = [
        // BC compressed formats usable if "texture-compression-bc" is both
        // supported by the device/user agent and enabled in requestDevice.
        // 'bc6h-rgb-ufloat'
        // 'bc6h-rgb-float'
        // 'bc7-rgba-unorm',
        // 'bc7-rgba-unorm-srgb',
        ...gl.getExtension("EXT_texture_compression_bptc") ? [
          "bc6h-rgb-ufloat",
          "bc6h-rgb-float",
          "bc7-rgba-unorm",
          "bc7-rgba-unorm-srgb"
        ] : [],
        // BC compressed formats usable if "texture-compression-bc" is both
        // supported by the device/user agent and enabled in requestDevice.
        // 'bc1-rgba-unorm',
        // 'bc1-rgba-unorm-srgb',
        // 'bc4-r-unorm'
        // 'bc4-r-snorm'
        // 'bc5-rg-unorm'
        // 'bc5-rg-snorm'
        ...gl.getExtension("WEBGL_compressed_texture_s3tc") ? [
          "bc1-rgba-unorm",
          "bc2-rgba-unorm",
          "bc3-rgba-unorm"
        ] : [],
        ...gl.getExtension("WEBGL_compressed_texture_s3tc_srgb") ? [
          "bc1-rgba-unorm-srgb",
          "bc2-rgba-unorm-srgb",
          "bc3-rgba-unorm-srgb"
        ] : [],
        ...gl.getExtension("EXT_texture_compression_rgtc") ? [
          "bc4-r-unorm",
          "bc4-r-snorm",
          "bc5-rg-unorm",
          "bc5-rg-snorm"
        ] : [],
        // ETC2 compressed formats usable if "texture-compression-etc2" is both
        // supported by the device/user agent and enabled in requestDevice.
        ...gl.getExtension("WEBGL_compressed_texture_etc") ? [
          "etc2-rgb8unorm",
          "etc2-rgb8unorm-srgb",
          "etc2-rgba8unorm",
          "etc2-rgba8unorm-srgb",
          "etc2-rgb8a1unorm",
          "etc2-rgb8a1unorm-srgb",
          "eac-r11unorm",
          "eac-rg11unorm"
        ] : [],
        // 'eac-r11snorm',
        // 'eac-rg11snorm',
        // ASTC compressed formats usable if "texture-compression-astc" is both
        // supported by the device/user agent and enabled in requestDevice.
        ...gl.getExtension("WEBGL_compressed_texture_astc") ? [
          "astc-4x4-unorm",
          "astc-4x4-unorm-srgb",
          "astc-5x4-unorm",
          "astc-5x4-unorm-srgb",
          "astc-5x5-unorm",
          "astc-5x5-unorm-srgb",
          "astc-6x5-unorm",
          "astc-6x5-unorm-srgb",
          "astc-6x6-unorm",
          "astc-6x6-unorm-srgb",
          "astc-8x5-unorm",
          "astc-8x5-unorm-srgb",
          "astc-8x6-unorm",
          "astc-8x6-unorm-srgb",
          "astc-8x8-unorm",
          "astc-8x8-unorm-srgb",
          "astc-10x5-unorm",
          "astc-10x5-unorm-srgb",
          "astc-10x6-unorm",
          "astc-10x6-unorm-srgb",
          "astc-10x8-unorm",
          "astc-10x8-unorm-srgb",
          "astc-10x10-unorm",
          "astc-10x10-unorm-srgb",
          "astc-12x10-unorm",
          "astc-12x10-unorm-srgb",
          "astc-12x12-unorm",
          "astc-12x12-unorm-srgb"
        ] : []
      ];
      return supportedGLCompressedTextureFormats;
    }

    "use strict";
    let supportedGPUCompressedTextureFormats;
    async function getSupportedGPUCompressedTextureFormats() {
      if (supportedGPUCompressedTextureFormats)
        return supportedGPUCompressedTextureFormats;
      const adapter = await DOMAdapter.get().getNavigator().gpu.requestAdapter();
      supportedGPUCompressedTextureFormats = [
        ...adapter.features.has("texture-compression-bc") ? [
          // BC compressed formats usable if "texture-compression-bc" is both
          // supported by the device/user agent and enabled in requestDevice.
          "bc1-rgba-unorm",
          "bc1-rgba-unorm-srgb",
          "bc2-rgba-unorm",
          "bc2-rgba-unorm-srgb",
          "bc3-rgba-unorm",
          "bc3-rgba-unorm-srgb",
          "bc4-r-unorm",
          "bc4-r-snorm",
          "bc5-rg-unorm",
          "bc5-rg-snorm",
          "bc6h-rgb-ufloat",
          "bc6h-rgb-float",
          "bc7-rgba-unorm",
          "bc7-rgba-unorm-srgb"
        ] : [],
        ...adapter.features.has("texture-compression-etc2") ? [
          // ETC2 compressed formats usable if "texture-compression-etc2" is both
          // supported by the device/user agent and enabled in requestDevice.
          "etc2-rgb8unorm",
          "etc2-rgb8unorm-srgb",
          "etc2-rgb8a1unorm",
          "etc2-rgb8a1unorm-srgb",
          "etc2-rgba8unorm",
          "etc2-rgba8unorm-srgb",
          "eac-r11unorm",
          "eac-r11snorm",
          "eac-rg11unorm",
          "eac-rg11snorm"
        ] : [],
        ...adapter.features.has("texture-compression-astc") ? [
          // ASTC compressed formats usable if "texture-compression-astc" is both
          // supported by the device/user agent and enabled in requestDevice.
          "astc-4x4-unorm",
          "astc-4x4-unorm-srgb",
          "astc-5x4-unorm",
          "astc-5x4-unorm-srgb",
          "astc-5x5-unorm",
          "astc-5x5-unorm-srgb",
          "astc-6x5-unorm",
          "astc-6x5-unorm-srgb",
          "astc-6x6-unorm",
          "astc-6x6-unorm-srgb",
          "astc-8x5-unorm",
          "astc-8x5-unorm-srgb",
          "astc-8x6-unorm",
          "astc-8x6-unorm-srgb",
          "astc-8x8-unorm",
          "astc-8x8-unorm-srgb",
          "astc-10x5-unorm",
          "astc-10x5-unorm-srgb",
          "astc-10x6-unorm",
          "astc-10x6-unorm-srgb",
          "astc-10x8-unorm",
          "astc-10x8-unorm-srgb",
          "astc-10x10-unorm",
          "astc-10x10-unorm-srgb",
          "astc-12x10-unorm",
          "astc-12x10-unorm-srgb",
          "astc-12x12-unorm",
          "astc-12x12-unorm-srgb"
        ] : []
      ];
      return supportedGPUCompressedTextureFormats;
    }

    "use strict";
    let supportedCompressedTextureFormats;
    async function getSupportedCompressedTextureFormats() {
      if (supportedCompressedTextureFormats !== void 0)
        return supportedCompressedTextureFormats;
      supportedCompressedTextureFormats = await (async () => {
        const _isWebGPUSupported = await isWebGPUSupported();
        const _isWebGLSupported = isWebGLSupported();
        if (_isWebGPUSupported && _isWebGLSupported) {
          const gpuTextureFormats = await getSupportedGPUCompressedTextureFormats();
          const glTextureFormats = getSupportedGlCompressedTextureFormats();
          return gpuTextureFormats.filter((format) => glTextureFormats.includes(format));
        } else if (_isWebGPUSupported) {
          return await getSupportedGPUCompressedTextureFormats();
        } else if (_isWebGLSupported) {
          return getSupportedGlCompressedTextureFormats();
        }
        return [];
      })();
      return supportedCompressedTextureFormats;
    }

    "use strict";
    const nonCompressedFormats = [
      // 8-bit formats
      "r8unorm",
      "r8snorm",
      "r8uint",
      "r8sint",
      // 16-bit formats
      "r16uint",
      "r16sint",
      "r16float",
      "rg8unorm",
      "rg8snorm",
      "rg8uint",
      "rg8sint",
      // 32-bit formats
      "r32uint",
      "r32sint",
      "r32float",
      "rg16uint",
      "rg16sint",
      "rg16float",
      "rgba8unorm",
      "rgba8unorm-srgb",
      "rgba8snorm",
      "rgba8uint",
      "rgba8sint",
      "bgra8unorm",
      "bgra8unorm-srgb",
      // Packed 32-bit formats
      "rgb9e5ufloat",
      "rgb10a2unorm",
      "rg11b10ufloat",
      // 64-bit formats
      "rg32uint",
      "rg32sint",
      "rg32float",
      "rgba16uint",
      "rgba16sint",
      "rgba16float",
      // 128-bit formats
      "rgba32uint",
      "rgba32sint",
      "rgba32float",
      // Depth/stencil formats
      "stencil8",
      "depth16unorm",
      "depth24plus",
      "depth24plus-stencil8",
      "depth32float",
      // "depth32float-stencil8" feature
      "depth32float-stencil8"
    ];
    let supportedTextureFormats;
    async function getSupportedTextureFormats() {
      if (supportedTextureFormats !== void 0)
        return supportedTextureFormats;
      const compressedTextureFormats = await getSupportedCompressedTextureFormats();
      supportedTextureFormats = [
        ...nonCompressedFormats,
        ...compressedTextureFormats
      ];
      return supportedTextureFormats;
    }

    const WORKER_CODE$1 = "(function () {\n    'use strict';\n\n    function createLevelBuffers(basisTexture, basisTranscoderFormat) {\n      const images = basisTexture.getNumImages();\n      const levels = basisTexture.getNumLevels(0);\n      const success = basisTexture.startTranscoding();\n      if (!success) {\n        throw new Error(\"startTranscoding failed\");\n      }\n      const levelBuffers = [];\n      for (let levelIndex = 0; levelIndex < levels; ++levelIndex) {\n        for (let sliceIndex = 0; sliceIndex < images; ++sliceIndex) {\n          const transcodeSize = basisTexture.getImageTranscodedSizeInBytes(sliceIndex, levelIndex, basisTranscoderFormat);\n          const levelBuffer = new Uint8Array(transcodeSize);\n          const success2 = basisTexture.transcodeImage(levelBuffer, sliceIndex, levelIndex, basisTranscoderFormat, 1, 0);\n          if (!success2) {\n            throw new Error(\"transcodeImage failed\");\n          }\n          levelBuffers.push(levelBuffer);\n        }\n      }\n      return levelBuffers;\n    }\n\n    const gpuFormatToBasisTranscoderFormatMap = {\n      \"bc3-rgba-unorm\": 3,\n      // cTFBC3_RGBA\n      \"bc7-rgba-unorm\": 6,\n      // cTFBC7_RGBA,\n      \"etc2-rgba8unorm\": 1,\n      // cTFETC2_RGBA,\n      \"astc-4x4-unorm\": 10,\n      // cTFASTC_4x4_RGBA,\n      // Uncompressed\n      rgba8unorm: 13,\n      // cTFRGBA32,\n      rgba4unorm: 16\n      // cTFRGBA4444,\n    };\n    function gpuFormatToBasisTranscoderFormat(transcoderFormat) {\n      const format = gpuFormatToBasisTranscoderFormatMap[transcoderFormat];\n      if (format) {\n        return format;\n      }\n      throw new Error(`Unsupported transcoderFormat: ${transcoderFormat}`);\n    }\n\n    const settings = {\n      jsUrl: \"basis/basis_transcoder.js\",\n      wasmUrl: \"basis/basis_transcoder.wasm\"\n    };\n    let basisTranscoderFormat;\n    let basisTranscodedTextureFormat;\n    let basisPromise;\n    async function getBasis() {\n      if (!basisPromise) {\n        const absoluteJsUrl = new URL(settings.jsUrl, location.origin).href;\n        const absoluteWasmUrl = new URL(settings.wasmUrl, location.origin).href;\n        importScripts(absoluteJsUrl);\n        basisPromise = new Promise((resolve) => {\n          BASIS({\n            locateFile: (_file) => absoluteWasmUrl\n          }).then((module) => {\n            module.initializeBasis();\n            resolve(module.BasisFile);\n          });\n        });\n      }\n      return basisPromise;\n    }\n    async function fetchBasisTexture(url, BasisTexture) {\n      const basisResponse = await fetch(url);\n      if (basisResponse.ok) {\n        const basisArrayBuffer = await basisResponse.arrayBuffer();\n        return new BasisTexture(new Uint8Array(basisArrayBuffer));\n      }\n      throw new Error(`Failed to load Basis texture: ${url}`);\n    }\n    const preferredTranscodedFormat = [\n      \"bc7-rgba-unorm\",\n      \"astc-4x4-unorm\",\n      \"etc2-rgba8unorm\",\n      \"bc3-rgba-unorm\",\n      \"rgba8unorm\"\n    ];\n    async function load(url) {\n      const BasisTexture = await getBasis();\n      const basisTexture = await fetchBasisTexture(url, BasisTexture);\n      const levelBuffers = createLevelBuffers(basisTexture, basisTranscoderFormat);\n      return {\n        width: basisTexture.getImageWidth(0, 0),\n        height: basisTexture.getImageHeight(0, 0),\n        format: basisTranscodedTextureFormat,\n        resource: levelBuffers,\n        alphaMode: \"no-premultiply-alpha\"\n      };\n    }\n    async function init(jsUrl, wasmUrl, supportedTextures) {\n      if (jsUrl)\n        settings.jsUrl = jsUrl;\n      if (wasmUrl)\n        settings.wasmUrl = wasmUrl;\n      basisTranscodedTextureFormat = preferredTranscodedFormat.filter((format) => supportedTextures.includes(format))[0];\n      basisTranscoderFormat = gpuFormatToBasisTranscoderFormat(basisTranscodedTextureFormat);\n      await getBasis();\n    }\n    const messageHandlers = {\n      init: async (data) => {\n        const { jsUrl, wasmUrl, supportedTextures } = data;\n        await init(jsUrl, wasmUrl, supportedTextures);\n      },\n      load: async (data) => {\n        var _a;\n        try {\n          const textureOptions = await load(data.url);\n          return {\n            type: \"load\",\n            url: data.url,\n            success: true,\n            textureOptions,\n            transferables: (_a = textureOptions.resource) == null ? void 0 : _a.map((arr) => arr.buffer)\n          };\n        } catch (e) {\n          throw e;\n        }\n      }\n    };\n    self.onmessage = async (messageEvent) => {\n      const message = messageEvent.data;\n      const response = await messageHandlers[message.type](message);\n      if (response) {\n        self.postMessage(response, response.transferables);\n      }\n    };\n\n})();\n";
    let WORKER_URL$1 = null;
    let WorkerInstance$1 = class WorkerInstance
    {
        constructor()
        {
            if (!WORKER_URL$1)
            {
                WORKER_URL$1 = URL.createObjectURL(new Blob([WORKER_CODE$1], { type: 'application/javascript' }));
            }
            this.worker = new Worker(WORKER_URL$1);
        }
    };
    WorkerInstance$1.revokeObjectURL = function revokeObjectURL()
    {
        if (WORKER_URL$1)
        {
            URL.revokeObjectURL(WORKER_URL$1);
            WORKER_URL$1 = null;
        }
    };

    "use strict";
    const basisTranscoderUrls = {
      jsUrl: "https://cdn.jsdelivr.net/npm/pixi.js/transcoders/basis/basis_transcoder.js",
      wasmUrl: "https://cdn.jsdelivr.net/npm/pixi.js/transcoders/basis/basis_transcoder.wasm"
    };
    function setBasisTranscoderPath(config) {
      Object.assign(basisTranscoderUrls, config);
    }

    "use strict";
    let basisWorker;
    const urlHash$1 = {};
    function getBasisWorker(supportedTextures) {
      if (!basisWorker) {
        basisWorker = new WorkerInstance$1().worker;
        basisWorker.onmessage = (messageEvent) => {
          const { success, url, textureOptions } = messageEvent.data;
          if (!success) {
            console.warn("Failed to load Basis texture", url);
          }
          urlHash$1[url](textureOptions);
        };
        basisWorker.postMessage({
          type: "init",
          jsUrl: basisTranscoderUrls.jsUrl,
          wasmUrl: basisTranscoderUrls.wasmUrl,
          supportedTextures
        });
      }
      return basisWorker;
    }
    function loadBasisOnWorker(url, supportedTextures) {
      const ktxWorker = getBasisWorker(supportedTextures);
      return new Promise((resolve) => {
        urlHash$1[url] = resolve;
        ktxWorker.postMessage({ type: "load", url });
      });
    }

    "use strict";
    const loadBasis = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.High,
        name: "loadBasis"
      },
      /** used for deprecation purposes */
      name: "loadBasis",
      id: "basis",
      test(url) {
        return checkExtension(url, [".basis"]);
      },
      async load(url, _asset, loader) {
        const supportedTextures = await getSupportedTextureFormats();
        const textureOptions = await loadBasisOnWorker(url, supportedTextures);
        const compressedTextureSource = new CompressedSource(textureOptions);
        return createTexture(compressedTextureSource, loader, url);
      },
      unload(texture) {
        if (Array.isArray(texture)) {
          texture.forEach((t) => t.destroy(true));
        } else {
          texture.destroy(true);
        }
      }
    };

    "use strict";

    "use strict";
    function createLevelBuffers(basisTexture, basisTranscoderFormat) {
      const images = basisTexture.getNumImages();
      const levels = basisTexture.getNumLevels(0);
      const success = basisTexture.startTranscoding();
      if (!success) {
        throw new Error("startTranscoding failed");
      }
      const levelBuffers = [];
      for (let levelIndex = 0; levelIndex < levels; ++levelIndex) {
        for (let sliceIndex = 0; sliceIndex < images; ++sliceIndex) {
          const transcodeSize = basisTexture.getImageTranscodedSizeInBytes(sliceIndex, levelIndex, basisTranscoderFormat);
          const levelBuffer = new Uint8Array(transcodeSize);
          const success2 = basisTexture.transcodeImage(levelBuffer, sliceIndex, levelIndex, basisTranscoderFormat, 1, 0);
          if (!success2) {
            throw new Error("transcodeImage failed");
          }
          levelBuffers.push(levelBuffer);
        }
      }
      return levelBuffers;
    }

    "use strict";
    const gpuFormatToBasisTranscoderFormatMap$1 = {
      "bc3-rgba-unorm": 3,
      // cTFBC3_RGBA
      "bc7-rgba-unorm": 6,
      // cTFBC7_RGBA,
      "etc2-rgba8unorm": 1,
      // cTFETC2_RGBA,
      "astc-4x4-unorm": 10,
      // cTFASTC_4x4_RGBA,
      // Uncompressed
      rgba8unorm: 13,
      // cTFRGBA32,
      rgba4unorm: 16
      // cTFRGBA4444,
    };
    function gpuFormatToBasisTranscoderFormat(transcoderFormat) {
      const format = gpuFormatToBasisTranscoderFormatMap$1[transcoderFormat];
      if (format) {
        return format;
      }
      throw new Error(`Unsupported transcoderFormat: ${transcoderFormat}`);
    }

    "use strict";
    const DDS_HEADER_FIELDS = {
      MAGIC: 0,
      SIZE: 1,
      FLAGS: 2,
      HEIGHT: 3,
      WIDTH: 4,
      MIPMAP_COUNT: 7,
      PIXEL_FORMAT: 19,
      PF_FLAGS: 20,
      FOURCC: 21,
      RGB_BITCOUNT: 22,
      R_BIT_MASK: 23,
      G_BIT_MASK: 24,
      B_BIT_MASK: 25,
      A_BIT_MASK: 26
    };
    const DDS_DX10_FIELDS = {
      DXGI_FORMAT: 0,
      RESOURCE_DIMENSION: 1,
      MISC_FLAG: 2,
      ARRAY_SIZE: 3,
      MISC_FLAGS2: 4
    };
    var DXGI_FORMAT = /* @__PURE__ */ ((DXGI_FORMAT2) => {
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_UNKNOWN"] = 0] = "DXGI_FORMAT_UNKNOWN";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32A32_TYPELESS"] = 1] = "DXGI_FORMAT_R32G32B32A32_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32A32_FLOAT"] = 2] = "DXGI_FORMAT_R32G32B32A32_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32A32_UINT"] = 3] = "DXGI_FORMAT_R32G32B32A32_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32A32_SINT"] = 4] = "DXGI_FORMAT_R32G32B32A32_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32_TYPELESS"] = 5] = "DXGI_FORMAT_R32G32B32_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32_FLOAT"] = 6] = "DXGI_FORMAT_R32G32B32_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32_UINT"] = 7] = "DXGI_FORMAT_R32G32B32_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32B32_SINT"] = 8] = "DXGI_FORMAT_R32G32B32_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_TYPELESS"] = 9] = "DXGI_FORMAT_R16G16B16A16_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_FLOAT"] = 10] = "DXGI_FORMAT_R16G16B16A16_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_UNORM"] = 11] = "DXGI_FORMAT_R16G16B16A16_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_UINT"] = 12] = "DXGI_FORMAT_R16G16B16A16_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_SNORM"] = 13] = "DXGI_FORMAT_R16G16B16A16_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16B16A16_SINT"] = 14] = "DXGI_FORMAT_R16G16B16A16_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32_TYPELESS"] = 15] = "DXGI_FORMAT_R32G32_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32_FLOAT"] = 16] = "DXGI_FORMAT_R32G32_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32_UINT"] = 17] = "DXGI_FORMAT_R32G32_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G32_SINT"] = 18] = "DXGI_FORMAT_R32G32_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32G8X24_TYPELESS"] = 19] = "DXGI_FORMAT_R32G8X24_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_D32_FLOAT_S8X24_UINT"] = 20] = "DXGI_FORMAT_D32_FLOAT_S8X24_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS"] = 21] = "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_X32_TYPELESS_G8X24_UINT"] = 22] = "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R10G10B10A2_TYPELESS"] = 23] = "DXGI_FORMAT_R10G10B10A2_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R10G10B10A2_UNORM"] = 24] = "DXGI_FORMAT_R10G10B10A2_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R10G10B10A2_UINT"] = 25] = "DXGI_FORMAT_R10G10B10A2_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R11G11B10_FLOAT"] = 26] = "DXGI_FORMAT_R11G11B10_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_TYPELESS"] = 27] = "DXGI_FORMAT_R8G8B8A8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_UNORM"] = 28] = "DXGI_FORMAT_R8G8B8A8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"] = 29] = "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_UINT"] = 30] = "DXGI_FORMAT_R8G8B8A8_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_SNORM"] = 31] = "DXGI_FORMAT_R8G8B8A8_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8B8A8_SINT"] = 32] = "DXGI_FORMAT_R8G8B8A8_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_TYPELESS"] = 33] = "DXGI_FORMAT_R16G16_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_FLOAT"] = 34] = "DXGI_FORMAT_R16G16_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_UNORM"] = 35] = "DXGI_FORMAT_R16G16_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_UINT"] = 36] = "DXGI_FORMAT_R16G16_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_SNORM"] = 37] = "DXGI_FORMAT_R16G16_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16G16_SINT"] = 38] = "DXGI_FORMAT_R16G16_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32_TYPELESS"] = 39] = "DXGI_FORMAT_R32_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_D32_FLOAT"] = 40] = "DXGI_FORMAT_D32_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32_FLOAT"] = 41] = "DXGI_FORMAT_R32_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32_UINT"] = 42] = "DXGI_FORMAT_R32_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R32_SINT"] = 43] = "DXGI_FORMAT_R32_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R24G8_TYPELESS"] = 44] = "DXGI_FORMAT_R24G8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_D24_UNORM_S8_UINT"] = 45] = "DXGI_FORMAT_D24_UNORM_S8_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R24_UNORM_X8_TYPELESS"] = 46] = "DXGI_FORMAT_R24_UNORM_X8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_X24_TYPELESS_G8_UINT"] = 47] = "DXGI_FORMAT_X24_TYPELESS_G8_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_TYPELESS"] = 48] = "DXGI_FORMAT_R8G8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_UNORM"] = 49] = "DXGI_FORMAT_R8G8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_UINT"] = 50] = "DXGI_FORMAT_R8G8_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_SNORM"] = 51] = "DXGI_FORMAT_R8G8_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_SINT"] = 52] = "DXGI_FORMAT_R8G8_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_TYPELESS"] = 53] = "DXGI_FORMAT_R16_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_FLOAT"] = 54] = "DXGI_FORMAT_R16_FLOAT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_D16_UNORM"] = 55] = "DXGI_FORMAT_D16_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_UNORM"] = 56] = "DXGI_FORMAT_R16_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_UINT"] = 57] = "DXGI_FORMAT_R16_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_SNORM"] = 58] = "DXGI_FORMAT_R16_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R16_SINT"] = 59] = "DXGI_FORMAT_R16_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8_TYPELESS"] = 60] = "DXGI_FORMAT_R8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8_UNORM"] = 61] = "DXGI_FORMAT_R8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8_UINT"] = 62] = "DXGI_FORMAT_R8_UINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8_SNORM"] = 63] = "DXGI_FORMAT_R8_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8_SINT"] = 64] = "DXGI_FORMAT_R8_SINT";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_A8_UNORM"] = 65] = "DXGI_FORMAT_A8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R1_UNORM"] = 66] = "DXGI_FORMAT_R1_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R9G9B9E5_SHAREDEXP"] = 67] = "DXGI_FORMAT_R9G9B9E5_SHAREDEXP";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R8G8_B8G8_UNORM"] = 68] = "DXGI_FORMAT_R8G8_B8G8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_G8R8_G8B8_UNORM"] = 69] = "DXGI_FORMAT_G8R8_G8B8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC1_TYPELESS"] = 70] = "DXGI_FORMAT_BC1_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC1_UNORM"] = 71] = "DXGI_FORMAT_BC1_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC1_UNORM_SRGB"] = 72] = "DXGI_FORMAT_BC1_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC2_TYPELESS"] = 73] = "DXGI_FORMAT_BC2_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC2_UNORM"] = 74] = "DXGI_FORMAT_BC2_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC2_UNORM_SRGB"] = 75] = "DXGI_FORMAT_BC2_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC3_TYPELESS"] = 76] = "DXGI_FORMAT_BC3_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC3_UNORM"] = 77] = "DXGI_FORMAT_BC3_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC3_UNORM_SRGB"] = 78] = "DXGI_FORMAT_BC3_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC4_TYPELESS"] = 79] = "DXGI_FORMAT_BC4_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC4_UNORM"] = 80] = "DXGI_FORMAT_BC4_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC4_SNORM"] = 81] = "DXGI_FORMAT_BC4_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC5_TYPELESS"] = 82] = "DXGI_FORMAT_BC5_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC5_UNORM"] = 83] = "DXGI_FORMAT_BC5_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC5_SNORM"] = 84] = "DXGI_FORMAT_BC5_SNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B5G6R5_UNORM"] = 85] = "DXGI_FORMAT_B5G6R5_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B5G5R5A1_UNORM"] = 86] = "DXGI_FORMAT_B5G5R5A1_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8A8_UNORM"] = 87] = "DXGI_FORMAT_B8G8R8A8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8X8_UNORM"] = 88] = "DXGI_FORMAT_B8G8R8X8_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM"] = 89] = "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8A8_TYPELESS"] = 90] = "DXGI_FORMAT_B8G8R8A8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8A8_UNORM_SRGB"] = 91] = "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8X8_TYPELESS"] = 92] = "DXGI_FORMAT_B8G8R8X8_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B8G8R8X8_UNORM_SRGB"] = 93] = "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC6H_TYPELESS"] = 94] = "DXGI_FORMAT_BC6H_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC6H_UF16"] = 95] = "DXGI_FORMAT_BC6H_UF16";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC6H_SF16"] = 96] = "DXGI_FORMAT_BC6H_SF16";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC7_TYPELESS"] = 97] = "DXGI_FORMAT_BC7_TYPELESS";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC7_UNORM"] = 98] = "DXGI_FORMAT_BC7_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_BC7_UNORM_SRGB"] = 99] = "DXGI_FORMAT_BC7_UNORM_SRGB";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_AYUV"] = 100] = "DXGI_FORMAT_AYUV";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_Y410"] = 101] = "DXGI_FORMAT_Y410";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_Y416"] = 102] = "DXGI_FORMAT_Y416";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_NV12"] = 103] = "DXGI_FORMAT_NV12";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_P010"] = 104] = "DXGI_FORMAT_P010";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_P016"] = 105] = "DXGI_FORMAT_P016";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_420_OPAQUE"] = 106] = "DXGI_FORMAT_420_OPAQUE";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_YUY2"] = 107] = "DXGI_FORMAT_YUY2";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_Y210"] = 108] = "DXGI_FORMAT_Y210";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_Y216"] = 109] = "DXGI_FORMAT_Y216";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_NV11"] = 110] = "DXGI_FORMAT_NV11";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_AI44"] = 111] = "DXGI_FORMAT_AI44";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_IA44"] = 112] = "DXGI_FORMAT_IA44";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_P8"] = 113] = "DXGI_FORMAT_P8";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_A8P8"] = 114] = "DXGI_FORMAT_A8P8";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_B4G4R4A4_UNORM"] = 115] = "DXGI_FORMAT_B4G4R4A4_UNORM";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_P208"] = 116] = "DXGI_FORMAT_P208";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_V208"] = 117] = "DXGI_FORMAT_V208";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_V408"] = 118] = "DXGI_FORMAT_V408";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE"] = 119] = "DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE"] = 120] = "DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE";
      DXGI_FORMAT2[DXGI_FORMAT2["DXGI_FORMAT_FORCE_UINT"] = 121] = "DXGI_FORMAT_FORCE_UINT";
      return DXGI_FORMAT2;
    })(DXGI_FORMAT || {});
    var D3D10_RESOURCE_DIMENSION = /* @__PURE__ */ ((D3D10_RESOURCE_DIMENSION2) => {
      D3D10_RESOURCE_DIMENSION2[D3D10_RESOURCE_DIMENSION2["DDS_DIMENSION_TEXTURE1D"] = 2] = "DDS_DIMENSION_TEXTURE1D";
      D3D10_RESOURCE_DIMENSION2[D3D10_RESOURCE_DIMENSION2["DDS_DIMENSION_TEXTURE2D"] = 3] = "DDS_DIMENSION_TEXTURE2D";
      D3D10_RESOURCE_DIMENSION2[D3D10_RESOURCE_DIMENSION2["DDS_DIMENSION_TEXTURE3D"] = 6] = "DDS_DIMENSION_TEXTURE3D";
      return D3D10_RESOURCE_DIMENSION2;
    })(D3D10_RESOURCE_DIMENSION || {});
    function fourCCToInt32(value) {
      return value.charCodeAt(0) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) << 16) + (value.charCodeAt(3) << 24);
    }
    var D3DFMT = ((D3DFMT2) => {
      D3DFMT2[D3DFMT2["UNKNOWN"] = 0] = "UNKNOWN";
      D3DFMT2[D3DFMT2["R8G8B8"] = 20] = "R8G8B8";
      D3DFMT2[D3DFMT2["A8R8G8B8"] = 21] = "A8R8G8B8";
      D3DFMT2[D3DFMT2["X8R8G8B8"] = 22] = "X8R8G8B8";
      D3DFMT2[D3DFMT2["R5G6B5"] = 23] = "R5G6B5";
      D3DFMT2[D3DFMT2["X1R5G5B5"] = 24] = "X1R5G5B5";
      D3DFMT2[D3DFMT2["A1R5G5B5"] = 25] = "A1R5G5B5";
      D3DFMT2[D3DFMT2["A4R4G4B4"] = 26] = "A4R4G4B4";
      D3DFMT2[D3DFMT2["R3G3B2"] = 27] = "R3G3B2";
      D3DFMT2[D3DFMT2["A8"] = 28] = "A8";
      D3DFMT2[D3DFMT2["A8R3G3B2"] = 29] = "A8R3G3B2";
      D3DFMT2[D3DFMT2["X4R4G4B4"] = 30] = "X4R4G4B4";
      D3DFMT2[D3DFMT2["A2B10G10R10"] = 31] = "A2B10G10R10";
      D3DFMT2[D3DFMT2["A8B8G8R8"] = 32] = "A8B8G8R8";
      D3DFMT2[D3DFMT2["X8B8G8R8"] = 33] = "X8B8G8R8";
      D3DFMT2[D3DFMT2["G16R16"] = 34] = "G16R16";
      D3DFMT2[D3DFMT2["A2R10G10B10"] = 35] = "A2R10G10B10";
      D3DFMT2[D3DFMT2["A16B16G16R16"] = 36] = "A16B16G16R16";
      D3DFMT2[D3DFMT2["A8P8"] = 40] = "A8P8";
      D3DFMT2[D3DFMT2["P8"] = 41] = "P8";
      D3DFMT2[D3DFMT2["L8"] = 50] = "L8";
      D3DFMT2[D3DFMT2["A8L8"] = 51] = "A8L8";
      D3DFMT2[D3DFMT2["A4L4"] = 52] = "A4L4";
      D3DFMT2[D3DFMT2["V8U8"] = 60] = "V8U8";
      D3DFMT2[D3DFMT2["L6V5U5"] = 61] = "L6V5U5";
      D3DFMT2[D3DFMT2["X8L8V8U8"] = 62] = "X8L8V8U8";
      D3DFMT2[D3DFMT2["Q8W8V8U8"] = 63] = "Q8W8V8U8";
      D3DFMT2[D3DFMT2["V16U16"] = 64] = "V16U16";
      D3DFMT2[D3DFMT2["A2W10V10U10"] = 67] = "A2W10V10U10";
      D3DFMT2[D3DFMT2["Q16W16V16U16"] = 110] = "Q16W16V16U16";
      D3DFMT2[D3DFMT2["R16F"] = 111] = "R16F";
      D3DFMT2[D3DFMT2["G16R16F"] = 112] = "G16R16F";
      D3DFMT2[D3DFMT2["A16B16G16R16F"] = 113] = "A16B16G16R16F";
      D3DFMT2[D3DFMT2["R32F"] = 114] = "R32F";
      D3DFMT2[D3DFMT2["G32R32F"] = 115] = "G32R32F";
      D3DFMT2[D3DFMT2["A32B32G32R32F"] = 116] = "A32B32G32R32F";
      D3DFMT2[D3DFMT2["UYVY"] = fourCCToInt32("UYVY")] = "UYVY";
      D3DFMT2[D3DFMT2["R8G8_B8G8"] = fourCCToInt32("RGBG")] = "R8G8_B8G8";
      D3DFMT2[D3DFMT2["YUY2"] = fourCCToInt32("YUY2")] = "YUY2";
      D3DFMT2[D3DFMT2["D3DFMT_G8R8_G8B8"] = fourCCToInt32("GRGB")] = "D3DFMT_G8R8_G8B8";
      D3DFMT2[D3DFMT2["DXT1"] = fourCCToInt32("DXT1")] = "DXT1";
      D3DFMT2[D3DFMT2["DXT2"] = fourCCToInt32("DXT2")] = "DXT2";
      D3DFMT2[D3DFMT2["DXT3"] = fourCCToInt32("DXT3")] = "DXT3";
      D3DFMT2[D3DFMT2["DXT4"] = fourCCToInt32("DXT4")] = "DXT4";
      D3DFMT2[D3DFMT2["DXT5"] = fourCCToInt32("DXT5")] = "DXT5";
      D3DFMT2[D3DFMT2["ATI1"] = fourCCToInt32("ATI1")] = "ATI1";
      D3DFMT2[D3DFMT2["AT1N"] = fourCCToInt32("AT1N")] = "AT1N";
      D3DFMT2[D3DFMT2["ATI2"] = fourCCToInt32("ATI2")] = "ATI2";
      D3DFMT2[D3DFMT2["AT2N"] = fourCCToInt32("AT2N")] = "AT2N";
      D3DFMT2[D3DFMT2["BC4U"] = fourCCToInt32("BC4U")] = "BC4U";
      D3DFMT2[D3DFMT2["BC4S"] = fourCCToInt32("BC4S")] = "BC4S";
      D3DFMT2[D3DFMT2["BC5U"] = fourCCToInt32("BC5U")] = "BC5U";
      D3DFMT2[D3DFMT2["BC5S"] = fourCCToInt32("BC5S")] = "BC5S";
      D3DFMT2[D3DFMT2["DX10"] = fourCCToInt32("DX10")] = "DX10";
      return D3DFMT2;
    })(D3DFMT || {});
    const FOURCC_TO_TEXTURE_FORMAT = {
      [D3DFMT.DXT1]: "bc1-rgba-unorm",
      [D3DFMT.DXT2]: "bc2-rgba-unorm",
      [D3DFMT.DXT3]: "bc2-rgba-unorm",
      [D3DFMT.DXT4]: "bc3-rgba-unorm",
      [D3DFMT.DXT5]: "bc3-rgba-unorm",
      [D3DFMT.ATI1]: "bc4-r-unorm",
      [D3DFMT.BC4U]: "bc4-r-unorm",
      [D3DFMT.BC4S]: "bc4-r-snorm",
      [D3DFMT.ATI2]: "bc5-rg-unorm",
      [D3DFMT.BC5U]: "bc5-rg-unorm",
      [D3DFMT.BC5S]: "bc5-rg-snorm",
      [36 /* A16B16G16R16 */]: "rgba16uint",
      [110 /* Q16W16V16U16 */]: "rgba16sint",
      [111 /* R16F */]: "r16float",
      [112 /* G16R16F */]: "rg16float",
      [113 /* A16B16G16R16F */]: "rgba16float",
      [114 /* R32F */]: "r32float",
      [115 /* G32R32F */]: "rg32float",
      [116 /* A32B32G32R32F */]: "rgba32float"
    };
    const DXGI_TO_TEXTURE_FORMAT = {
      [70 /* DXGI_FORMAT_BC1_TYPELESS */]: "bc1-rgba-unorm",
      [71 /* DXGI_FORMAT_BC1_UNORM */]: "bc1-rgba-unorm",
      [72 /* DXGI_FORMAT_BC1_UNORM_SRGB */]: "bc1-rgba-unorm-srgb",
      [73 /* DXGI_FORMAT_BC2_TYPELESS */]: "bc2-rgba-unorm",
      [74 /* DXGI_FORMAT_BC2_UNORM */]: "bc2-rgba-unorm",
      [75 /* DXGI_FORMAT_BC2_UNORM_SRGB */]: "bc2-rgba-unorm-srgb",
      [76 /* DXGI_FORMAT_BC3_TYPELESS */]: "bc3-rgba-unorm",
      [77 /* DXGI_FORMAT_BC3_UNORM */]: "bc3-rgba-unorm",
      [78 /* DXGI_FORMAT_BC3_UNORM_SRGB */]: "bc3-rgba-unorm-srgb",
      [79 /* DXGI_FORMAT_BC4_TYPELESS */]: "bc4-r-unorm",
      [80 /* DXGI_FORMAT_BC4_UNORM */]: "bc4-r-unorm",
      [81 /* DXGI_FORMAT_BC4_SNORM */]: "bc4-r-snorm",
      [82 /* DXGI_FORMAT_BC5_TYPELESS */]: "bc5-rg-unorm",
      [83 /* DXGI_FORMAT_BC5_UNORM */]: "bc5-rg-unorm",
      [84 /* DXGI_FORMAT_BC5_SNORM */]: "bc5-rg-snorm",
      [94 /* DXGI_FORMAT_BC6H_TYPELESS */]: "bc6h-rgb-ufloat",
      [95 /* DXGI_FORMAT_BC6H_UF16 */]: "bc6h-rgb-ufloat",
      [96 /* DXGI_FORMAT_BC6H_SF16 */]: "bc6h-rgb-float",
      [97 /* DXGI_FORMAT_BC7_TYPELESS */]: "bc7-rgba-unorm",
      [98 /* DXGI_FORMAT_BC7_UNORM */]: "bc7-rgba-unorm",
      [99 /* DXGI_FORMAT_BC7_UNORM_SRGB */]: "bc7-rgba-unorm-srgb",
      [28 /* DXGI_FORMAT_R8G8B8A8_UNORM */]: "rgba8unorm",
      [29 /* DXGI_FORMAT_R8G8B8A8_UNORM_SRGB */]: "rgba8unorm-srgb",
      [87 /* DXGI_FORMAT_B8G8R8A8_UNORM */]: "bgra8unorm",
      [91 /* DXGI_FORMAT_B8G8R8A8_UNORM_SRGB */]: "bgra8unorm-srgb",
      [41 /* DXGI_FORMAT_R32_FLOAT */]: "r32float",
      [49 /* DXGI_FORMAT_R8G8_UNORM */]: "rg8unorm",
      [56 /* DXGI_FORMAT_R16_UNORM */]: "r16uint",
      [61 /* DXGI_FORMAT_R8_UNORM */]: "r8unorm",
      [24 /* DXGI_FORMAT_R10G10B10A2_UNORM */]: "rgb10a2unorm",
      [11 /* DXGI_FORMAT_R16G16B16A16_UNORM */]: "rgba16uint",
      [13 /* DXGI_FORMAT_R16G16B16A16_SNORM */]: "rgba16sint",
      [10 /* DXGI_FORMAT_R16G16B16A16_FLOAT */]: "rgba16float",
      [54 /* DXGI_FORMAT_R16_FLOAT */]: "r16float",
      [34 /* DXGI_FORMAT_R16G16_FLOAT */]: "rg16float",
      [16 /* DXGI_FORMAT_R32G32_FLOAT */]: "rg32float",
      [2 /* DXGI_FORMAT_R32G32B32A32_FLOAT */]: "rgba32float"
    };
    const DDS = {
      MAGIC_VALUE: 542327876,
      MAGIC_SIZE: 4,
      HEADER_SIZE: 124,
      HEADER_DX10_SIZE: 20,
      PIXEL_FORMAT_FLAGS: {
        // PIXEL_FORMAT flags
        // https://github.com/Microsoft/DirectXTex/blob/main/DirectXTex/DDS.h
        // https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-pixelformat
        ALPHAPIXELS: 1,
        ALPHA: 2,
        FOURCC: 4,
        RGB: 64,
        RGBA: 65,
        YUV: 512,
        LUMINANCE: 131072,
        LUMINANCEA: 131073
      },
      RESOURCE_MISC_TEXTURECUBE: 4,
      HEADER_FIELDS: DDS_HEADER_FIELDS,
      HEADER_DX10_FIELDS: DDS_DX10_FIELDS,
      DXGI_FORMAT,
      D3D10_RESOURCE_DIMENSION,
      D3DFMT
    };
    const TEXTURE_FORMAT_BLOCK_SIZE = {
      "bc1-rgba-unorm": 8,
      "bc1-rgba-unorm-srgb": 8,
      "bc2-rgba-unorm": 16,
      "bc2-rgba-unorm-srgb": 16,
      "bc3-rgba-unorm": 16,
      "bc3-rgba-unorm-srgb": 16,
      "bc4-r-unorm": 8,
      "bc4-r-snorm": 8,
      "bc5-rg-unorm": 16,
      "bc5-rg-snorm": 16,
      "bc6h-rgb-ufloat": 16,
      "bc6h-rgb-float": 16,
      "bc7-rgba-unorm": 16,
      "bc7-rgba-unorm-srgb": 16
    };

    "use strict";
    function parseDDS(arrayBuffer, supportedFormats) {
      const {
        format,
        fourCC,
        width,
        height,
        dataOffset,
        mipmapCount
      } = parseDDSHeader(arrayBuffer);
      if (!supportedFormats.includes(format)) {
        throw new Error(`Unsupported texture format: ${fourCC} ${format}, supported: ${supportedFormats}`);
      }
      if (mipmapCount <= 1) {
        return {
          format,
          width,
          height,
          resource: [new Uint8Array(arrayBuffer, dataOffset)],
          alphaMode: "no-premultiply-alpha"
        };
      }
      const levelBuffers = getMipmapLevelBuffers(format, width, height, dataOffset, mipmapCount, arrayBuffer);
      const textureOptions = {
        format,
        width,
        height,
        resource: levelBuffers,
        alphaMode: "no-premultiply-alpha"
      };
      return textureOptions;
    }
    function getMipmapLevelBuffers(format, width, height, dataOffset, mipmapCount, arrayBuffer) {
      const levelBuffers = [];
      const blockBytes = TEXTURE_FORMAT_BLOCK_SIZE[format];
      let mipWidth = width;
      let mipHeight = height;
      let offset = dataOffset;
      for (let level = 0; level < mipmapCount; ++level) {
        const alignedWidth = Math.ceil(Math.max(4, mipWidth) / 4) * 4;
        const alignedHeight = Math.ceil(Math.max(4, mipHeight) / 4) * 4;
        const byteLength = blockBytes ? alignedWidth / 4 * alignedHeight / 4 * blockBytes : mipWidth * mipHeight * 4;
        const levelBuffer = new Uint8Array(arrayBuffer, offset, byteLength);
        levelBuffers.push(levelBuffer);
        offset += byteLength;
        mipWidth = Math.max(mipWidth >> 1, 1);
        mipHeight = Math.max(mipHeight >> 1, 1);
      }
      return levelBuffers;
    }
    function parseDDSHeader(buffer) {
      const header = new Uint32Array(buffer, 0, DDS.HEADER_SIZE / Uint32Array.BYTES_PER_ELEMENT);
      if (header[DDS.HEADER_FIELDS.MAGIC] !== DDS.MAGIC_VALUE) {
        throw new Error("Invalid magic number in DDS header");
      }
      const height = header[DDS.HEADER_FIELDS.HEIGHT];
      const width = header[DDS.HEADER_FIELDS.WIDTH];
      const mipmapCount = Math.max(1, header[DDS.HEADER_FIELDS.MIPMAP_COUNT]);
      const flags = header[DDS.HEADER_FIELDS.PF_FLAGS];
      const fourCC = header[DDS.HEADER_FIELDS.FOURCC];
      const format = getTextureFormat(header, flags, fourCC, buffer);
      const dataOffset = DDS.MAGIC_SIZE + DDS.HEADER_SIZE + (fourCC === DDS.D3DFMT.DX10 ? DDS.HEADER_DX10_SIZE : 0);
      return {
        format,
        fourCC,
        width,
        height,
        dataOffset,
        mipmapCount
      };
    }
    function getTextureFormat(header, flags, fourCC, buffer) {
      if (flags & DDS.PIXEL_FORMAT_FLAGS.FOURCC) {
        if (fourCC === DDS.D3DFMT.DX10) {
          const dx10Header = new Uint32Array(
            buffer,
            DDS.MAGIC_SIZE + DDS.HEADER_SIZE,
            // there is a 20-byte DDS_HEADER_DX10 after DDS_HEADER
            DDS.HEADER_DX10_SIZE / Uint32Array.BYTES_PER_ELEMENT
          );
          const miscFlag = dx10Header[DDS.HEADER_DX10_FIELDS.MISC_FLAG];
          if (miscFlag === DDS.RESOURCE_MISC_TEXTURECUBE) {
            throw new Error("DDSParser does not support cubemap textures");
          }
          const resourceDimension = dx10Header[DDS.HEADER_DX10_FIELDS.RESOURCE_DIMENSION];
          if (resourceDimension === DDS.D3D10_RESOURCE_DIMENSION.DDS_DIMENSION_TEXTURE3D) {
            throw new Error("DDSParser does not supported 3D texture data");
          }
          const dxgiFormat = dx10Header[DDS.HEADER_DX10_FIELDS.DXGI_FORMAT];
          if (dxgiFormat in DXGI_TO_TEXTURE_FORMAT) {
            return DXGI_TO_TEXTURE_FORMAT[dxgiFormat];
          }
          throw new Error(`DDSParser cannot parse texture data with DXGI format ${dxgiFormat}`);
        }
        if (fourCC in FOURCC_TO_TEXTURE_FORMAT) {
          return FOURCC_TO_TEXTURE_FORMAT[fourCC];
        }
        throw new Error(`DDSParser cannot parse texture data with fourCC format ${fourCC}`);
      }
      if (flags & DDS.PIXEL_FORMAT_FLAGS.RGB || flags & DDS.PIXEL_FORMAT_FLAGS.RGBA) {
        return getUncompressedTextureFormat(header);
      }
      if (flags & DDS.PIXEL_FORMAT_FLAGS.YUV) {
        throw new Error("DDSParser does not supported YUV uncompressed texture data.");
      }
      if (flags & DDS.PIXEL_FORMAT_FLAGS.LUMINANCE || flags & DDS.PIXEL_FORMAT_FLAGS.LUMINANCEA) {
        throw new Error("DDSParser does not support single-channel (lumninance) texture data!");
      }
      if (flags & DDS.PIXEL_FORMAT_FLAGS.ALPHA || flags & DDS.PIXEL_FORMAT_FLAGS.ALPHAPIXELS) {
        throw new Error("DDSParser does not support single-channel (alpha) texture data!");
      }
      throw new Error("DDSParser failed to load a texture file due to an unknown reason!");
    }
    function getUncompressedTextureFormat(header) {
      const bitCount = header[DDS.HEADER_FIELDS.RGB_BITCOUNT];
      const rBitMask = header[DDS.HEADER_FIELDS.R_BIT_MASK];
      const gBitMask = header[DDS.HEADER_FIELDS.G_BIT_MASK];
      const bBitMask = header[DDS.HEADER_FIELDS.B_BIT_MASK];
      const aBitMask = header[DDS.HEADER_FIELDS.A_BIT_MASK];
      switch (bitCount) {
        case 32:
          if (rBitMask === 255 && gBitMask === 65280 && bBitMask === 16711680 && aBitMask === 4278190080) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM];
          }
          if (rBitMask === 16711680 && gBitMask === 65280 && bBitMask === 255 && aBitMask === 4278190080) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM];
          }
          if (rBitMask === 1072693248 && gBitMask === 1047552 && bBitMask === 1023 && aBitMask === 3221225472) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM];
          }
          if (rBitMask === 65535 && gBitMask === 4294901760 && bBitMask === 0 && aBitMask === 0) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R16G16_UNORM];
          }
          if (rBitMask === 4294967295 && gBitMask === 0 && bBitMask === 0 && aBitMask === 0) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT];
          }
          break;
        case 24:
          if (rBitMask === 16711680 && gBitMask === 65280 && bBitMask === 255 && aBitMask === 32768) {
          }
          break;
        case 16:
          if (rBitMask === 31744 && gBitMask === 992 && bBitMask === 31 && aBitMask === 32768) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM];
          }
          if (rBitMask === 63488 && gBitMask === 2016 && bBitMask === 31 && aBitMask === 0) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM];
          }
          if (rBitMask === 3840 && gBitMask === 240 && bBitMask === 15 && aBitMask === 61440) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM];
          }
          if (rBitMask === 255 && gBitMask === 0 && bBitMask === 0 && aBitMask === 65280) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM];
          }
          if (rBitMask === 65535 && gBitMask === 0 && bBitMask === 0 && aBitMask === 0) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM];
          }
          break;
        case 8:
          if (rBitMask === 255 && gBitMask === 0 && bBitMask === 0 && aBitMask === 0) {
            return DXGI_TO_TEXTURE_FORMAT[DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM];
          }
          break;
      }
      throw new Error(`DDSParser does not support uncompressed texture with configuration:
                bitCount = ${bitCount}, rBitMask = ${rBitMask}, gBitMask = ${gBitMask}, aBitMask = ${aBitMask}`);
    }

    "use strict";
    const loadDDS = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.High,
        name: "loadDDS"
      },
      /** used for deprecation purposes */
      name: "loadDDS",
      id: "dds",
      test(url) {
        return checkExtension(url, [".dds"]);
      },
      async load(url, _asset, loader) {
        const supportedTextures = await getSupportedTextureFormats();
        const ddsResponse = await fetch(url);
        const ddsArrayBuffer = await ddsResponse.arrayBuffer();
        const textureOptions = parseDDS(ddsArrayBuffer, supportedTextures);
        const compressedTextureSource = new CompressedSource(textureOptions);
        return createTexture(compressedTextureSource, loader, url);
      },
      unload(texture) {
        if (Array.isArray(texture)) {
          texture.forEach((t) => t.destroy(true));
        } else {
          texture.destroy(true);
        }
      }
    };

    "use strict";
    var GL_INTERNAL_FORMAT = /* @__PURE__ */ ((GL_INTERNAL_FORMAT2) => {
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["RGBA8_SNORM"] = 36759] = "RGBA8_SNORM";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["RGBA"] = 6408] = "RGBA";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["RGBA8UI"] = 36220] = "RGBA8UI";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["SRGB8_ALPHA8"] = 35907] = "SRGB8_ALPHA8";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["RGBA8I"] = 36238] = "RGBA8I";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["RGBA8"] = 32856] = "RGBA8";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGB_S3TC_DXT1_EXT"] = 33776] = "COMPRESSED_RGB_S3TC_DXT1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_S3TC_DXT1_EXT"] = 33777] = "COMPRESSED_RGBA_S3TC_DXT1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_S3TC_DXT3_EXT"] = 33778] = "COMPRESSED_RGBA_S3TC_DXT3_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_S3TC_DXT5_EXT"] = 33779] = "COMPRESSED_RGBA_S3TC_DXT5_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT"] = 35917] = "COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT"] = 35918] = "COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"] = 35919] = "COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB_S3TC_DXT1_EXT"] = 35916] = "COMPRESSED_SRGB_S3TC_DXT1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RED_RGTC1_EXT"] = 36283] = "COMPRESSED_RED_RGTC1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SIGNED_RED_RGTC1_EXT"] = 36284] = "COMPRESSED_SIGNED_RED_RGTC1_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RED_GREEN_RGTC2_EXT"] = 36285] = "COMPRESSED_RED_GREEN_RGTC2_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT"] = 36286] = "COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_R11_EAC"] = 37488] = "COMPRESSED_R11_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SIGNED_R11_EAC"] = 37489] = "COMPRESSED_SIGNED_R11_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RG11_EAC"] = 37490] = "COMPRESSED_RG11_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SIGNED_RG11_EAC"] = 37491] = "COMPRESSED_SIGNED_RG11_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGB8_ETC2"] = 37492] = "COMPRESSED_RGB8_ETC2";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA8_ETC2_EAC"] = 37496] = "COMPRESSED_RGBA8_ETC2_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ETC2"] = 37493] = "COMPRESSED_SRGB8_ETC2";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"] = 37497] = "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"] = 37494] = "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"] = 37495] = "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_4x4_KHR"] = 37808] = "COMPRESSED_RGBA_ASTC_4x4_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_5x4_KHR"] = 37809] = "COMPRESSED_RGBA_ASTC_5x4_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_5x5_KHR"] = 37810] = "COMPRESSED_RGBA_ASTC_5x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_6x5_KHR"] = 37811] = "COMPRESSED_RGBA_ASTC_6x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_6x6_KHR"] = 37812] = "COMPRESSED_RGBA_ASTC_6x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_8x5_KHR"] = 37813] = "COMPRESSED_RGBA_ASTC_8x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_8x6_KHR"] = 37814] = "COMPRESSED_RGBA_ASTC_8x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_8x8_KHR"] = 37815] = "COMPRESSED_RGBA_ASTC_8x8_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_10x5_KHR"] = 37816] = "COMPRESSED_RGBA_ASTC_10x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_10x6_KHR"] = 37817] = "COMPRESSED_RGBA_ASTC_10x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_10x8_KHR"] = 37818] = "COMPRESSED_RGBA_ASTC_10x8_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_10x10_KHR"] = 37819] = "COMPRESSED_RGBA_ASTC_10x10_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_12x10_KHR"] = 37820] = "COMPRESSED_RGBA_ASTC_12x10_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_ASTC_12x12_KHR"] = 37821] = "COMPRESSED_RGBA_ASTC_12x12_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"] = 37840] = "COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"] = 37841] = "COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"] = 37842] = "COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"] = 37843] = "COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"] = 37844] = "COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"] = 37845] = "COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"] = 37846] = "COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"] = 37847] = "COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"] = 37848] = "COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"] = 37849] = "COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"] = 37850] = "COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"] = 37851] = "COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"] = 37852] = "COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"] = 37853] = "COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGBA_BPTC_UNORM_EXT"] = 36492] = "COMPRESSED_RGBA_BPTC_UNORM_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT"] = 36493] = "COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT"] = 36494] = "COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT";
      GL_INTERNAL_FORMAT2[GL_INTERNAL_FORMAT2["COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT"] = 36495] = "COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT";
      return GL_INTERNAL_FORMAT2;
    })(GL_INTERNAL_FORMAT || {});
    var GL_FORMATS$1 = /* @__PURE__ */ ((GL_FORMATS2) => {
      GL_FORMATS2[GL_FORMATS2["RGBA"] = 6408] = "RGBA";
      GL_FORMATS2[GL_FORMATS2["RGB"] = 6407] = "RGB";
      GL_FORMATS2[GL_FORMATS2["RG"] = 33319] = "RG";
      GL_FORMATS2[GL_FORMATS2["RED"] = 6403] = "RED";
      GL_FORMATS2[GL_FORMATS2["RGBA_INTEGER"] = 36249] = "RGBA_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RGB_INTEGER"] = 36248] = "RGB_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RG_INTEGER"] = 33320] = "RG_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RED_INTEGER"] = 36244] = "RED_INTEGER";
      GL_FORMATS2[GL_FORMATS2["ALPHA"] = 6406] = "ALPHA";
      GL_FORMATS2[GL_FORMATS2["LUMINANCE"] = 6409] = "LUMINANCE";
      GL_FORMATS2[GL_FORMATS2["LUMINANCE_ALPHA"] = 6410] = "LUMINANCE_ALPHA";
      GL_FORMATS2[GL_FORMATS2["DEPTH_COMPONENT"] = 6402] = "DEPTH_COMPONENT";
      GL_FORMATS2[GL_FORMATS2["DEPTH_STENCIL"] = 34041] = "DEPTH_STENCIL";
      return GL_FORMATS2;
    })(GL_FORMATS$1 || {});
    var GL_TYPES$1 = /* @__PURE__ */ ((GL_TYPES2) => {
      GL_TYPES2[GL_TYPES2["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_6_5"] = 33635] = "UNSIGNED_SHORT_5_6_5";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_4_4_4_4"] = 32819] = "UNSIGNED_SHORT_4_4_4_4";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_5_5_1"] = 32820] = "UNSIGNED_SHORT_5_5_5_1";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT"] = 5125] = "UNSIGNED_INT";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_10F_11F_11F_REV"] = 35899] = "UNSIGNED_INT_10F_11F_11F_REV";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_2_10_10_10_REV"] = 33640] = "UNSIGNED_INT_2_10_10_10_REV";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_24_8"] = 34042] = "UNSIGNED_INT_24_8";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_5_9_9_9_REV"] = 35902] = "UNSIGNED_INT_5_9_9_9_REV";
      GL_TYPES2[GL_TYPES2["BYTE"] = 5120] = "BYTE";
      GL_TYPES2[GL_TYPES2["SHORT"] = 5122] = "SHORT";
      GL_TYPES2[GL_TYPES2["INT"] = 5124] = "INT";
      GL_TYPES2[GL_TYPES2["FLOAT"] = 5126] = "FLOAT";
      GL_TYPES2[GL_TYPES2["FLOAT_32_UNSIGNED_INT_24_8_REV"] = 36269] = "FLOAT_32_UNSIGNED_INT_24_8_REV";
      GL_TYPES2[GL_TYPES2["HALF_FLOAT"] = 36193] = "HALF_FLOAT";
      return GL_TYPES2;
    })(GL_TYPES$1 || {});
    const INTERNAL_FORMAT_TO_TEXTURE_FORMATS = {
      [33776 /* COMPRESSED_RGB_S3TC_DXT1_EXT */]: "bc1-rgba-unorm",
      // TODO: ???
      [33777 /* COMPRESSED_RGBA_S3TC_DXT1_EXT */]: "bc1-rgba-unorm",
      [33778 /* COMPRESSED_RGBA_S3TC_DXT3_EXT */]: "bc2-rgba-unorm",
      [33779 /* COMPRESSED_RGBA_S3TC_DXT5_EXT */]: "bc3-rgba-unorm",
      [35916 /* COMPRESSED_SRGB_S3TC_DXT1_EXT */]: "bc1-rgba-unorm-srgb",
      // TODO: ???
      [35917 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT */]: "bc1-rgba-unorm-srgb",
      [35918 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT */]: "bc2-rgba-unorm-srgb",
      [35919 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT */]: "bc3-rgba-unorm-srgb",
      [36283 /* COMPRESSED_RED_RGTC1_EXT */]: "bc4-r-unorm",
      [36284 /* COMPRESSED_SIGNED_RED_RGTC1_EXT */]: "bc4-r-snorm",
      [36285 /* COMPRESSED_RED_GREEN_RGTC2_EXT */]: "bc5-rg-unorm",
      [36286 /* COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT */]: "bc5-rg-snorm",
      [37488 /* COMPRESSED_R11_EAC */]: "eac-r11unorm",
      // [GL_INTERNAL_FORMAT.COMPRESSED_SIGNED_R11_EAC]: 'eac-r11snorm',
      [37490 /* COMPRESSED_RG11_EAC */]: "eac-rg11snorm",
      // [GL_INTERNAL_FORMAT.COMPRESSED_SIGNED_RG11_EAC]: 'eac-rg11unorm',
      [37492 /* COMPRESSED_RGB8_ETC2 */]: "etc2-rgb8unorm",
      [37496 /* COMPRESSED_RGBA8_ETC2_EAC */]: "etc2-rgba8unorm",
      [37493 /* COMPRESSED_SRGB8_ETC2 */]: "etc2-rgb8unorm-srgb",
      [37497 /* COMPRESSED_SRGB8_ALPHA8_ETC2_EAC */]: "etc2-rgba8unorm-srgb",
      [37494 /* COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 */]: "etc2-rgb8a1unorm",
      [37495 /* COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 */]: "etc2-rgb8a1unorm-srgb",
      [37808 /* COMPRESSED_RGBA_ASTC_4x4_KHR */]: "astc-4x4-unorm",
      [37840 /* COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */]: "astc-4x4-unorm-srgb",
      [37809 /* COMPRESSED_RGBA_ASTC_5x4_KHR */]: "astc-5x4-unorm",
      [37841 /* COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR */]: "astc-5x4-unorm-srgb",
      [37810 /* COMPRESSED_RGBA_ASTC_5x5_KHR */]: "astc-5x5-unorm",
      [37842 /* COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR */]: "astc-5x5-unorm-srgb",
      [37811 /* COMPRESSED_RGBA_ASTC_6x5_KHR */]: "astc-6x5-unorm",
      [37843 /* COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR */]: "astc-6x5-unorm-srgb",
      [37812 /* COMPRESSED_RGBA_ASTC_6x6_KHR */]: "astc-6x6-unorm",
      [37844 /* COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR */]: "astc-6x6-unorm-srgb",
      [37813 /* COMPRESSED_RGBA_ASTC_8x5_KHR */]: "astc-8x5-unorm",
      [37845 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR */]: "astc-8x5-unorm-srgb",
      [37814 /* COMPRESSED_RGBA_ASTC_8x6_KHR */]: "astc-8x6-unorm",
      [37846 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR */]: "astc-8x6-unorm-srgb",
      [37815 /* COMPRESSED_RGBA_ASTC_8x8_KHR */]: "astc-8x8-unorm",
      [37847 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR */]: "astc-8x8-unorm-srgb",
      [37816 /* COMPRESSED_RGBA_ASTC_10x5_KHR */]: "astc-10x5-unorm",
      [37848 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR */]: "astc-10x5-unorm-srgb",
      [37817 /* COMPRESSED_RGBA_ASTC_10x6_KHR */]: "astc-10x6-unorm",
      [37849 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR */]: "astc-10x6-unorm-srgb",
      [37818 /* COMPRESSED_RGBA_ASTC_10x8_KHR */]: "astc-10x8-unorm",
      [37850 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR */]: "astc-10x8-unorm-srgb",
      [37819 /* COMPRESSED_RGBA_ASTC_10x10_KHR */]: "astc-10x10-unorm",
      [37851 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR */]: "astc-10x10-unorm-srgb",
      [37820 /* COMPRESSED_RGBA_ASTC_12x10_KHR */]: "astc-12x10-unorm",
      [37852 /* COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR */]: "astc-12x10-unorm-srgb",
      [37821 /* COMPRESSED_RGBA_ASTC_12x12_KHR */]: "astc-12x12-unorm",
      [37853 /* COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR */]: "astc-12x12-unorm-srgb",
      [36492 /* COMPRESSED_RGBA_BPTC_UNORM_EXT */]: "bc7-rgba-unorm",
      [36493 /* COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT */]: "bc7-rgba-unorm-srgb",
      [36494 /* COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT */]: "bc6h-rgb-float",
      [36495 /* COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT */]: "bc6h-rgb-ufloat",
      [35907 /* SRGB8_ALPHA8 */]: "rgba8unorm-srgb",
      [36759 /* RGBA8_SNORM */]: "rgba8snorm",
      [36220 /* RGBA8UI */]: "rgba8uint",
      [36238 /* RGBA8I */]: "rgba8sint",
      [6408 /* RGBA */]: "rgba8unorm"
      // [GL_INTERNAL_FORMAT.RGBA8]: 'bgra8unorm'
    };
    const FILE_IDENTIFIER = [171, 75, 84, 88, 32, 49, 49, 187, 13, 10, 26, 10];
    const FIELDS = {
      FILE_IDENTIFIER: 0,
      ENDIANNESS: 12,
      GL_TYPE: 16,
      GL_TYPE_SIZE: 20,
      GL_FORMAT: 24,
      GL_INTERNAL_FORMAT: 28,
      GL_BASE_INTERNAL_FORMAT: 32,
      PIXEL_WIDTH: 36,
      PIXEL_HEIGHT: 40,
      PIXEL_DEPTH: 44,
      NUMBER_OF_ARRAY_ELEMENTS: 48,
      NUMBER_OF_FACES: 52,
      NUMBER_OF_MIPMAP_LEVELS: 56,
      BYTES_OF_KEY_VALUE_DATA: 60
    };
    const FILE_HEADER_SIZE = 64;
    const ENDIANNESS = 67305985;
    const TYPES_TO_BYTES_PER_COMPONENT = {
      [5121 /* UNSIGNED_BYTE */]: 1,
      [5123 /* UNSIGNED_SHORT */]: 2,
      [5124 /* INT */]: 4,
      [5125 /* UNSIGNED_INT */]: 4,
      [5126 /* FLOAT */]: 4,
      [36193 /* HALF_FLOAT */]: 8
    };
    const FORMATS_TO_COMPONENTS = {
      [6408 /* RGBA */]: 4,
      [6407 /* RGB */]: 3,
      [33319 /* RG */]: 2,
      [6403 /* RED */]: 1,
      [6409 /* LUMINANCE */]: 1,
      [6410 /* LUMINANCE_ALPHA */]: 2,
      [6406 /* ALPHA */]: 1
    };
    const TYPES_TO_BYTES_PER_PIXEL = {
      [32819 /* UNSIGNED_SHORT_4_4_4_4 */]: 2,
      [32820 /* UNSIGNED_SHORT_5_5_5_1 */]: 2,
      [33635 /* UNSIGNED_SHORT_5_6_5 */]: 2
    };
    const INTERNAL_FORMAT_TO_BYTES_PER_PIXEL = {
      [33776 /* COMPRESSED_RGB_S3TC_DXT1_EXT */]: 0.5,
      [33777 /* COMPRESSED_RGBA_S3TC_DXT1_EXT */]: 0.5,
      [33778 /* COMPRESSED_RGBA_S3TC_DXT3_EXT */]: 1,
      [33779 /* COMPRESSED_RGBA_S3TC_DXT5_EXT */]: 1,
      [35916 /* COMPRESSED_SRGB_S3TC_DXT1_EXT */]: 0.5,
      [35917 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT */]: 0.5,
      [35918 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT */]: 1,
      [35919 /* COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT */]: 1,
      [36283 /* COMPRESSED_RED_RGTC1_EXT */]: 0.5,
      [36284 /* COMPRESSED_SIGNED_RED_RGTC1_EXT */]: 0.5,
      [36285 /* COMPRESSED_RED_GREEN_RGTC2_EXT */]: 1,
      [36286 /* COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT */]: 1,
      [37488 /* COMPRESSED_R11_EAC */]: 0.5,
      [37489 /* COMPRESSED_SIGNED_R11_EAC */]: 0.5,
      [37490 /* COMPRESSED_RG11_EAC */]: 1,
      [37491 /* COMPRESSED_SIGNED_RG11_EAC */]: 1,
      [37492 /* COMPRESSED_RGB8_ETC2 */]: 0.5,
      [37496 /* COMPRESSED_RGBA8_ETC2_EAC */]: 1,
      [37493 /* COMPRESSED_SRGB8_ETC2 */]: 0.5,
      [37497 /* COMPRESSED_SRGB8_ALPHA8_ETC2_EAC */]: 1,
      [37494 /* COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 */]: 0.5,
      [37495 /* COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 */]: 0.5,
      [37808 /* COMPRESSED_RGBA_ASTC_4x4_KHR */]: 1,
      [37840 /* COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */]: 1,
      [37809 /* COMPRESSED_RGBA_ASTC_5x4_KHR */]: 0.8,
      [37841 /* COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR */]: 0.8,
      [37810 /* COMPRESSED_RGBA_ASTC_5x5_KHR */]: 0.64,
      [37842 /* COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR */]: 0.64,
      [37811 /* COMPRESSED_RGBA_ASTC_6x5_KHR */]: 0.53375,
      [37843 /* COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR */]: 0.53375,
      [37812 /* COMPRESSED_RGBA_ASTC_6x6_KHR */]: 0.445,
      [37844 /* COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR */]: 0.445,
      [37813 /* COMPRESSED_RGBA_ASTC_8x5_KHR */]: 0.4,
      [37845 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR */]: 0.4,
      [37814 /* COMPRESSED_RGBA_ASTC_8x6_KHR */]: 0.33375,
      [37846 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR */]: 0.33375,
      [37815 /* COMPRESSED_RGBA_ASTC_8x8_KHR */]: 0.25,
      [37847 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR */]: 0.25,
      [37816 /* COMPRESSED_RGBA_ASTC_10x5_KHR */]: 0.32,
      [37848 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR */]: 0.32,
      [37817 /* COMPRESSED_RGBA_ASTC_10x6_KHR */]: 0.26625,
      [37849 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR */]: 0.26625,
      [37818 /* COMPRESSED_RGBA_ASTC_10x8_KHR */]: 0.2,
      [37850 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR */]: 0.2,
      [37819 /* COMPRESSED_RGBA_ASTC_10x10_KHR */]: 0.16,
      [37851 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR */]: 0.16,
      [37820 /* COMPRESSED_RGBA_ASTC_12x10_KHR */]: 0.13375,
      [37852 /* COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR */]: 0.13375,
      [37821 /* COMPRESSED_RGBA_ASTC_12x12_KHR */]: 0.11125,
      [37853 /* COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR */]: 0.11125,
      [36492 /* COMPRESSED_RGBA_BPTC_UNORM_EXT */]: 1,
      [36493 /* COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT */]: 1,
      [36494 /* COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT */]: 1,
      [36495 /* COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT */]: 1
    };
    const KTX = {
      FILE_HEADER_SIZE,
      FILE_IDENTIFIER,
      FORMATS_TO_COMPONENTS,
      INTERNAL_FORMAT_TO_BYTES_PER_PIXEL,
      INTERNAL_FORMAT_TO_TEXTURE_FORMATS,
      FIELDS,
      TYPES_TO_BYTES_PER_COMPONENT,
      TYPES_TO_BYTES_PER_PIXEL,
      ENDIANNESS
    };

    "use strict";
    function parseKTX(arrayBuffer, supportedFormats) {
      const dataView = new DataView(arrayBuffer);
      if (!validate(dataView)) {
        throw new Error("Invalid KTX identifier in header");
      }
      const {
        littleEndian,
        glType,
        glFormat,
        glInternalFormat,
        pixelWidth,
        pixelHeight,
        numberOfMipmapLevels,
        offset
      } = parseKTXHeader(dataView);
      const textureFormat = KTX.INTERNAL_FORMAT_TO_TEXTURE_FORMATS[glInternalFormat];
      if (!textureFormat) {
        throw new Error(`Unknown texture format ${glInternalFormat}`);
      }
      if (!supportedFormats.includes(textureFormat)) {
        throw new Error(`Unsupported texture format: ${textureFormat}, supportedFormats: ${supportedFormats}`);
      }
      const imagePixelByteSize = getImagePixelByteSize(glType, glFormat, glInternalFormat);
      const imageBuffers = getImageBuffers(
        dataView,
        glType,
        imagePixelByteSize,
        pixelWidth,
        pixelHeight,
        offset,
        numberOfMipmapLevels,
        littleEndian
      );
      return {
        format: textureFormat,
        width: pixelWidth,
        height: pixelHeight,
        resource: imageBuffers,
        alphaMode: "no-premultiply-alpha"
      };
    }
    function getImageBuffers(dataView, glType, imagePixelByteSize, pixelWidth, pixelHeight, offset, numberOfMipmapLevels, littleEndian) {
      const alignedWidth = pixelWidth + 3 & ~3;
      const alignedHeight = pixelHeight + 3 & ~3;
      let imagePixels = pixelWidth * pixelHeight;
      if (glType === 0) {
        imagePixels = alignedWidth * alignedHeight;
      }
      let mipByteSize = imagePixels * imagePixelByteSize;
      let mipWidth = pixelWidth;
      let mipHeight = pixelHeight;
      let alignedMipWidth = alignedWidth;
      let alignedMipHeight = alignedHeight;
      let imageOffset = offset;
      const imageBuffers = new Array(numberOfMipmapLevels);
      for (let mipmapLevel = 0; mipmapLevel < numberOfMipmapLevels; mipmapLevel++) {
        const imageSize = dataView.getUint32(imageOffset, littleEndian);
        let elementOffset = imageOffset + 4;
        imageBuffers[mipmapLevel] = new Uint8Array(dataView.buffer, elementOffset, mipByteSize);
        elementOffset += mipByteSize;
        imageOffset += imageSize + 4;
        imageOffset = imageOffset % 4 !== 0 ? imageOffset + 4 - imageOffset % 4 : imageOffset;
        mipWidth = mipWidth >> 1 || 1;
        mipHeight = mipHeight >> 1 || 1;
        alignedMipWidth = mipWidth + 4 - 1 & ~(4 - 1);
        alignedMipHeight = mipHeight + 4 - 1 & ~(4 - 1);
        mipByteSize = alignedMipWidth * alignedMipHeight * imagePixelByteSize;
      }
      return imageBuffers;
    }
    function getImagePixelByteSize(glType, glFormat, glInternalFormat) {
      let imagePixelByteSize = KTX.INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[glInternalFormat];
      if (glType !== 0) {
        if (KTX.TYPES_TO_BYTES_PER_COMPONENT[glType]) {
          imagePixelByteSize = KTX.TYPES_TO_BYTES_PER_COMPONENT[glType] * KTX.FORMATS_TO_COMPONENTS[glFormat];
        } else {
          imagePixelByteSize = KTX.TYPES_TO_BYTES_PER_PIXEL[glType];
        }
      }
      if (imagePixelByteSize === void 0) {
        throw new Error("Unable to resolve the pixel format stored in the *.ktx file!");
      }
      return imagePixelByteSize;
    }
    function parseKTXHeader(dataView) {
      const littleEndian = dataView.getUint32(KTX.FIELDS.ENDIANNESS, true) === KTX.ENDIANNESS;
      const glType = dataView.getUint32(KTX.FIELDS.GL_TYPE, littleEndian);
      const glFormat = dataView.getUint32(KTX.FIELDS.GL_FORMAT, littleEndian);
      const glInternalFormat = dataView.getUint32(KTX.FIELDS.GL_INTERNAL_FORMAT, littleEndian);
      const pixelWidth = dataView.getUint32(KTX.FIELDS.PIXEL_WIDTH, littleEndian);
      const pixelHeight = dataView.getUint32(KTX.FIELDS.PIXEL_HEIGHT, littleEndian) || 1;
      const pixelDepth = dataView.getUint32(KTX.FIELDS.PIXEL_DEPTH, littleEndian) || 1;
      const numberOfArrayElements = dataView.getUint32(KTX.FIELDS.NUMBER_OF_ARRAY_ELEMENTS, littleEndian) || 1;
      const numberOfFaces = dataView.getUint32(KTX.FIELDS.NUMBER_OF_FACES, littleEndian);
      const numberOfMipmapLevels = dataView.getUint32(KTX.FIELDS.NUMBER_OF_MIPMAP_LEVELS, littleEndian);
      const bytesOfKeyValueData = dataView.getUint32(KTX.FIELDS.BYTES_OF_KEY_VALUE_DATA, littleEndian);
      if (pixelHeight === 0 || pixelDepth !== 1) {
        throw new Error("Only 2D textures are supported");
      }
      if (numberOfFaces !== 1) {
        throw new Error("CubeTextures are not supported by KTXLoader yet!");
      }
      if (numberOfArrayElements !== 1) {
        throw new Error("WebGL does not support array textures");
      }
      return {
        littleEndian,
        glType,
        glFormat,
        glInternalFormat,
        pixelWidth,
        pixelHeight,
        numberOfMipmapLevels,
        offset: KTX.FILE_HEADER_SIZE + bytesOfKeyValueData
      };
    }
    function validate(dataView) {
      for (let i = 0; i < KTX.FILE_IDENTIFIER.length; i++) {
        if (dataView.getUint8(i) !== KTX.FILE_IDENTIFIER[i]) {
          return false;
        }
      }
      return true;
    }

    "use strict";
    const loadKTX = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.High,
        name: "loadKTX"
      },
      /** used for deprecation purposes */
      name: "loadKTX",
      id: "ktx",
      test(url) {
        return checkExtension(url, ".ktx");
      },
      async load(url, _asset, loader) {
        const supportedTextures = await getSupportedTextureFormats();
        const ktxResponse = await fetch(url);
        const ktxArrayBuffer = await ktxResponse.arrayBuffer();
        const textureOptions = parseKTX(ktxArrayBuffer, supportedTextures);
        const compressedTextureSource = new CompressedSource(textureOptions);
        return createTexture(compressedTextureSource, loader, url);
      },
      unload(texture) {
        if (Array.isArray(texture)) {
          texture.forEach((t) => t.destroy(true));
        } else {
          texture.destroy(true);
        }
      }
    };

    const WORKER_CODE = "(function () {\n    'use strict';\n\n    const converters = {\n      rgb8unorm: {\n        convertedFormat: \"rgba8unorm\",\n        convertFunction: convertRGBtoRGBA\n      },\n      \"rgb8unorm-srgb\": {\n        convertedFormat: \"rgba8unorm-srgb\",\n        convertFunction: convertRGBtoRGBA\n      }\n    };\n    function convertFormatIfRequired(textureOptions) {\n      const format = textureOptions.format;\n      if (converters[format]) {\n        const convertFunction = converters[format].convertFunction;\n        const levelBuffers = textureOptions.resource;\n        for (let i = 0; i < levelBuffers.length; i++) {\n          levelBuffers[i] = convertFunction(levelBuffers[i]);\n        }\n        textureOptions.format = converters[format].convertedFormat;\n      }\n    }\n    function convertRGBtoRGBA(levelBuffer) {\n      const pixelCount = levelBuffer.byteLength / 3;\n      const levelBufferWithAlpha = new Uint32Array(pixelCount);\n      for (let i = 0; i < pixelCount; ++i) {\n        levelBufferWithAlpha[i] = levelBuffer[i * 3] + (levelBuffer[i * 3 + 1] << 8) + (levelBuffer[i * 3 + 2] << 16) + 4278190080;\n      }\n      return new Uint8Array(levelBufferWithAlpha.buffer);\n    }\n\n    function createLevelBuffersFromKTX(ktxTexture) {\n      const levelBuffers = [];\n      for (let i = 0; i < ktxTexture.numLevels; i++) {\n        const imageData = ktxTexture.getImageData(i, 0, 0);\n        const levelBuffer = new Uint8Array(imageData.byteLength);\n        levelBuffer.set(imageData);\n        levelBuffers.push(levelBuffer);\n      }\n      return levelBuffers;\n    }\n\n    const glFormatToGPUFormatMap = {\n      6408: \"rgba8unorm\",\n      32856: \"bgra8unorm\",\n      //\n      32857: \"rgb10a2unorm\",\n      33189: \"depth16unorm\",\n      33190: \"depth24plus\",\n      33321: \"r8unorm\",\n      33323: \"rg8unorm\",\n      33325: \"r16float\",\n      33326: \"r32float\",\n      33327: \"rg16float\",\n      33328: \"rg32float\",\n      33329: \"r8sint\",\n      33330: \"r8uint\",\n      33331: \"r16sint\",\n      33332: \"r16uint\",\n      33333: \"r32sint\",\n      33334: \"r32uint\",\n      33335: \"rg8sint\",\n      33336: \"rg8uint\",\n      33337: \"rg16sint\",\n      33338: \"rg16uint\",\n      33339: \"rg32sint\",\n      33340: \"rg32uint\",\n      33778: \"bc2-rgba-unorm\",\n      33779: \"bc3-rgba-unorm\",\n      34836: \"rgba32float\",\n      34842: \"rgba16float\",\n      35056: \"depth24plus-stencil8\",\n      35898: \"rg11b10ufloat\",\n      35901: \"rgb9e5ufloat\",\n      35907: \"rgba8unorm-srgb\",\n      // bgra8unorm-srgb\n      36012: \"depth32float\",\n      36013: \"depth32float-stencil8\",\n      36168: \"stencil8\",\n      36208: \"rgba32uint\",\n      36214: \"rgba16uint\",\n      36220: \"rgba8uint\",\n      36226: \"rgba32sint\",\n      36232: \"rgba16sint\",\n      36238: \"rgba8sint\",\n      36492: \"bc7-rgba-unorm\",\n      36756: \"r8snorm\",\n      36757: \"rg8snorm\",\n      36759: \"rgba8snorm\",\n      37496: \"etc2-rgba8unorm\",\n      37808: \"astc-4x4-unorm\"\n    };\n    function glFormatToGPUFormat(glInternalFormat) {\n      const format = glFormatToGPUFormatMap[glInternalFormat];\n      if (format) {\n        return format;\n      }\n      throw new Error(`Unsupported glInternalFormat: ${glInternalFormat}`);\n    }\n\n    const vkFormatToGPUFormatMap = {\n      23: \"rgb8unorm\",\n      // VK_FORMAT_R8G8B8_UNORM\n      37: \"rgba8unorm\",\n      // VK_FORMAT_R8G8B8A8_UNORM\n      43: \"rgba8unorm-srgb\"\n      // VK_FORMAT_R8G8B8A8_SRGB\n      // TODO add more!\n    };\n    function vkFormatToGPUFormat(vkFormat) {\n      const format = vkFormatToGPUFormatMap[vkFormat];\n      if (format) {\n        return format;\n      }\n      throw new Error(`Unsupported VkFormat: ${vkFormat}`);\n    }\n\n    function getTextureFormatFromKTXTexture(ktxTexture) {\n      if (ktxTexture.classId === 2) {\n        return vkFormatToGPUFormat(ktxTexture.vkFormat);\n      }\n      return glFormatToGPUFormat(ktxTexture.glInternalformat);\n    }\n\n    const gpuFormatToBasisTranscoderFormatMap = {\n      \"bc3-rgba-unorm\": \"BC3_RGBA\",\n      \"bc7-rgba-unorm\": \"BC7_M5_RGBA\",\n      \"etc2-rgba8unorm\": \"ETC2_RGBA\",\n      \"astc-4x4-unorm\": \"ASTC_4x4_RGBA\",\n      // Uncompressed\n      rgba8unorm: \"RGBA32\",\n      rg11b10ufloat: \"R11F_G11F_B10F\"\n    };\n    function gpuFormatToKTXBasisTranscoderFormat(transcoderFormat) {\n      const format = gpuFormatToBasisTranscoderFormatMap[transcoderFormat];\n      if (format) {\n        return format;\n      }\n      throw new Error(`Unsupported transcoderFormat: ${transcoderFormat}`);\n    }\n\n    const settings = {\n      jsUrl: \"\",\n      wasmUrl: \"\"\n    };\n    let basisTranscoderFormat;\n    let basisTranscodedTextureFormat;\n    let ktxPromise;\n    async function getKTX() {\n      if (!ktxPromise) {\n        const absoluteJsUrl = new URL(settings.jsUrl, location.origin).href;\n        const absoluteWasmUrl = new URL(settings.wasmUrl, location.origin).href;\n        importScripts(absoluteJsUrl);\n        ktxPromise = new Promise((resolve) => {\n          LIBKTX({\n            locateFile: (_file) => absoluteWasmUrl\n          }).then((libktx) => {\n            resolve(libktx);\n          });\n        });\n      }\n      return ktxPromise;\n    }\n    async function fetchKTXTexture(url, ktx) {\n      const ktx2Response = await fetch(url);\n      if (ktx2Response.ok) {\n        const ktx2ArrayBuffer = await ktx2Response.arrayBuffer();\n        return new ktx.ktxTexture(new Uint8Array(ktx2ArrayBuffer));\n      }\n      throw new Error(`Failed to load KTX(2) texture: ${url}`);\n    }\n    const preferredTranscodedFormat = [\n      \"bc7-rgba-unorm\",\n      \"astc-4x4-unorm\",\n      \"etc2-rgba8unorm\",\n      \"bc3-rgba-unorm\",\n      \"rgba8unorm\"\n    ];\n    async function load(url) {\n      const ktx = await getKTX();\n      const ktxTexture = await fetchKTXTexture(url, ktx);\n      let format;\n      if (ktxTexture.needsTranscoding) {\n        format = basisTranscodedTextureFormat;\n        const transcodeFormat = ktx.TranscodeTarget[basisTranscoderFormat];\n        const result = ktxTexture.transcodeBasis(transcodeFormat, 0);\n        if (result !== ktx.ErrorCode.SUCCESS) {\n          throw new Error(\"Unable to transcode basis texture.\");\n        }\n      } else {\n        format = getTextureFormatFromKTXTexture(ktxTexture);\n      }\n      const levelBuffers = createLevelBuffersFromKTX(ktxTexture);\n      const textureOptions = {\n        width: ktxTexture.baseWidth,\n        height: ktxTexture.baseHeight,\n        format,\n        mipLevelCount: ktxTexture.numLevels,\n        resource: levelBuffers,\n        alphaMode: \"no-premultiply-alpha\"\n      };\n      convertFormatIfRequired(textureOptions);\n      return textureOptions;\n    }\n    async function init(jsUrl, wasmUrl, supportedTextures) {\n      if (jsUrl)\n        settings.jsUrl = jsUrl;\n      if (wasmUrl)\n        settings.wasmUrl = wasmUrl;\n      basisTranscodedTextureFormat = preferredTranscodedFormat.filter((format) => supportedTextures.includes(format))[0];\n      basisTranscoderFormat = gpuFormatToKTXBasisTranscoderFormat(basisTranscodedTextureFormat);\n      await getKTX();\n    }\n    const messageHandlers = {\n      init: async (data) => {\n        const { jsUrl, wasmUrl, supportedTextures } = data;\n        await init(jsUrl, wasmUrl, supportedTextures);\n      },\n      load: async (data) => {\n        var _a;\n        try {\n          const textureOptions = await load(data.url);\n          return {\n            type: \"load\",\n            url: data.url,\n            success: true,\n            textureOptions,\n            transferables: (_a = textureOptions.resource) == null ? void 0 : _a.map((arr) => arr.buffer)\n          };\n        } catch (e) {\n          throw e;\n        }\n      }\n    };\n    self.onmessage = async (messageEvent) => {\n      var _a;\n      const message = messageEvent.data;\n      try {\n        const response = await ((_a = messageHandlers[message.type]) == null ? void 0 : _a.call(messageHandlers, message));\n        if (response) {\n          self.postMessage(response, response.transferables);\n        }\n      } catch (err) {\n        self.postMessage({\n          type: \"error\",\n          err,\n          url: message.url\n        });\n      }\n    };\n\n})();\n";
    let WORKER_URL = null;
    class WorkerInstance
    {
        constructor()
        {
            if (!WORKER_URL)
            {
                WORKER_URL = URL.createObjectURL(new Blob([WORKER_CODE], { type: 'application/javascript' }));
            }
            this.worker = new Worker(WORKER_URL);
        }
    }
    WorkerInstance.revokeObjectURL = function revokeObjectURL()
    {
        if (WORKER_URL)
        {
            URL.revokeObjectURL(WORKER_URL);
            WORKER_URL = null;
        }
    };

    "use strict";
    const ktxTranscoderUrls = {
      jsUrl: "https://cdn.jsdelivr.net/npm/pixi.js/transcoders/ktx/libktx.js",
      wasmUrl: "https://cdn.jsdelivr.net/npm/pixi.js/transcoders/ktx/libktx.wasm"
    };
    function setKTXTranscoderPath(config) {
      Object.assign(ktxTranscoderUrls, config);
    }

    "use strict";
    let ktxWorker;
    const urlHash = {};
    const errorHash = {};
    function getKTX2Worker(supportedTextures) {
      if (!ktxWorker) {
        ktxWorker = new WorkerInstance().worker;
        ktxWorker.onmessage = (messageEvent) => {
          const { err, success, url, textureOptions } = messageEvent.data;
          if (err) {
            errorHash[url](err);
            return;
          }
          if (!success) {
            console.warn("Failed to load KTX texture", url);
          }
          urlHash[url](textureOptions);
        };
        ktxWorker.postMessage({
          type: "init",
          jsUrl: ktxTranscoderUrls.jsUrl,
          wasmUrl: ktxTranscoderUrls.wasmUrl,
          supportedTextures
        });
      }
      return ktxWorker;
    }
    function loadKTX2onWorker(url, supportedTextures) {
      const ktxWorker2 = getKTX2Worker(supportedTextures);
      return new Promise((resolve, reject) => {
        urlHash[url] = resolve;
        errorHash[url] = reject;
        ktxWorker2.postMessage({ type: "load", url });
      });
    }

    "use strict";
    const loadKTX2 = {
      extension: {
        type: ExtensionType.LoadParser,
        priority: LoaderParserPriority.High,
        name: "loadKTX2"
      },
      /** used for deprecation purposes */
      name: "loadKTX2",
      id: "ktx2",
      test(url) {
        return checkExtension(url, ".ktx2");
      },
      async load(url, _asset, loader) {
        const supportedTextures = await getSupportedTextureFormats();
        const textureOptions = await loadKTX2onWorker(url, supportedTextures);
        const compressedTextureSource = new CompressedSource(textureOptions);
        return createTexture(compressedTextureSource, loader, url);
      },
      async unload(texture) {
        if (Array.isArray(texture)) {
          texture.forEach((t) => t.destroy(true));
        } else {
          texture.destroy(true);
        }
      }
    };

    "use strict";

    "use strict";
    const converters = {
      rgb8unorm: {
        convertedFormat: "rgba8unorm",
        convertFunction: convertRGBtoRGBA
      },
      "rgb8unorm-srgb": {
        convertedFormat: "rgba8unorm-srgb",
        convertFunction: convertRGBtoRGBA
      }
    };
    function convertFormatIfRequired(textureOptions) {
      const format = textureOptions.format;
      if (converters[format]) {
        const convertFunction = converters[format].convertFunction;
        const levelBuffers = textureOptions.resource;
        for (let i = 0; i < levelBuffers.length; i++) {
          levelBuffers[i] = convertFunction(levelBuffers[i]);
        }
        textureOptions.format = converters[format].convertedFormat;
      }
    }
    function convertRGBtoRGBA(levelBuffer) {
      const pixelCount = levelBuffer.byteLength / 3;
      const levelBufferWithAlpha = new Uint32Array(pixelCount);
      for (let i = 0; i < pixelCount; ++i) {
        levelBufferWithAlpha[i] = levelBuffer[i * 3] + (levelBuffer[i * 3 + 1] << 8) + (levelBuffer[i * 3 + 2] << 16) + 4278190080;
      }
      return new Uint8Array(levelBufferWithAlpha.buffer);
    }

    "use strict";
    function createLevelBuffersFromKTX(ktxTexture) {
      const levelBuffers = [];
      for (let i = 0; i < ktxTexture.numLevels; i++) {
        const imageData = ktxTexture.getImageData(i, 0, 0);
        const levelBuffer = new Uint8Array(imageData.byteLength);
        levelBuffer.set(imageData);
        levelBuffers.push(levelBuffer);
      }
      return levelBuffers;
    }

    "use strict";
    const glFormatToGPUFormatMap = {
      6408: "rgba8unorm",
      32856: "bgra8unorm",
      //
      32857: "rgb10a2unorm",
      33189: "depth16unorm",
      33190: "depth24plus",
      33321: "r8unorm",
      33323: "rg8unorm",
      33325: "r16float",
      33326: "r32float",
      33327: "rg16float",
      33328: "rg32float",
      33329: "r8sint",
      33330: "r8uint",
      33331: "r16sint",
      33332: "r16uint",
      33333: "r32sint",
      33334: "r32uint",
      33335: "rg8sint",
      33336: "rg8uint",
      33337: "rg16sint",
      33338: "rg16uint",
      33339: "rg32sint",
      33340: "rg32uint",
      33778: "bc2-rgba-unorm",
      33779: "bc3-rgba-unorm",
      34836: "rgba32float",
      34842: "rgba16float",
      35056: "depth24plus-stencil8",
      35898: "rg11b10ufloat",
      35901: "rgb9e5ufloat",
      35907: "rgba8unorm-srgb",
      // bgra8unorm-srgb
      36012: "depth32float",
      36013: "depth32float-stencil8",
      36168: "stencil8",
      36208: "rgba32uint",
      36214: "rgba16uint",
      36220: "rgba8uint",
      36226: "rgba32sint",
      36232: "rgba16sint",
      36238: "rgba8sint",
      36492: "bc7-rgba-unorm",
      36756: "r8snorm",
      36757: "rg8snorm",
      36759: "rgba8snorm",
      37496: "etc2-rgba8unorm",
      37808: "astc-4x4-unorm"
    };
    function glFormatToGPUFormat(glInternalFormat) {
      const format = glFormatToGPUFormatMap[glInternalFormat];
      if (format) {
        return format;
      }
      throw new Error(`Unsupported glInternalFormat: ${glInternalFormat}`);
    }

    "use strict";
    const vkFormatToGPUFormatMap = {
      23: "rgb8unorm",
      // VK_FORMAT_R8G8B8_UNORM
      37: "rgba8unorm",
      // VK_FORMAT_R8G8B8A8_UNORM
      43: "rgba8unorm-srgb"
      // VK_FORMAT_R8G8B8A8_SRGB
      // TODO add more!
    };
    function vkFormatToGPUFormat(vkFormat) {
      const format = vkFormatToGPUFormatMap[vkFormat];
      if (format) {
        return format;
      }
      throw new Error(`Unsupported VkFormat: ${vkFormat}`);
    }

    "use strict";
    function getTextureFormatFromKTXTexture(ktxTexture) {
      if (ktxTexture.classId === 2) {
        return vkFormatToGPUFormat(ktxTexture.vkFormat);
      }
      return glFormatToGPUFormat(ktxTexture.glInternalformat);
    }

    "use strict";
    const gpuFormatToBasisTranscoderFormatMap = {
      "bc3-rgba-unorm": "BC3_RGBA",
      "bc7-rgba-unorm": "BC7_M5_RGBA",
      "etc2-rgba8unorm": "ETC2_RGBA",
      "astc-4x4-unorm": "ASTC_4x4_RGBA",
      // Uncompressed
      rgba8unorm: "RGBA32",
      rg11b10ufloat: "R11F_G11F_B10F"
    };
    function gpuFormatToKTXBasisTranscoderFormat(transcoderFormat) {
      const format = gpuFormatToBasisTranscoderFormatMap[transcoderFormat];
      if (format) {
        return format;
      }
      throw new Error(`Unsupported transcoderFormat: ${transcoderFormat}`);
    }

    "use strict";
    const validFormats = ["basis", "bc7", "bc6h", "astc", "etc2", "bc5", "bc4", "bc3", "bc2", "bc1", "eac"];
    const resolveCompressedTextureUrl = {
      extension: ExtensionType.ResolveParser,
      test: (value) => checkExtension(value, [".ktx", ".ktx2", ".dds"]),
      parse: (value) => {
        var _a, _b;
        let format;
        const splitValue = value.split(".");
        if (splitValue.length > 2) {
          const newFormat = splitValue[splitValue.length - 2];
          if (validFormats.includes(newFormat)) {
            format = newFormat;
          }
        } else {
          format = splitValue[splitValue.length - 1];
        }
        return {
          resolution: parseFloat((_b = (_a = Resolver.RETINA_PREFIX.exec(value)) == null ? void 0 : _a[1]) != null ? _b : "1"),
          format,
          src: value
        };
      }
    };

    "use strict";
    let compressedTextureExtensions;
    const detectCompressed = {
      extension: {
        type: ExtensionType.DetectionParser,
        priority: 2
      },
      test: async () => {
        if (await isWebGPUSupported())
          return true;
        if (isWebGLSupported())
          return true;
        return false;
      },
      add: async (formats) => {
        const supportedCompressedTextureFormats = await getSupportedCompressedTextureFormats();
        compressedTextureExtensions = extractExtensionsForCompressedTextureFormats(supportedCompressedTextureFormats);
        return [...compressedTextureExtensions, ...formats];
      },
      remove: async (formats) => {
        if (compressedTextureExtensions) {
          return formats.filter((f) => !(f in compressedTextureExtensions));
        }
        return formats;
      }
    };
    function extractExtensionsForCompressedTextureFormats(formats) {
      const extensions = ["basis"];
      const dupeMap = {};
      formats.forEach((format) => {
        const extension = format.split("-")[0];
        if (extension && !dupeMap[extension]) {
          dupeMap[extension] = true;
          extensions.push(extension);
        }
      });
      extensions.sort((a, b) => {
        const aIndex = validFormats.indexOf(a);
        const bIndex = validFormats.indexOf(b);
        if (aIndex === -1) {
          return 1;
        }
        if (bIndex === -1) {
          return -1;
        }
        return aIndex - bIndex;
      });
      return extensions;
    }

    "use strict";

    "use strict";
    const tempBounds$2 = new Bounds();
    const _Culler = class _Culler {
      /**
       * Culls the children of a specific container based on the given view rectangle.
       * This determines which objects should be rendered and which can be skipped.
       * @param container - The container to cull. Must be a Container instance.
       * @param view - The view rectangle that defines the visible area
       * @param skipUpdateTransform - Whether to skip updating transforms for better performance
       * @example
       * ```ts
       * // Basic culling with view bounds
       * const culler = new Culler();
       * culler.cull(stage, {
       *     x: 0,
       *     y: 0,
       *     width: 800,
       *     height: 600
       * });
       *
       * // Culling to renderer screen
       * culler.cull(stage, renderer.screen, false);
       * ```
       * @remarks
       * - Recursively processes all cullable children
       * - Uses cullArea if defined, otherwise calculates bounds
       * - Performance depends on scene complexity
       * @see {@link CullingMixinConstructor.cullable} For enabling culling on objects
       * @see {@link CullingMixinConstructor.cullArea} For custom culling boundaries
       */
      cull(container, view, skipUpdateTransform = true) {
        this._cullRecursive(container, view, skipUpdateTransform);
      }
      _cullRecursive(container, view, skipUpdateTransform = true) {
        var _a;
        if (container.cullable && container.measurable && container.includeInBuild) {
          const bounds = (_a = container.cullArea) != null ? _a : getGlobalBounds(container, skipUpdateTransform, tempBounds$2);
          container.culled = bounds.x >= view.x + view.width || bounds.y >= view.y + view.height || bounds.x + bounds.width <= view.x || bounds.y + bounds.height <= view.y;
        } else {
          container.culled = false;
        }
        if (!container.cullableChildren || container.culled || !container.renderable || !container.measurable || !container.includeInBuild)
          return;
        for (let i = 0; i < container.children.length; i++) {
          this._cullRecursive(container.children[i], view, skipUpdateTransform);
        }
      }
    };
    /**
     * A shared instance of the Culler class. Provides a global culler instance for convenience.
     * @example
     * ```ts
     * // Use the shared instance instead of creating a new one
     * Culler.shared.cull(stage, {
     *     x: 0,
     *     y: 0,
     *     width: 800,
     *     height: 600
     * });
     * ```
     * @see {@link CullerPlugin} For automatic culling using this instance
     */
    _Culler.shared = new _Culler();
    let Culler = _Culler;

    "use strict";
    class CullerPlugin {
      /**
       * Initialize the plugin with scope of application instance
       * @private
       * @param {object} [options] - See application options
       */
      static init(options) {
        this._renderRef = this.render.bind(this);
        this.render = () => {
          var _a;
          const updateTransform = ((_a = options == null ? void 0 : options.culler) == null ? void 0 : _a.updateTransform) !== true;
          Culler.shared.cull(this.stage, this.renderer.screen, updateTransform);
          this.renderer.render({ container: this.stage });
        };
      }
      /** @internal */
      static destroy() {
        this.render = this._renderRef;
      }
    }
    /** @ignore */
    CullerPlugin.extension = {
      priority: 10,
      type: ExtensionType.Application,
      name: "culler"
    };

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";
    const webworkerExt = {
      extension: {
        type: ExtensionType.Environment,
        name: "webworker",
        priority: 0
      },
      test: () => typeof self !== "undefined" && self.WorkerGlobalScope !== void 0,
      load: async () => {
        await Promise.resolve().then(function () { return webworkerAll; });
      }
    };

    "use strict";

    "use strict";

    var blendTemplateFrag = "\nin vec2 vTextureCoord;\nin vec4 vColor;\n\nout vec4 finalColor;\n\nuniform float uBlend;\n\nuniform sampler2D uTexture;\nuniform sampler2D uBackTexture;\n\n{FUNCTIONS}\n\nvoid main()\n{ \n    vec4 back = texture(uBackTexture, vTextureCoord);\n    vec4 front = texture(uTexture, vTextureCoord);\n    float blendedAlpha = front.a + back.a * (1.0 - front.a);\n    \n    {MAIN}\n}\n";

    var blendTemplateVert = "in vec2 aPosition;\nout vec2 vTextureCoord;\nout vec2 backgroundUv;\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nvec4 filterVertexPosition( void )\n{\n    vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n    \n    position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n    return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvoid main(void)\n{\n    gl_Position = filterVertexPosition();\n    vTextureCoord = filterTextureCoord();\n}\n";

    var blendTemplate = "\nstruct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct BlendUniforms {\n  uBlend:f32,\n};\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n@group(0) @binding(3) var uBackTexture: texture_2d<f32>;\n\n@group(1) @binding(0) var<uniform> blendUniforms : BlendUniforms;\n\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>\n  };\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);  \n}\n  \n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition)\n  );\n}\n\n{FUNCTIONS}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>\n) -> @location(0) vec4<f32> {\n\n\n   var back =  textureSample(uBackTexture, uSampler, uv);\n   var front = textureSample(uTexture, uSampler, uv);\n   var blendedAlpha = front.a + back.a * (1.0 - front.a);\n   \n   var out = vec4<f32>(0.0,0.0,0.0,0.0);\n\n   {MAIN}\n\n   return out;\n}";

    "use strict";
    var __defProp$D = Object.defineProperty;
    var __getOwnPropSymbols$F = Object.getOwnPropertySymbols;
    var __hasOwnProp$F = Object.prototype.hasOwnProperty;
    var __propIsEnum$F = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$D = (obj, key, value) => key in obj ? __defProp$D(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$D = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$F.call(b, prop))
          __defNormalProp$D(a, prop, b[prop]);
      if (__getOwnPropSymbols$F)
        for (var prop of __getOwnPropSymbols$F(b)) {
          if (__propIsEnum$F.call(b, prop))
            __defNormalProp$D(a, prop, b[prop]);
        }
      return a;
    };
    class BlendModeFilter extends Filter {
      constructor(options) {
        const gpuOptions = options.gpu;
        const gpuSource = compileBlendModeShader(__spreadValues$D({ source: blendTemplate }, gpuOptions));
        const gpuProgram = GpuProgram.from({
          vertex: {
            source: gpuSource,
            entryPoint: "mainVertex"
          },
          fragment: {
            source: gpuSource,
            entryPoint: "mainFragment"
          }
        });
        const glOptions = options.gl;
        const glSource = compileBlendModeShader(__spreadValues$D({ source: blendTemplateFrag }, glOptions));
        const glProgram = GlProgram.from({
          vertex: blendTemplateVert,
          fragment: glSource
        });
        const uniformGroup = new UniformGroup({
          uBlend: {
            value: 1,
            type: "f32"
          }
        });
        super({
          gpuProgram,
          glProgram,
          blendRequired: true,
          resources: {
            blendUniforms: uniformGroup,
            uBackTexture: Texture.EMPTY
          }
        });
      }
    }
    function compileBlendModeShader(options) {
      const { source, functions, main } = options;
      return source.replace("{FUNCTIONS}", functions).replace("{MAIN}", main);
    }

    "use strict";
    const hslgl = `
	float getLuminosity(vec3 c) {
		return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
	}

	vec3 setLuminosity(vec3 c, float lum) {
		float modLum = lum - getLuminosity(c);
		vec3 color = c.rgb + vec3(modLum);

		// clip back into legal range
		modLum = getLuminosity(color);
		vec3 modLumVec = vec3(modLum);

		float cMin = min(color.r, min(color.g, color.b));
		float cMax = max(color.r, max(color.g, color.b));

		if(cMin < 0.0) {
			color = mix(modLumVec, color, modLum / (modLum - cMin));
		}

		if(cMax > 1.0) {
			color = mix(modLumVec, color, (1.0 - modLum) / (cMax - modLum));
		}

		return color;
	}

	float getSaturation(vec3 c) {
		return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
	}

	vec3 setSaturationMinMidMax(vec3 cSorted, float s) {
		vec3 colorSorted = cSorted;

		if(colorSorted.z > colorSorted.x) {
			colorSorted.y = (((colorSorted.y - colorSorted.x) * s) / (colorSorted.z - colorSorted.x));
			colorSorted.z = s;
		}
		else {
			colorSorted.y = 0.0;
			colorSorted.z = 0.0;
		}

		colorSorted.x = 0.0;

		return colorSorted;
	}

	vec3 setSaturation(vec3 c, float s) {
		vec3 color = c;

		if(color.r <= color.g && color.r <= color.b) {
			if(color.g <= color.b) {
				color = setSaturationMinMidMax(color.rgb, s).rgb;
			}
			else {
				color = setSaturationMinMidMax(color.rbg, s).rbg;
			}
		}
		else if(color.g <= color.r && color.g <= color.b) {
			if(color.r <= color.b) {
				color = setSaturationMinMidMax(color.grb, s).grb;
			}
			else {
				color = setSaturationMinMidMax(color.gbr, s).gbr;
			}
		}
		else {
			// Using bgr for both fixes part of hue
			if(color.r <= color.g) {
				color = setSaturationMinMidMax(color.brg, s).brg;
			}
			else {
				color = setSaturationMinMidMax(color.bgr, s).bgr;
			}
		}

		return color;
	}
    `;

    "use strict";
    const hslgpu = `
	fn getLuminosity(c: vec3<f32>) -> f32
	{
		return 0.3*c.r + 0.59*c.g + 0.11*c.b;
	}

	fn setLuminosity(c: vec3<f32>, lum: f32) -> vec3<f32>
	{
		var modLum: f32 = lum - getLuminosity(c);
		var color: vec3<f32> = c.rgb + modLum;

		// clip back into legal range
		modLum = getLuminosity(color);
		let modLumVec = vec3<f32>(modLum);

		let cMin: f32 = min(color.r, min(color.g, color.b));
		let cMax: f32 = max(color.r, max(color.g, color.b));

		if(cMin < 0.0)
		{
			color = mix(modLumVec, color, modLum / (modLum - cMin));
		}

		if(cMax > 1.0)
		{
			color = mix(modLumVec, color, (1 - modLum) / (cMax - modLum));
		}

		return color;
	}

	fn getSaturation(c: vec3<f32>) -> f32
	{
		return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
	}

	fn setSaturationMinMidMax(cSorted: vec3<f32>, s: f32) -> vec3<f32>
	{
		var colorSorted = cSorted;

		if(colorSorted.z > colorSorted.x)
		{
			colorSorted.y = (((colorSorted.y - colorSorted.x) * s) / (colorSorted.z - colorSorted.x));
			colorSorted.z = s;
		}
		else
		{
			colorSorted.y = 0;
			colorSorted.z = 0;
		}

		colorSorted.x = 0;

		return colorSorted;
	}

	fn setSaturation(c: vec3<f32>, s: f32) -> vec3<f32>
	{
		var color = c;

		if (color.r <= color.g && color.r <= color.b)
		{
			if (color.g <= color.b)
			{
				color = vec3<f32>(setSaturationMinMidMax(color.rgb, s)).rgb;
			}
			else
			{
				color = vec3<f32>(setSaturationMinMidMax(color.rbg, s)).rbg;
			}
		}
		else if (color.g <= color.r && color.g <= color.b)
		{
			if (color.r <= color.b)
			{
				color = vec3<f32>(setSaturationMinMidMax(color.grb, s)).grb;
			}
			else
			{
				color = vec3<f32>(setSaturationMinMidMax(color.gbr, s)).gbr;
			}
		}
		else
		{
			// Using bgr for both fixes part of hue
			if (color.r <= color.g)
			{
				color = vec3<f32>(setSaturationMinMidMax(color.brg, s)).brg;
			}
			else
			{
				color  = vec3<f32>(setSaturationMinMidMax(color.bgr, s)).bgr;
			}
		}

		return color;
	}
	`;

    var fragment$4 = "\nin vec2 vTextureCoord;\n\nout vec4 finalColor;\n\nuniform float uAlpha;\nuniform sampler2D uTexture;\n\nvoid main()\n{\n    finalColor =  texture(uTexture, vTextureCoord) * uAlpha;\n}\n";

    var source$5 = "struct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct AlphaUniforms {\n  uAlpha:f32,\n};\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n\n@group(1) @binding(0) var<uniform> alphaUniforms : AlphaUniforms;\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>\n  };\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);  \n}\n\nfn getSize() -> vec2<f32>\n{\n  return gfu.uGlobalFrame.zw;\n}\n  \n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition)\n  );\n}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n  @builtin(position) position: vec4<f32>\n) -> @location(0) vec4<f32> {\n \n    var sample = textureSample(uTexture, uSampler, uv);\n    \n    return sample * alphaUniforms.uAlpha;\n}";

    "use strict";
    var __defProp$C = Object.defineProperty;
    var __defProps$j = Object.defineProperties;
    var __getOwnPropDescs$j = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$E = Object.getOwnPropertySymbols;
    var __hasOwnProp$E = Object.prototype.hasOwnProperty;
    var __propIsEnum$E = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$C = (obj, key, value) => key in obj ? __defProp$C(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$C = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$E.call(b, prop))
          __defNormalProp$C(a, prop, b[prop]);
      if (__getOwnPropSymbols$E)
        for (var prop of __getOwnPropSymbols$E(b)) {
          if (__propIsEnum$E.call(b, prop))
            __defNormalProp$C(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$j = (a, b) => __defProps$j(a, __getOwnPropDescs$j(b));
    var __objRest$h = (source2, exclude) => {
      var target = {};
      for (var prop in source2)
        if (__hasOwnProp$E.call(source2, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source2[prop];
      if (source2 != null && __getOwnPropSymbols$E)
        for (var prop of __getOwnPropSymbols$E(source2)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$E.call(source2, prop))
            target[prop] = source2[prop];
        }
      return target;
    };
    const _AlphaFilter = class _AlphaFilter extends Filter {
      constructor(options) {
        options = __spreadValues$C(__spreadValues$C({}, _AlphaFilter.defaultOptions), options);
        const gpuProgram = GpuProgram.from({
          vertex: {
            source: source$5,
            entryPoint: "mainVertex"
          },
          fragment: {
            source: source$5,
            entryPoint: "mainFragment"
          }
        });
        const glProgram = GlProgram.from({
          vertex: vertex$2,
          fragment: fragment$4,
          name: "alpha-filter"
        });
        const _a = options, { alpha } = _a, rest = __objRest$h(_a, ["alpha"]);
        const alphaUniforms = new UniformGroup({
          uAlpha: { value: alpha, type: "f32" }
        });
        super(__spreadProps$j(__spreadValues$C({}, rest), {
          gpuProgram,
          glProgram,
          resources: {
            alphaUniforms
          }
        }));
      }
      /**
       * The alpha value of the filter.
       * Controls the transparency of the filtered display object.
       * @example
       * ```ts
       * // Create filter with initial alpha
       * const filter = new AlphaFilter({ alpha: 0.5 });
       *
       * // Update alpha value dynamically
       * filter.alpha = 0.8;
       * ```
       * @default 1
       * @remarks
       * - 0 = fully transparent
       * - 1 = fully opaque
       * - Values are clamped between 0 and 1
       */
      get alpha() {
        return this.resources.alphaUniforms.uniforms.uAlpha;
      }
      set alpha(value) {
        this.resources.alphaUniforms.uniforms.uAlpha = value;
      }
    };
    /**
     * Default options for the AlphaFilter.
     * @example
     * ```ts
     * AlphaFilter.defaultOptions = {
     *     alpha: 0.5, // Default alpha value
     * };
     * // Use default options
     * const filter = new AlphaFilter(); // Uses default alpha of 0.5
     * ```
     */
    _AlphaFilter.defaultOptions = {
      /**
       * Amount of alpha transparency to apply.
       * - 0 = fully transparent
       * - 1 = fully opaque (default)
       * @default 1
       */
      alpha: 1
    };
    let AlphaFilter = _AlphaFilter;

    "use strict";
    const GAUSSIAN_VALUES = {
      5: [0.153388, 0.221461, 0.250301],
      7: [0.071303, 0.131514, 0.189879, 0.214607],
      9: [0.028532, 0.067234, 0.124009, 0.179044, 0.20236],
      11: [93e-4, 0.028002, 0.065984, 0.121703, 0.175713, 0.198596],
      13: [2406e-6, 9255e-6, 0.027867, 0.065666, 0.121117, 0.174868, 0.197641],
      15: [489e-6, 2403e-6, 9246e-6, 0.02784, 0.065602, 0.120999, 0.174697, 0.197448]
    };

    "use strict";
    const fragTemplate = [
      "in vec2 vBlurTexCoords[%size%];",
      "uniform sampler2D uTexture;",
      "out vec4 finalColor;",
      "void main(void)",
      "{",
      "    finalColor = vec4(0.0);",
      "    %blur%",
      "}"
    ].join("\n");
    function generateBlurFragSource(kernelSize) {
      const kernel = GAUSSIAN_VALUES[kernelSize];
      const halfLength = kernel.length;
      let fragSource = fragTemplate;
      let blurLoop = "";
      const template = "finalColor += texture(uTexture, vBlurTexCoords[%index%]) * %value%;";
      let value;
      for (let i = 0; i < kernelSize; i++) {
        let blur = template.replace("%index%", i.toString());
        value = i;
        if (i >= halfLength) {
          value = kernelSize - i - 1;
        }
        blur = blur.replace("%value%", kernel[value].toString());
        blurLoop += blur;
        blurLoop += "\n";
      }
      fragSource = fragSource.replace("%blur%", blurLoop);
      fragSource = fragSource.replace("%size%", kernelSize.toString());
      return fragSource;
    }

    "use strict";
    const vertTemplate = `
    in vec2 aPosition;

    uniform float uStrength;

    out vec2 vBlurTexCoords[%size%];

    uniform vec4 uInputSize;
    uniform vec4 uOutputFrame;
    uniform vec4 uOutputTexture;

    vec4 filterVertexPosition( void )
{
    vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;

    position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
    position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;

    return vec4(position, 0.0, 1.0);
}

    vec2 filterTextureCoord( void )
    {
        return aPosition * (uOutputFrame.zw * uInputSize.zw);
    }

    void main(void)
    {
        gl_Position = filterVertexPosition();

        float pixelStrength = uInputSize.%dimension% * uStrength;

        vec2 textureCoord = filterTextureCoord();
        %blur%
    }`;
    function generateBlurVertSource(kernelSize, x) {
      const halfLength = Math.ceil(kernelSize / 2);
      let vertSource = vertTemplate;
      let blurLoop = "";
      let template;
      if (x) {
        template = "vBlurTexCoords[%index%] =  textureCoord + vec2(%sampleIndex% * pixelStrength, 0.0);";
      } else {
        template = "vBlurTexCoords[%index%] =  textureCoord + vec2(0.0, %sampleIndex% * pixelStrength);";
      }
      for (let i = 0; i < kernelSize; i++) {
        let blur = template.replace("%index%", i.toString());
        blur = blur.replace("%sampleIndex%", `${i - (halfLength - 1)}.0`);
        blurLoop += blur;
        blurLoop += "\n";
      }
      vertSource = vertSource.replace("%blur%", blurLoop);
      vertSource = vertSource.replace("%size%", kernelSize.toString());
      vertSource = vertSource.replace("%dimension%", x ? "z" : "w");
      return vertSource;
    }

    "use strict";
    function generateBlurGlProgram(horizontal, kernelSize) {
      const vertex = generateBlurVertSource(kernelSize, horizontal);
      const fragment = generateBlurFragSource(kernelSize);
      return GlProgram.from({
        vertex,
        fragment,
        name: `blur-${horizontal ? "horizontal" : "vertical"}-pass-filter`
      });
    }

    var source$4 = "\n\nstruct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct BlurUniforms {\n  uStrength:f32,\n};\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n\n@group(1) @binding(0) var<uniform> blurUniforms : BlurUniforms;\n\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    %blur-struct%\n  };\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);  \n}\n\nfn getSize() -> vec2<f32>\n{\n  return gfu.uGlobalFrame.zw;\n}\n\n\n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n\n  let filteredCord = filterTextureCoord(aPosition);\n\n  let pixelStrength = gfu.uInputSize.%dimension% * blurUniforms.uStrength;\n\n  return VSOutput(\n   filterVertexPosition(aPosition),\n    %blur-vertex-out%\n  );\n}\n\n@fragment\nfn mainFragment(\n  @builtin(position) position: vec4<f32>,\n  %blur-fragment-in%\n) -> @location(0) vec4<f32> {\n\n    var   finalColor = vec4(0.0);\n\n    %blur-sampling%\n\n    return finalColor;\n}";

    "use strict";
    function generateBlurProgram(horizontal, kernelSize) {
      const kernel = GAUSSIAN_VALUES[kernelSize];
      const halfLength = kernel.length;
      const blurStructSource = [];
      const blurOutSource = [];
      const blurSamplingSource = [];
      for (let i = 0; i < kernelSize; i++) {
        blurStructSource[i] = `@location(${i}) offset${i}: vec2<f32>,`;
        if (horizontal) {
          blurOutSource[i] = `filteredCord + vec2(${i - halfLength + 1} * pixelStrength, 0.0),`;
        } else {
          blurOutSource[i] = `filteredCord + vec2(0.0, ${i - halfLength + 1} * pixelStrength),`;
        }
        const kernelIndex = i < halfLength ? i : kernelSize - i - 1;
        const kernelValue = kernel[kernelIndex].toString();
        blurSamplingSource[i] = `finalColor += textureSample(uTexture, uSampler, offset${i}) * ${kernelValue};`;
      }
      const blurStruct = blurStructSource.join("\n");
      const blurOut = blurOutSource.join("\n");
      const blurSampling = blurSamplingSource.join("\n");
      const finalSource = source$4.replace("%blur-struct%", blurStruct).replace("%blur-vertex-out%", blurOut).replace("%blur-fragment-in%", blurStruct).replace("%blur-sampling%", blurSampling).replace("%dimension%", horizontal ? "z" : "w");
      return GpuProgram.from({
        vertex: {
          source: finalSource,
          entryPoint: "mainVertex"
        },
        fragment: {
          source: finalSource,
          entryPoint: "mainFragment"
        }
      });
    }

    "use strict";
    var __defProp$B = Object.defineProperty;
    var __getOwnPropSymbols$D = Object.getOwnPropertySymbols;
    var __hasOwnProp$D = Object.prototype.hasOwnProperty;
    var __propIsEnum$D = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$B = (obj, key, value) => key in obj ? __defProp$B(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$B = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$D.call(b, prop))
          __defNormalProp$B(a, prop, b[prop]);
      if (__getOwnPropSymbols$D)
        for (var prop of __getOwnPropSymbols$D(b)) {
          if (__propIsEnum$D.call(b, prop))
            __defNormalProp$B(a, prop, b[prop]);
        }
      return a;
    };
    const _BlurFilterPass = class _BlurFilterPass extends Filter {
      /**
       * @param options
       * @param options.horizontal - Do pass along the x-axis (`true`) or y-axis (`false`).
       * @param options.strength - The strength of the blur filter.
       * @param options.quality - The quality of the blur filter.
       * @param options.kernelSize - The kernelSize of the blur filter.Options: 5, 7, 9, 11, 13, 15.
       */
      constructor(options) {
        options = __spreadValues$B(__spreadValues$B({}, _BlurFilterPass.defaultOptions), options);
        const glProgram = generateBlurGlProgram(options.horizontal, options.kernelSize);
        const gpuProgram = generateBlurProgram(options.horizontal, options.kernelSize);
        super(__spreadValues$B({
          glProgram,
          gpuProgram,
          resources: {
            blurUniforms: {
              uStrength: { value: 0, type: "f32" }
            }
          }
        }, options));
        this.horizontal = options.horizontal;
        this._quality = 0;
        this.quality = options.quality;
        this.blur = options.strength;
        this._uniforms = this.resources.blurUniforms.uniforms;
      }
      /**
       * Applies the filter.
       * @param filterManager - The manager.
       * @param input - The input target.
       * @param output - The output target.
       * @param clearMode - How to clear
       */
      apply(filterManager, input, output, clearMode) {
        this._uniforms.uStrength = this.strength / this.passes;
        if (this.passes === 1) {
          filterManager.applyFilter(this, input, output, clearMode);
        } else {
          const tempTexture = TexturePool.getSameSizeTexture(input);
          let flip = input;
          let flop = tempTexture;
          this._state.blend = false;
          const shouldClear = filterManager.renderer.type === RendererType.WEBGPU;
          for (let i = 0; i < this.passes - 1; i++) {
            filterManager.applyFilter(this, flip, flop, i === 0 ? true : shouldClear);
            const temp = flop;
            flop = flip;
            flip = temp;
          }
          this._state.blend = true;
          filterManager.applyFilter(this, flip, output, clearMode);
          TexturePool.returnTexture(tempTexture);
        }
      }
      /**
       * Sets the strength of both the blur.
       * @default 16
       */
      get blur() {
        return this.strength;
      }
      set blur(value) {
        this.padding = 1 + Math.abs(value) * 2;
        this.strength = value;
      }
      /**
       * Sets the quality of the blur by modifying the number of passes. More passes means higher
       * quality blurring but the lower the performance.
       * @default 4
       */
      get quality() {
        return this._quality;
      }
      set quality(value) {
        this._quality = value;
        this.passes = value;
      }
    };
    /** Default blur filter pass options */
    _BlurFilterPass.defaultOptions = {
      /** The strength of the blur filter. */
      strength: 8,
      /** The quality of the blur filter. */
      quality: 4,
      /** The kernelSize of the blur filter.Options: 5, 7, 9, 11, 13, 15. */
      kernelSize: 5
    };
    let BlurFilterPass = _BlurFilterPass;

    "use strict";
    var __defProp$A = Object.defineProperty;
    var __defProps$i = Object.defineProperties;
    var __getOwnPropDescs$i = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$C = Object.getOwnPropertySymbols;
    var __hasOwnProp$C = Object.prototype.hasOwnProperty;
    var __propIsEnum$C = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$A = (obj, key, value) => key in obj ? __defProp$A(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$A = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$C.call(b, prop))
          __defNormalProp$A(a, prop, b[prop]);
      if (__getOwnPropSymbols$C)
        for (var prop of __getOwnPropSymbols$C(b)) {
          if (__propIsEnum$C.call(b, prop))
            __defNormalProp$A(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$i = (a, b) => __defProps$i(a, __getOwnPropDescs$i(b));
    var __objRest$g = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$C.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$C)
        for (var prop of __getOwnPropSymbols$C(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$C.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class BlurFilter extends Filter {
      constructor(...args) {
        var _a;
        let options = (_a = args[0]) != null ? _a : {};
        if (typeof options === "number") {
          deprecation(v8_0_0, "BlurFilter constructor params are now options object. See params: { strength, quality, resolution, kernelSize }");
          options = { strength: options };
          if (args[1] !== void 0)
            options.quality = args[1];
          if (args[2] !== void 0)
            options.resolution = args[2] || "inherit";
          if (args[3] !== void 0)
            options.kernelSize = args[3];
        }
        options = __spreadValues$A(__spreadValues$A({}, BlurFilterPass.defaultOptions), options);
        const _b = options, { strength, strengthX, strengthY, quality } = _b, rest = __objRest$g(_b, ["strength", "strengthX", "strengthY", "quality"]);
        super(__spreadProps$i(__spreadValues$A({}, rest), {
          compatibleRenderers: RendererType.BOTH,
          resources: {}
        }));
        this._repeatEdgePixels = false;
        this.blurXFilter = new BlurFilterPass(__spreadValues$A({ horizontal: true }, options));
        this.blurYFilter = new BlurFilterPass(__spreadValues$A({ horizontal: false }, options));
        this.quality = quality;
        this.strengthX = strengthX != null ? strengthX : strength;
        this.strengthY = strengthY != null ? strengthY : strength;
        this.repeatEdgePixels = false;
      }
      /**
       * Applies the filter.
       * @param filterManager - The manager.
       * @param input - The input target.
       * @param output - The output target.
       * @param clearMode - How to clear
       * @advanced
       */
      apply(filterManager, input, output, clearMode) {
        const xStrength = Math.abs(this.blurXFilter.strength);
        const yStrength = Math.abs(this.blurYFilter.strength);
        if (xStrength && yStrength) {
          const tempTexture = TexturePool.getSameSizeTexture(input);
          this.blurXFilter.blendMode = "normal";
          this.blurXFilter.apply(filterManager, input, tempTexture, true);
          this.blurYFilter.blendMode = this.blendMode;
          this.blurYFilter.apply(filterManager, tempTexture, output, clearMode);
          TexturePool.returnTexture(tempTexture);
        } else if (yStrength) {
          this.blurYFilter.blendMode = this.blendMode;
          this.blurYFilter.apply(filterManager, input, output, clearMode);
        } else {
          this.blurXFilter.blendMode = this.blendMode;
          this.blurXFilter.apply(filterManager, input, output, clearMode);
        }
      }
      updatePadding() {
        if (this._repeatEdgePixels) {
          this.padding = 0;
        } else {
          this.padding = Math.max(Math.abs(this.blurXFilter.blur), Math.abs(this.blurYFilter.blur)) * 2;
        }
      }
      /**
       * Sets the strength of both the blurX and blurY properties simultaneously.
       * Controls the overall intensity of the Gaussian blur effect.
       * @example
       * ```ts
       * // Set equal blur strength for both axes
       * filter.strength = 8;
       *
       * // Will throw error if X and Y are different
       * filter.strengthX = 4;
       * filter.strengthY = 8;
       * filter.strength; // Error: BlurFilter's strengthX and strengthY are different
       * ```
       * @default 8
       * @throws {Error} If strengthX and strengthY are different values
       */
      get strength() {
        if (this.strengthX !== this.strengthY) {
          throw new Error("BlurFilter's strengthX and strengthY are different");
        }
        return this.strengthX;
      }
      set strength(value) {
        this.blurXFilter.blur = this.blurYFilter.blur = value;
        this.updatePadding();
      }
      /**
       * Sets the number of passes for blur. More passes means higher quality blurring.
       * Controls the precision and smoothness of the blur effect at the cost of performance.
       * @example
       * ```ts
       * // High quality blur (slower)
       * filter.quality = 8;
       *
       * // Low quality blur (faster)
       * filter.quality = 2;
       * ```
       * @default 4
       * @remarks Higher values produce better quality but impact performance
       */
      get quality() {
        return this.blurXFilter.quality;
      }
      set quality(value) {
        this.blurXFilter.quality = this.blurYFilter.quality = value;
      }
      /**
       * Sets the strength of horizontal blur.
       * Controls the blur intensity along the x-axis independently.
       * @example
       * ```ts
       * // Apply horizontal-only blur
       * filter.strengthX = 8;
       * filter.strengthY = 0;
       *
       * // Create motion blur effect
       * filter.strengthX = 16;
       * filter.strengthY = 2;
       * ```
       * @default 8
       */
      get strengthX() {
        return this.blurXFilter.blur;
      }
      set strengthX(value) {
        this.blurXFilter.blur = value;
        this.updatePadding();
      }
      /**
       * Sets the strength of the vertical blur.
       * Controls the blur intensity along the y-axis independently.
       * @example
       * ```ts
       * // Apply vertical-only blur
       * filter.strengthX = 0;
       * filter.strengthY = 8;
       *
       * // Create radial blur effect
       * filter.strengthX = 8;
       * filter.strengthY = 8;
       * ```
       * @default 8
       */
      get strengthY() {
        return this.blurYFilter.blur;
      }
      set strengthY(value) {
        this.blurYFilter.blur = value;
        this.updatePadding();
      }
      /**
       * Sets the strength of both the blurX and blurY properties simultaneously
       * @default 2
       * @deprecated since 8.3.0
       * @see BlurFilter.strength
       */
      get blur() {
        deprecation("8.3.0", "BlurFilter.blur is deprecated, please use BlurFilter.strength instead.");
        return this.strength;
      }
      set blur(value) {
        deprecation("8.3.0", "BlurFilter.blur is deprecated, please use BlurFilter.strength instead.");
        this.strength = value;
      }
      /**
       * Sets the strength of the blurX property
       * @default 2
       * @deprecated since 8.3.0
       * @see BlurFilter.strengthX
       */
      get blurX() {
        deprecation("8.3.0", "BlurFilter.blurX is deprecated, please use BlurFilter.strengthX instead.");
        return this.strengthX;
      }
      set blurX(value) {
        deprecation("8.3.0", "BlurFilter.blurX is deprecated, please use BlurFilter.strengthX instead.");
        this.strengthX = value;
      }
      /**
       * Sets the strength of the blurY property
       * @default 2
       * @deprecated since 8.3.0
       * @see BlurFilter.strengthY
       */
      get blurY() {
        deprecation("8.3.0", "BlurFilter.blurY is deprecated, please use BlurFilter.strengthY instead.");
        return this.strengthY;
      }
      set blurY(value) {
        deprecation("8.3.0", "BlurFilter.blurY is deprecated, please use BlurFilter.strengthY instead.");
        this.strengthY = value;
      }
      /**
       * If set to true the edge of the target will be clamped
       * @default false
       */
      get repeatEdgePixels() {
        return this._repeatEdgePixels;
      }
      set repeatEdgePixels(value) {
        this._repeatEdgePixels = value;
        this.updatePadding();
      }
    }
    /**
     * Default blur filter options
     * @example
     * ```ts
     * // Set default options for all BlurFilters
     * BlurFilter.defaultOptions = {
     *     strength: 10,       // Default blur strength
     *     quality: 2,        // Default blur quality
     *     kernelSize: 7      // Default kernel size
     * };
     * // Create a filter with these defaults
     * const filter = new BlurFilter(); // Uses default options
     * ```
     * @remarks
     * - These options are used when creating a new BlurFilter without specific parameters
     * - Can be overridden by passing options to the constructor
     * - Useful for setting global defaults for all blur filters in your application
     * @see {@link BlurFilterOptions} For detailed options
     * @see {@link BlurFilter} The filter that uses these options
     */
    BlurFilter.defaultOptions = {
      /** The strength of the blur filter. */
      strength: 8,
      /** The quality of the blur filter. */
      quality: 4,
      /** The kernelSize of the blur filter.Options: 5, 7, 9, 11, 13, 15. */
      kernelSize: 5
    };

    var fragment$3 = "\nin vec2 vTextureCoord;\nin vec4 vColor;\n\nout vec4 finalColor;\n\nuniform float uColorMatrix[20];\nuniform float uAlpha;\n\nuniform sampler2D uTexture;\n\nfloat rand(vec2 co)\n{\n    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nvoid main()\n{\n    vec4 color = texture(uTexture, vTextureCoord);\n    float randomValue = rand(gl_FragCoord.xy * 0.2);\n    float diff = (randomValue - 0.5) *  0.5;\n\n    if (uAlpha == 0.0) {\n        finalColor = color;\n        return;\n    }\n\n    if (color.a > 0.0) {\n        color.rgb /= color.a;\n    }\n\n    vec4 result;\n\n    result.r = (uColorMatrix[0] * color.r);\n        result.r += (uColorMatrix[1] * color.g);\n        result.r += (uColorMatrix[2] * color.b);\n        result.r += (uColorMatrix[3] * color.a);\n        result.r += uColorMatrix[4];\n\n    result.g = (uColorMatrix[5] * color.r);\n        result.g += (uColorMatrix[6] * color.g);\n        result.g += (uColorMatrix[7] * color.b);\n        result.g += (uColorMatrix[8] * color.a);\n        result.g += uColorMatrix[9];\n\n    result.b = (uColorMatrix[10] * color.r);\n       result.b += (uColorMatrix[11] * color.g);\n       result.b += (uColorMatrix[12] * color.b);\n       result.b += (uColorMatrix[13] * color.a);\n       result.b += uColorMatrix[14];\n\n    result.a = (uColorMatrix[15] * color.r);\n       result.a += (uColorMatrix[16] * color.g);\n       result.a += (uColorMatrix[17] * color.b);\n       result.a += (uColorMatrix[18] * color.a);\n       result.a += uColorMatrix[19];\n\n    vec3 rgb = mix(color.rgb, result.rgb, uAlpha);\n\n    // Premultiply alpha again.\n    rgb *= result.a;\n\n    finalColor = vec4(rgb, result.a);\n}\n";

    var source$3 = "struct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct ColorMatrixUniforms {\n  uColorMatrix:array<vec4<f32>, 5>,\n  uAlpha:f32,\n};\n\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n@group(1) @binding(0) var<uniform> colorMatrixUniforms : ColorMatrixUniforms;\n\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>,\n  };\n  \nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition),\n  );\n}\n\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n) -> @location(0) vec4<f32> {\n\n\n  var c = textureSample(uTexture, uSampler, uv);\n  \n  if (colorMatrixUniforms.uAlpha == 0.0) {\n    return c;\n  }\n\n \n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\n    if (c.a > 0.0) {\n      c.r /= c.a;\n      c.g /= c.a;\n      c.b /= c.a;\n    }\n\n    var cm = colorMatrixUniforms.uColorMatrix;\n\n\n    var result = vec4<f32>(0.);\n\n    result.r = (cm[0][0] * c.r);\n    result.r += (cm[0][1] * c.g);\n    result.r += (cm[0][2] * c.b);\n    result.r += (cm[0][3] * c.a);\n    result.r += cm[1][0];\n\n    result.g = (cm[1][1] * c.r);\n    result.g += (cm[1][2] * c.g);\n    result.g += (cm[1][3] * c.b);\n    result.g += (cm[2][0] * c.a);\n    result.g += cm[2][1];\n\n    result.b = (cm[2][2] * c.r);\n    result.b += (cm[2][3] * c.g);\n    result.b += (cm[3][0] * c.b);\n    result.b += (cm[3][1] * c.a);\n    result.b += cm[3][2];\n\n    result.a = (cm[3][3] * c.r);\n    result.a += (cm[4][0] * c.g);\n    result.a += (cm[4][1] * c.b);\n    result.a += (cm[4][2] * c.a);\n    result.a += cm[4][3];\n\n    var rgb = mix(c.rgb, result.rgb, colorMatrixUniforms.uAlpha);\n\n    rgb.r *= result.a;\n    rgb.g *= result.a;\n    rgb.b *= result.a;\n\n    return vec4(rgb, result.a);\n}";

    "use strict";
    var __defProp$z = Object.defineProperty;
    var __defProps$h = Object.defineProperties;
    var __getOwnPropDescs$h = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$B = Object.getOwnPropertySymbols;
    var __hasOwnProp$B = Object.prototype.hasOwnProperty;
    var __propIsEnum$B = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$z = (obj, key, value) => key in obj ? __defProp$z(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$z = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$B.call(b, prop))
          __defNormalProp$z(a, prop, b[prop]);
      if (__getOwnPropSymbols$B)
        for (var prop of __getOwnPropSymbols$B(b)) {
          if (__propIsEnum$B.call(b, prop))
            __defNormalProp$z(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$h = (a, b) => __defProps$h(a, __getOwnPropDescs$h(b));
    class ColorMatrixFilter extends Filter {
      constructor(options = {}) {
        const colorMatrixUniforms = new UniformGroup({
          uColorMatrix: {
            value: [
              1,
              0,
              0,
              0,
              0,
              0,
              1,
              0,
              0,
              0,
              0,
              0,
              1,
              0,
              0,
              0,
              0,
              0,
              1,
              0
            ],
            type: "f32",
            size: 20
          },
          uAlpha: {
            value: 1,
            type: "f32"
          }
        });
        const gpuProgram = GpuProgram.from({
          vertex: {
            source: source$3,
            entryPoint: "mainVertex"
          },
          fragment: {
            source: source$3,
            entryPoint: "mainFragment"
          }
        });
        const glProgram = GlProgram.from({
          vertex: vertex$2,
          fragment: fragment$3,
          name: "color-matrix-filter"
        });
        super(__spreadProps$h(__spreadValues$z({}, options), {
          gpuProgram,
          glProgram,
          resources: {
            colorMatrixUniforms
          }
        }));
        this.alpha = 1;
      }
      /**
       * Transforms current matrix and set the new one
       * @param {number[]} matrix - 5x4 matrix
       * @param multiply - if true, current matrix and matrix are multiplied. If false,
       *  just set the current matrix with matrix
       */
      _loadMatrix(matrix, multiply = false) {
        let newMatrix = matrix;
        if (multiply) {
          this._multiply(newMatrix, this.matrix, matrix);
          newMatrix = this._colorMatrix(newMatrix);
        }
        this.resources.colorMatrixUniforms.uniforms.uColorMatrix = newMatrix;
        this.resources.colorMatrixUniforms.update();
      }
      /**
       * Multiplies two mat5's
       * @private
       * @param out - 5x4 matrix the receiving matrix
       * @param a - 5x4 matrix the first operand
       * @param b - 5x4 matrix the second operand
       * @returns {number[]} 5x4 matrix
       */
      _multiply(out, a, b) {
        out[0] = a[0] * b[0] + a[1] * b[5] + a[2] * b[10] + a[3] * b[15];
        out[1] = a[0] * b[1] + a[1] * b[6] + a[2] * b[11] + a[3] * b[16];
        out[2] = a[0] * b[2] + a[1] * b[7] + a[2] * b[12] + a[3] * b[17];
        out[3] = a[0] * b[3] + a[1] * b[8] + a[2] * b[13] + a[3] * b[18];
        out[4] = a[0] * b[4] + a[1] * b[9] + a[2] * b[14] + a[3] * b[19] + a[4];
        out[5] = a[5] * b[0] + a[6] * b[5] + a[7] * b[10] + a[8] * b[15];
        out[6] = a[5] * b[1] + a[6] * b[6] + a[7] * b[11] + a[8] * b[16];
        out[7] = a[5] * b[2] + a[6] * b[7] + a[7] * b[12] + a[8] * b[17];
        out[8] = a[5] * b[3] + a[6] * b[8] + a[7] * b[13] + a[8] * b[18];
        out[9] = a[5] * b[4] + a[6] * b[9] + a[7] * b[14] + a[8] * b[19] + a[9];
        out[10] = a[10] * b[0] + a[11] * b[5] + a[12] * b[10] + a[13] * b[15];
        out[11] = a[10] * b[1] + a[11] * b[6] + a[12] * b[11] + a[13] * b[16];
        out[12] = a[10] * b[2] + a[11] * b[7] + a[12] * b[12] + a[13] * b[17];
        out[13] = a[10] * b[3] + a[11] * b[8] + a[12] * b[13] + a[13] * b[18];
        out[14] = a[10] * b[4] + a[11] * b[9] + a[12] * b[14] + a[13] * b[19] + a[14];
        out[15] = a[15] * b[0] + a[16] * b[5] + a[17] * b[10] + a[18] * b[15];
        out[16] = a[15] * b[1] + a[16] * b[6] + a[17] * b[11] + a[18] * b[16];
        out[17] = a[15] * b[2] + a[16] * b[7] + a[17] * b[12] + a[18] * b[17];
        out[18] = a[15] * b[3] + a[16] * b[8] + a[17] * b[13] + a[18] * b[18];
        out[19] = a[15] * b[4] + a[16] * b[9] + a[17] * b[14] + a[18] * b[19] + a[19];
        return out;
      }
      /**
       * Create a Float32 Array and normalize the offset component to 0-1
       * @param {number[]} matrix - 5x4 matrix
       * @returns {number[]} 5x4 matrix with all values between 0-1
       */
      _colorMatrix(matrix) {
        const m = new Float32Array(matrix);
        m[4] /= 255;
        m[9] /= 255;
        m[14] /= 255;
        m[19] /= 255;
        return m;
      }
      /**
       * Adjusts the brightness of a display object.
       *
       * The brightness adjustment works by multiplying the RGB channels by a scalar value while keeping
       * the alpha channel unchanged. Values below 1 darken the image, while values above 1 brighten it.
       * @param b - The brightness multiplier to apply. Values between 0-1 darken the image (0 being black),
       *           while values > 1 brighten it (2.0 would make it twice as bright)
       * @param multiply - When true, the new matrix is multiplied with the current one instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * // Create a new color matrix filter
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Darken the image to 50% brightness
       * colorMatrix.brightness(0.5, false);
       *
       * // Chain with other effects by using multiply
       * colorMatrix
       *     .brightness(1.2, true)  // Brighten by 20%
       *     .saturate(1.1, true);   // Increase saturation by 10%
       * ```
       */
      brightness(b, multiply) {
        const matrix = [
          b,
          0,
          0,
          0,
          0,
          0,
          b,
          0,
          0,
          0,
          0,
          0,
          b,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Sets each channel on the diagonal of the color matrix to apply a color tint.
       *
       * This method provides a way to tint display objects using the color matrix filter, similar to
       * the tint property available on Sprites and other display objects. The tint is applied by
       * scaling the RGB channels of each pixel.
       * @param color - The color to use for tinting, this can be any valid color source.
       * @param multiply - When true, the new tint matrix is multiplied with the current matrix instead
       *                  of replacing it. This allows for combining tints with other color effects.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply a red tint
       * colorMatrix.tint(0xff0000);
       *
       * // Layer a green tint on top of existing effects
       * colorMatrix.tint('green', true);
       *
       * // Chain with other color adjustments
       * colorMatrix
       *     .tint('blue')       // Blue tint
       *     .brightness(1.2, true) // Increase brightness
       * ```
       */
      tint(color, multiply) {
        const [r, g, b] = Color.shared.setValue(color).toArray();
        const matrix = [
          r,
          0,
          0,
          0,
          0,
          0,
          g,
          0,
          0,
          0,
          0,
          0,
          b,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Converts the display object to greyscale by applying a weighted matrix transformation.
       *
       * The greyscale effect works by setting equal RGB values for each pixel based on the scale parameter,
       * effectively removing color information while preserving luminance.
       * @param scale - The intensity of the greyscale effect. Value between 0-1, where:
       *               - 0 produces black
       *               - 0.5 produces 50% grey
       *               - 1 produces white
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Convert to 50% grey
       * colorMatrix.greyscale(0.5, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .greyscale(0.6, true)    // Add grey tint
       *     .brightness(1.2, true);   // Brighten the result
       * ```
       */
      greyscale(scale, multiply) {
        const matrix = [
          scale,
          scale,
          scale,
          0,
          0,
          scale,
          scale,
          scale,
          0,
          0,
          scale,
          scale,
          scale,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Converts the display object to grayscale by applying a weighted matrix transformation.
       *
       * The grayscale effect works by setting equal RGB values for each pixel based on the scale parameter,
       * effectively removing color information while preserving luminance.
       * @param scale - The intensity of the grayscale effect. Value between 0-1, where:
       *               - 0 produces black
       *               - 0.5 produces 50% grey
       *               - 1 produces white
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Convert to 50% grey
       * colorMatrix.grayscale(0.5, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .grayscale(0.6, true)    // Add grey tint
       *     .brightness(1.2, true);   // Brighten the result
       * ```
       */
      grayscale(scale, multiply) {
        this.greyscale(scale, multiply);
      }
      /**
       * Converts the display object to pure black and white using a luminance-based threshold.
       *
       * This method applies a matrix transformation that removes all color information and reduces
       * the image to just black and white values based on the luminance of each pixel. The transformation
       * uses standard luminance weightings: 30% red, 60% green, and 10% blue.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Convert to black and white
       * colorMatrix.blackAndWhite(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .blackAndWhite(true)     // Apply B&W effect
       *     .brightness(1.2, true);   // Then increase brightness
       * ```
       */
      blackAndWhite(multiply) {
        const matrix = [
          0.3,
          0.6,
          0.1,
          0,
          0,
          0.3,
          0.6,
          0.1,
          0,
          0,
          0.3,
          0.6,
          0.1,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Adjusts the hue of the display object by rotating the color values around the color wheel.
       *
       * This method uses an optimized matrix transformation that accurately rotates the RGB color space
       * around its luminance axis. The implementation is based on RGB cube rotation in 3D space, providing
       * better results than traditional matrices with magic luminance constants.
       * @param rotation - The angle of rotation in degrees around the color wheel:
       *                  - 0 = no change
       *                  - 90 = rotate colors 90° clockwise
       *                  - 180 = invert all colors
       *                  - 270 = rotate colors 90° counter-clockwise
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Rotate hue by 90 degrees
       * colorMatrix.hue(90, false);
       *
       * // Chain multiple color adjustments
       * colorMatrix
       *     .hue(45, true)          // Rotate colors by 45°
       *     .saturate(1.2, true)    // Increase saturation
       *     .brightness(1.1, true); // Slightly brighten
       * ```
       */
      hue(rotation, multiply) {
        rotation = (rotation || 0) / 180 * Math.PI;
        const cosR = Math.cos(rotation);
        const sinR = Math.sin(rotation);
        const sqrt = Math.sqrt;
        const w = 1 / 3;
        const sqrW = sqrt(w);
        const a00 = cosR + (1 - cosR) * w;
        const a01 = w * (1 - cosR) - sqrW * sinR;
        const a02 = w * (1 - cosR) + sqrW * sinR;
        const a10 = w * (1 - cosR) + sqrW * sinR;
        const a11 = cosR + w * (1 - cosR);
        const a12 = w * (1 - cosR) - sqrW * sinR;
        const a20 = w * (1 - cosR) - sqrW * sinR;
        const a21 = w * (1 - cosR) + sqrW * sinR;
        const a22 = cosR + w * (1 - cosR);
        const matrix = [
          a00,
          a01,
          a02,
          0,
          0,
          a10,
          a11,
          a12,
          0,
          0,
          a20,
          a21,
          a22,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Adjusts the contrast of the display object by modifying the separation between dark and bright values.
       *
       * This method applies a matrix transformation that affects the difference between dark and light areas
       * in the image. Increasing contrast makes shadows darker and highlights brighter, while decreasing
       * contrast brings shadows up and highlights down, reducing the overall dynamic range.
       * @param amount - The contrast adjustment value. Range is 0 to 1, where:
       *                - 0 represents minimum contrast (flat gray)
       *                - 0.5 represents normal contrast
       *                - 1 represents maximum contrast
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Increase contrast by 50%
       * colorMatrix.contrast(0.75, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .contrast(0.6, true)     // Boost contrast
       *     .brightness(1.1, true)   // Slightly brighten
       *     .saturate(1.2, true);    // Increase color intensity
       * ```
       */
      contrast(amount, multiply) {
        const v = (amount || 0) + 1;
        const o = -0.5 * (v - 1);
        const matrix = [
          v,
          0,
          0,
          0,
          o,
          0,
          v,
          0,
          0,
          o,
          0,
          0,
          v,
          0,
          o,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Adjusts the saturation of the display object by modifying color separation.
       *
       * This method applies a matrix transformation that affects the intensity of colors.
       * Increasing saturation makes colors more vivid and intense, while decreasing saturation
       * moves colors toward grayscale.
       * @param amount - The saturation adjustment value. Range is -1 to 1, where:
       *                - -1 produces grayscale
       *                - 0 represents no change
       *                - 1 produces maximum saturation
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Double the saturation
       * colorMatrix.saturate(1, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .saturate(0.5, true)     // Increase saturation by 50%
       *     .brightness(1.1, true)    // Slightly brighten
       *     .contrast(0.8, true);     // Reduce contrast
       * ```
       */
      saturate(amount = 0, multiply) {
        const x = amount * 2 / 3 + 1;
        const y = (x - 1) * -0.5;
        const matrix = [
          x,
          y,
          y,
          0,
          0,
          y,
          x,
          y,
          0,
          0,
          y,
          y,
          x,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Completely removes color information from the display object, creating a grayscale version.
       *
       * This is a convenience method that calls `saturate(-1)` internally. The transformation preserves
       * the luminance of the original image while removing all color information.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Convert image to grayscale
       * colorMatrix.desaturate();
       *
       * // Can be chained with other effects
       * colorMatrix
       *     .desaturate()         // Remove all color
       *     .brightness(1.2);     // Then increase brightness
       * ```
       */
      desaturate() {
        this.saturate(-1);
      }
      /**
       * Creates a negative effect by inverting all colors in the display object.
       *
       * This method applies a matrix transformation that inverts the RGB values of each pixel
       * while preserving the alpha channel. The result is similar to a photographic negative.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Create negative effect
       * colorMatrix.negative(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .negative(true)       // Apply negative effect
       *     .brightness(1.2, true) // Increase brightness
       *     .contrast(0.8, true);  // Reduce contrast
       * ```
       */
      negative(multiply) {
        const matrix = [
          -1,
          0,
          0,
          1,
          0,
          0,
          -1,
          0,
          1,
          0,
          0,
          0,
          -1,
          1,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a sepia tone effect to the display object, creating a warm brown tint reminiscent of vintage photographs.
       *
       * This method applies a matrix transformation that converts colors to various shades of brown while
       * preserving the original luminance values.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply sepia effect
       * colorMatrix.sepia(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .sepia(true)           // Add sepia tone
       *     .brightness(1.1, true)  // Slightly brighten
       *     .contrast(0.9, true);   // Reduce contrast
       * ```
       */
      sepia(multiply) {
        const matrix = [
          0.393,
          0.7689999,
          0.18899999,
          0,
          0,
          0.349,
          0.6859999,
          0.16799999,
          0,
          0,
          0.272,
          0.5339999,
          0.13099999,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a Technicolor-style effect that simulates the early color motion picture process.
       *
       * This method applies a matrix transformation that recreates the distinctive look of the
       * Technicolor process. The effect produces highly
       * saturated colors with a particular emphasis on reds, greens, and blues.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply Technicolor effect
       * colorMatrix.technicolor(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .technicolor(true)      // Add Technicolor effect
       *     .contrast(1.1, true)    // Boost contrast
       *     .brightness(0.9, true); // Slightly darken
       * ```
       */
      technicolor(multiply) {
        const matrix = [
          1.9125277891456083,
          -0.8545344976951645,
          -0.09155508482755585,
          0,
          11.793603434377337,
          -0.3087833385928097,
          1.7658908555458428,
          -0.10601743074722245,
          0,
          -70.35205161461398,
          -0.231103377548616,
          -0.7501899197440212,
          1.847597816108189,
          0,
          30.950940869491138,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a vintage Polaroid camera effect to the display object.
       *
       * This method applies a matrix transformation that simulates the distinctive look of
       * Polaroid instant photographs, characterized by slightly enhanced contrast, subtle color shifts,
       * and a warm overall tone.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply Polaroid effect
       * colorMatrix.polaroid(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .polaroid(true)         // Add Polaroid effect
       *     .brightness(1.1, true)  // Slightly brighten
       *     .contrast(1.1, true);   // Boost contrast
       * ```
       */
      polaroid(multiply) {
        const matrix = [
          1.438,
          -0.062,
          -0.062,
          0,
          0,
          -0.122,
          1.378,
          -0.122,
          0,
          0,
          -0.016,
          -0.016,
          1.483,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Swaps the red and blue color channels in the display object.
       *
       * This method applies a matrix transformation that exchanges the red and blue color values
       * while keeping the green channel and alpha unchanged.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Swap red and blue channels
       * colorMatrix.toBGR(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .toBGR(true)           // Swap R and B channels
       *     .brightness(1.1, true)  // Slightly brighten
       *     .contrast(0.9, true);   // Reduce contrast
       * ```
       */
      toBGR(multiply) {
        const matrix = [
          0,
          0,
          1,
          0,
          0,
          0,
          1,
          0,
          0,
          0,
          1,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a Kodachrome color effect that simulates the iconic film stock.
       *
       * This method applies a matrix transformation that recreates the distinctive look of Kodachrome film,
       * known for its rich, vibrant colors and excellent image preservation qualities. The effect emphasizes
       * reds and blues while producing deep, true blacks.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply Kodachrome effect
       * colorMatrix.kodachrome(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .kodachrome(true)       // Add Kodachrome effect
       *     .contrast(1.1, true)    // Boost contrast
       *     .brightness(0.9, true); // Slightly darken
       * ```
       */
      kodachrome(multiply) {
        const matrix = [
          1.1285582396593525,
          -0.3967382283601348,
          -0.03992559172921793,
          0,
          63.72958762196502,
          -0.16404339962244616,
          1.0835251566291304,
          -0.05498805115633132,
          0,
          24.732407896706203,
          -0.16786010706155763,
          -0.5603416277695248,
          1.6014850761964943,
          0,
          35.62982807460946,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a stylized brown-tinted effect to the display object.
       *
       * This method applies a matrix transformation that creates a rich, warm brown tone
       * with enhanced contrast and subtle color shifts.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply browni effect
       * colorMatrix.browni(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .browni(true)          // Add brown tint
       *     .brightness(1.1, true)  // Slightly brighten
       *     .contrast(1.2, true);   // Boost contrast
       * ```
       */
      browni(multiply) {
        const matrix = [
          0.5997023498159715,
          0.34553243048391263,
          -0.2708298674538042,
          0,
          47.43192855600873,
          -0.037703249837783157,
          0.8609577587992641,
          0.15059552388459913,
          0,
          -36.96841498319127,
          0.24113635128153335,
          -0.07441037908422492,
          0.44972182064877153,
          0,
          -7.562075277591283,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a vintage photo effect that simulates old photography techniques.
       *
       * This method applies a matrix transformation that creates a nostalgic, aged look
       * with muted colors, enhanced warmth, and subtle vignetting.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply vintage effect
       * colorMatrix.vintage(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .vintage(true)          // Add vintage look
       *     .brightness(0.9, true)  // Slightly darken
       *     .contrast(1.1, true);   // Boost contrast
       * ```
       */
      vintage(multiply) {
        const matrix = [
          0.6279345635605994,
          0.3202183420819367,
          -0.03965408211312453,
          0,
          9.651285835294123,
          0.02578397704808868,
          0.6441188644374771,
          0.03259127616149294,
          0,
          7.462829176470591,
          0.0466055556782719,
          -0.0851232987247891,
          0.5241648018700465,
          0,
          5.159190588235296,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * We don't know exactly what it does, kind of gradient map, but funny to play with!
       * @param desaturation - Tone values.
       * @param toned - Tone values.
       * @param lightColor - Tone values, example: `0xFFE580`
       * @param darkColor - Tone values, example: `0xFFE580`
       * @param multiply - if true, current matrix and matrix are multiplied. If false,
       *  just set the current matrix with matrix
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Create sepia-like effect with custom colors
       * colorMatrix.colorTone(
       *     0.3,        // Moderate desaturation
       *     0.2,        // Moderate toning
       *     0xFFE580,   // Warm highlight color
       *     0x338000,   // Dark green shadows
       *     false
       * );
       *
       * // Chain with other effects
       * colorMatrix
       *     .colorTone(0.2, 0.15, 0xFFE580, 0x338000, true)
       *     .brightness(1.1, true);  // Slightly brighten
       * ```
       */
      colorTone(desaturation, toned, lightColor, darkColor, multiply) {
        desaturation || (desaturation = 0.2);
        toned || (toned = 0.15);
        lightColor || (lightColor = 16770432);
        darkColor || (darkColor = 3375104);
        const temp = Color.shared;
        const [lR, lG, lB] = temp.setValue(lightColor).toArray();
        const [dR, dG, dB] = temp.setValue(darkColor).toArray();
        const matrix = [
          0.3,
          0.59,
          0.11,
          0,
          0,
          lR,
          lG,
          lB,
          desaturation,
          0,
          dR,
          dG,
          dB,
          toned,
          0,
          lR - dR,
          lG - dG,
          lB - dB,
          0,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a night vision effect to the display object.
       *
       * This method applies a matrix transformation that simulates night vision by enhancing
       * certain color channels while suppressing others, creating a green-tinted effect
       * similar to night vision goggles.
       * @param intensity - The intensity of the night effect (0-1):
       *                   - 0 produces no effect
       *                   - 0.1 produces a subtle night vision effect (default)
       *                   - 1 produces maximum night vision effect
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply night vision effect
       * colorMatrix.night(0.3, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .night(0.2, true)        // Add night vision
       *     .brightness(1.1, true)    // Slightly brighten
       *     .contrast(1.2, true);     // Boost contrast
       * ```
       */
      night(intensity, multiply) {
        intensity || (intensity = 0.1);
        const matrix = [
          intensity * -2,
          -intensity,
          0,
          0,
          0,
          -intensity,
          0,
          intensity,
          0,
          0,
          0,
          intensity,
          intensity * 2,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Predator effect
       *
       * Erase the current matrix by setting a new independent one
       * @param amount - how much the predator feels his future victim
       * @param multiply - if true, current matrix and matrix are multiplied. If false,
       *  just set the current matrix with matrix
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply thermal vision effect
       * colorMatrix.predator(0.5, false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .predator(0.3, true)      // Add thermal effect
       *     .contrast(1.2, true)      // Boost contrast
       *     .brightness(1.1, true);   // Slightly brighten
       * ```
       */
      predator(amount, multiply) {
        const matrix = [
          // row 1
          11.224130630493164 * amount,
          -4.794486999511719 * amount,
          -2.8746118545532227 * amount,
          0 * amount,
          0.40342438220977783 * amount,
          // row 2
          -3.6330697536468506 * amount,
          9.193157196044922 * amount,
          -2.951810836791992 * amount,
          0 * amount,
          -1.316135048866272 * amount,
          // row 3
          -3.2184197902679443 * amount,
          -4.2375030517578125 * amount,
          7.476448059082031 * amount,
          0 * amount,
          0.8044459223747253 * amount,
          // row 4
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Applies a psychedelic color effect that creates dramatic color shifts.
       *
       * This method applies a matrix transformation that produces vibrant colors
       * through channel mixing and amplification. Creates an effect reminiscent of
       * color distortions in psychedelic art.
       * @param multiply - When true, the new matrix is multiplied with the current matrix instead of replacing it.
       *                  This allows for cumulative effects when calling multiple color adjustments.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply psychedelic effect
       * colorMatrix.lsd(false);
       *
       * // Chain with other effects
       * colorMatrix
       *     .lsd(true)             // Add color distortion
       *     .brightness(0.9, true)  // Slightly darken
       *     .contrast(1.2, true);   // Boost contrast
       * ```
       */
      lsd(multiply) {
        const matrix = [
          2,
          -0.4,
          0.5,
          0,
          0,
          -0.5,
          2,
          -0.4,
          0,
          0,
          -0.4,
          -0.5,
          3,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, multiply);
      }
      /**
       * Resets the color matrix filter to its default state.
       *
       * This method resets all color transformations by setting the matrix back to its identity state.
       * The identity matrix leaves colors unchanged, effectively removing all previously applied effects.
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply some effects
       * colorMatrix
       *     .sepia(true)
       *     .brightness(1.2, true);
       *
       * // Reset back to original colors
       * colorMatrix.reset();
       * ```
       */
      reset() {
        const matrix = [
          1,
          0,
          0,
          0,
          0,
          0,
          1,
          0,
          0,
          0,
          0,
          0,
          1,
          0,
          0,
          0,
          0,
          0,
          1,
          0
        ];
        this._loadMatrix(matrix, false);
      }
      /**
       * The current color transformation matrix of the filter.
       *
       * This 5x4 matrix transforms RGBA color and alpha values of each pixel. The matrix is stored
       * as a 20-element array in row-major order.
       * @type {ColorMatrix}
       * @default [
       *     1, 0, 0, 0, 0,  // Red channel
       *     0, 1, 0, 0, 0,  // Green channel
       *     0, 0, 1, 0, 0,  // Blue channel
       *     0, 0, 0, 1, 0   // Alpha channel
       * ]
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       * // Get the current color matrix
       * const currentMatrix = colorMatrix.matrix;
       * // Modify the matrix
       * colorMatrix.matrix = [
       *     1, 0, 0, 0, 0,
       *     0, 1, 0, 0, 0,
       *     0, 0, 1, 0, 0,
       *     0, 0, 0, 1, 0
       * ];
       */
      get matrix() {
        return this.resources.colorMatrixUniforms.uniforms.uColorMatrix;
      }
      set matrix(value) {
        this.resources.colorMatrixUniforms.uniforms.uColorMatrix = value;
      }
      /**
       * The opacity value used to blend between the original and transformed colors.
       *
       * This value controls how much of the color transformation is applied:
       * - 0 = Original color only (no effect)
       * - 0.5 = 50% blend of original and transformed colors
       * - 1 = Fully transformed color (default)
       * @default 1
       * @example
       * ```ts
       * const colorMatrix = new ColorMatrixFilter();
       *
       * // Apply sepia at 50% strength
       * colorMatrix.sepia(false);
       * colorMatrix.alpha = 0.5;
       *
       * // Fade between effects
       * colorMatrix
       *     .saturate(1.5)      // Increase saturation
       *     .contrast(1.2);     // Boost contrast
       * colorMatrix.alpha = 0.7; // Apply at 70% strength
       * ```
       */
      get alpha() {
        return this.resources.colorMatrixUniforms.uniforms.uAlpha;
      }
      set alpha(value) {
        this.resources.colorMatrixUniforms.uniforms.uAlpha = value;
      }
    }

    var fragment$2 = "\nin vec2 vTextureCoord;\nin vec2 vFilterUv;\n\nout vec4 finalColor;\n\nuniform sampler2D uTexture;\nuniform sampler2D uMapTexture;\n\nuniform vec4 uInputClamp;\nuniform highp vec4 uInputSize;\nuniform mat2 uRotation;\nuniform vec2 uScale;\n\nvoid main()\n{\n    vec4 map = texture(uMapTexture, vFilterUv);\n    \n    vec2 offset = uInputSize.zw * (uRotation * (map.xy - 0.5)) * uScale; \n\n    finalColor = texture(uTexture, clamp(vTextureCoord + offset, uInputClamp.xy, uInputClamp.zw));\n}\n";

    var vertex$1 = "in vec2 aPosition;\nout vec2 vTextureCoord;\nout vec2 vFilterUv;\n\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nuniform mat3 uFilterMatrix;\n\nvec4 filterVertexPosition( void )\n{\n    vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n    \n    position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n    return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvec2 getFilterCoord( void )\n{\n  return ( uFilterMatrix * vec3( filterTextureCoord(), 1.0)  ).xy;\n}\n\n\nvoid main(void)\n{\n    gl_Position = filterVertexPosition();\n    vTextureCoord = filterTextureCoord();\n    vFilterUv = getFilterCoord();\n}\n";

    var source$2 = "\nstruct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct DisplacementUniforms {\n  uFilterMatrix:mat3x3<f32>,\n  uScale:vec2<f32>,\n  uRotation:mat2x2<f32>\n};\n\n\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n\n@group(1) @binding(0) var<uniform> filterUniforms : DisplacementUniforms;\n@group(1) @binding(1) var uMapTexture: texture_2d<f32>;\n@group(1) @binding(2) var uMapSampler : sampler;\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>,\n    @location(1) filterUv : vec2<f32>,\n  };\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);  \n}\n\nfn getFilterCoord(aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return ( filterUniforms.uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0)  ).xy;\n}\n\nfn getSize() -> vec2<f32>\n{\n\n  \n  return gfu.uGlobalFrame.zw;\n}\n  \n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition),\n   getFilterCoord(aPosition)\n  );\n}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n  @location(1) filterUv: vec2<f32>,\n  @builtin(position) position: vec4<f32>\n) -> @location(0) vec4<f32> {\n\n    var map = textureSample(uMapTexture, uMapSampler, filterUv);\n\n    var offset =  gfu.uInputSize.zw * (filterUniforms.uRotation * (map.xy - 0.5)) * filterUniforms.uScale; \n   \n    return textureSample(uTexture, uSampler, clamp(uv + offset, gfu.uInputClamp.xy, gfu.uInputClamp.zw));\n}";

    "use strict";
    var __defProp$y = Object.defineProperty;
    var __defProps$g = Object.defineProperties;
    var __getOwnPropDescs$g = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$A = Object.getOwnPropertySymbols;
    var __hasOwnProp$A = Object.prototype.hasOwnProperty;
    var __propIsEnum$A = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$y = (obj, key, value) => key in obj ? __defProp$y(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$y = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$A.call(b, prop))
          __defNormalProp$y(a, prop, b[prop]);
      if (__getOwnPropSymbols$A)
        for (var prop of __getOwnPropSymbols$A(b)) {
          if (__propIsEnum$A.call(b, prop))
            __defNormalProp$y(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$g = (a, b) => __defProps$g(a, __getOwnPropDescs$g(b));
    var __objRest$f = (source2, exclude) => {
      var target = {};
      for (var prop in source2)
        if (__hasOwnProp$A.call(source2, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source2[prop];
      if (source2 != null && __getOwnPropSymbols$A)
        for (var prop of __getOwnPropSymbols$A(source2)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$A.call(source2, prop))
            target[prop] = source2[prop];
        }
      return target;
    };
    class DisplacementFilter extends Filter {
      constructor(...args) {
        let options = args[0];
        if (options instanceof Sprite) {
          if (args[1]) {
            deprecation(v8_0_0, "DisplacementFilter now uses options object instead of params. {sprite, scale}");
          }
          options = { sprite: options, scale: args[1] };
        }
        const _a = options, { sprite, scale: scaleOption } = _a, rest = __objRest$f(_a, ["sprite", "scale"]);
        let scale = scaleOption != null ? scaleOption : 20;
        if (typeof scale === "number") {
          scale = new Point(scale, scale);
        }
        const filterUniforms = new UniformGroup({
          uFilterMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uScale: { value: scale, type: "vec2<f32>" },
          uRotation: { value: new Float32Array([0, 0, 0, 0]), type: "mat2x2<f32>" }
        });
        const glProgram = GlProgram.from({
          vertex: vertex$1,
          fragment: fragment$2,
          name: "displacement-filter"
        });
        const gpuProgram = GpuProgram.from({
          vertex: {
            source: source$2,
            entryPoint: "mainVertex"
          },
          fragment: {
            source: source$2,
            entryPoint: "mainFragment"
          }
        });
        const textureSource = sprite.texture.source;
        super(__spreadProps$g(__spreadValues$y({}, rest), {
          gpuProgram,
          glProgram,
          resources: {
            filterUniforms,
            uMapTexture: textureSource,
            uMapSampler: textureSource.style
          }
        }));
        this._sprite = options.sprite;
        this._sprite.renderable = false;
      }
      /**
       * Applies the filter.
       * @param filterManager - The manager.
       * @param input - The input target.
       * @param output - The output target.
       * @param clearMode - clearMode.
       * @advanced
       */
      apply(filterManager, input, output, clearMode) {
        const uniforms = this.resources.filterUniforms.uniforms;
        filterManager.calculateSpriteMatrix(
          uniforms.uFilterMatrix,
          this._sprite
        );
        const wt = this._sprite.worldTransform;
        const lenX = Math.sqrt(wt.a * wt.a + wt.b * wt.b);
        const lenY = Math.sqrt(wt.c * wt.c + wt.d * wt.d);
        if (lenX !== 0 && lenY !== 0) {
          uniforms.uRotation[0] = wt.a / lenX;
          uniforms.uRotation[1] = wt.b / lenX;
          uniforms.uRotation[2] = wt.c / lenY;
          uniforms.uRotation[3] = wt.d / lenY;
        }
        this.resources.uMapTexture = this._sprite.texture.source;
        filterManager.applyFilter(this, input, output, clearMode);
      }
      /**
       * The scale of the displacement effect.
       *
       * Gets the current x and y scaling values used for the displacement mapping.
       * - x: Horizontal displacement scale
       * - y: Vertical displacement scale
       * @returns {Point} The current scale as a Point object
       * @example
       * ```ts
       * const filter = new DisplacementFilter({ sprite });
       *
       * // Get current scale
       * console.log(filter.scale.x, filter.scale.y);
       *
       * // Update scale
       * filter.scale.x = 100;
       * filter.scale.y = 50;
       * ```
       */
      get scale() {
        return this.resources.filterUniforms.uniforms.uScale;
      }
    }

    var fragment$1 = "\nin vec2 vTextureCoord;\nin vec4 vColor;\n\nout vec4 finalColor;\n\nuniform float uNoise;\nuniform float uSeed;\nuniform sampler2D uTexture;\n\nfloat rand(vec2 co)\n{\n    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nvoid main()\n{\n    vec4 color = texture(uTexture, vTextureCoord);\n    float randomValue = rand(gl_FragCoord.xy * uSeed);\n    float diff = (randomValue - 0.5) *  uNoise;\n\n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\n    if (color.a > 0.0) {\n        color.rgb /= color.a;\n    }\n\n    color.r += diff;\n    color.g += diff;\n    color.b += diff;\n\n    // Premultiply alpha again.\n    color.rgb *= color.a;\n\n    finalColor = color;\n}\n";

    var source$1 = "\n\nstruct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct NoiseUniforms {\n  uNoise:f32,\n  uSeed:f32,\n};\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n\n@group(1) @binding(0) var<uniform> noiseUniforms : NoiseUniforms;\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>\n  };\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);  \n}\n\nfn getSize() -> vec2<f32>\n{\n  return gfu.uGlobalFrame.zw;\n}\n  \n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>, \n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition)\n  );\n}\n\nfn rand(co:vec2<f32>) -> f32\n{\n  return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\n\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n  @builtin(position) position: vec4<f32>\n) -> @location(0) vec4<f32> {\n\n    var pixelPosition =  globalTextureCoord(position.xy);// / (getSize());//-  gfu.uOutputFrame.xy);\n  \n    \n    var sample = textureSample(uTexture, uSampler, uv);\n    var randomValue =  rand(pixelPosition.xy * noiseUniforms.uSeed);\n    var diff = (randomValue - 0.5) * noiseUniforms.uNoise;\n  \n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\n    if (sample.a > 0.0) {\n      sample.r /= sample.a;\n      sample.g /= sample.a;\n      sample.b /= sample.a;\n    }\n\n    sample.r += diff;\n    sample.g += diff;\n    sample.b += diff;\n\n    // Premultiply alpha again.\n    sample.r *= sample.a;\n    sample.g *= sample.a;\n    sample.b *= sample.a;\n    \n    return sample;\n}";

    "use strict";
    var __defProp$x = Object.defineProperty;
    var __defProps$f = Object.defineProperties;
    var __getOwnPropDescs$f = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$z = Object.getOwnPropertySymbols;
    var __hasOwnProp$z = Object.prototype.hasOwnProperty;
    var __propIsEnum$z = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$x = (obj, key, value) => key in obj ? __defProp$x(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$x = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$z.call(b, prop))
          __defNormalProp$x(a, prop, b[prop]);
      if (__getOwnPropSymbols$z)
        for (var prop of __getOwnPropSymbols$z(b)) {
          if (__propIsEnum$z.call(b, prop))
            __defNormalProp$x(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$f = (a, b) => __defProps$f(a, __getOwnPropDescs$f(b));
    var __objRest$e = (source2, exclude) => {
      var target = {};
      for (var prop in source2)
        if (__hasOwnProp$z.call(source2, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source2[prop];
      if (source2 != null && __getOwnPropSymbols$z)
        for (var prop of __getOwnPropSymbols$z(source2)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$z.call(source2, prop))
            target[prop] = source2[prop];
        }
      return target;
    };
    const _NoiseFilter = class _NoiseFilter extends Filter {
      /**
       * @param options - The options of the noise filter.
       */
      constructor(options = {}) {
        options = __spreadValues$x(__spreadValues$x({}, _NoiseFilter.defaultOptions), options);
        const gpuProgram = GpuProgram.from({
          vertex: {
            source: source$1,
            entryPoint: "mainVertex"
          },
          fragment: {
            source: source$1,
            entryPoint: "mainFragment"
          }
        });
        const glProgram = GlProgram.from({
          vertex: vertex$2,
          fragment: fragment$1,
          name: "noise-filter"
        });
        const _a = options, { noise, seed } = _a, rest = __objRest$e(_a, ["noise", "seed"]);
        super(__spreadProps$f(__spreadValues$x({}, rest), {
          gpuProgram,
          glProgram,
          resources: {
            noiseUniforms: new UniformGroup({
              uNoise: { value: 1, type: "f32" },
              uSeed: { value: 1, type: "f32" }
            })
          }
        }));
        this.noise = noise;
        this.seed = seed != null ? seed : Math.random();
      }
      /**
       * The amount of noise to apply to the filtered content.
       *
       * This value controls the intensity of the random noise effect:
       * - Values close to 0 produce subtle noise
       * - Values around 0.5 produce moderate noise
       * - Values close to 1 produce strong noise
       * @default 0.5
       * @example
       * ```ts
       * const noiseFilter = new NoiseFilter();
       *
       * // Set to subtle noise
       * noiseFilter.noise = 0.2;
       *
       * // Set to maximum noise
       * noiseFilter.noise = 1.0;
       * ```
       */
      get noise() {
        return this.resources.noiseUniforms.uniforms.uNoise;
      }
      set noise(value) {
        this.resources.noiseUniforms.uniforms.uNoise = value;
      }
      /**
       * The seed value used for random noise generation.
       *
       * This value determines the noise pattern:
       * - Using the same seed will generate identical noise patterns
       * - Different seeds produce different but consistent patterns
       * - `Math.random()` can be used for random patterns
       * @default Math.random()
       * @example
       * ```ts
       * const noiseFilter = new NoiseFilter();
       *
       * // Use a fixed seed for consistent noise
       * noiseFilter.seed = 12345;
       *
       * // Generate new random pattern
       * noiseFilter.seed = Math.random();
       * ```
       */
      get seed() {
        return this.resources.noiseUniforms.uniforms.uSeed;
      }
      set seed(value) {
        this.resources.noiseUniforms.uniforms.uSeed = value;
      }
    };
    /**
     * The default configuration options for the NoiseFilter.
     *
     * These values will be used when no specific options are provided to the constructor.
     * You can override any of these values by passing your own options object.
     * @example
     * ```ts
     * NoiseFilter.defaultOptions.noise = 0.7; // Change default noise to 0.7
     * const filter = new NoiseFilter(); // Will use noise 0.7 by default
     * ```
     */
    _NoiseFilter.defaultOptions = {
      noise: 0.5
    };
    let NoiseFilter = _NoiseFilter;

    var fragment = "in vec2 vMaskCoord;\nin vec2 vTextureCoord;\n\nuniform sampler2D uTexture;\nuniform sampler2D uMaskTexture;\n\nuniform float uAlpha;\nuniform vec4 uMaskClamp;\nuniform float uInverse;\n\nout vec4 finalColor;\n\nvoid main(void)\n{\n    float clip = step(3.5,\n        step(uMaskClamp.x, vMaskCoord.x) +\n        step(uMaskClamp.y, vMaskCoord.y) +\n        step(vMaskCoord.x, uMaskClamp.z) +\n        step(vMaskCoord.y, uMaskClamp.w));\n\n    // TODO look into why this is needed\n    float npmAlpha = uAlpha;\n    vec4 original = texture(uTexture, vTextureCoord);\n    vec4 masky = texture(uMaskTexture, vMaskCoord);\n    float alphaMul = 1.0 - npmAlpha * (1.0 - masky.a);\n\n    float a = alphaMul * masky.r * npmAlpha * clip;\n\n    if (uInverse == 1.0) {\n        a = 1.0 - a;\n    }\n\n    finalColor = original * a;\n}\n";

    var vertex = "in vec2 aPosition;\n\nout vec2 vTextureCoord;\nout vec2 vMaskCoord;\n\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\nuniform mat3 uFilterMatrix;\n\nvec4 filterVertexPosition(  vec2 aPosition )\n{\n    vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n       \n    position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord(  vec2 aPosition )\n{\n    return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvec2 getFilterCoord( vec2 aPosition )\n{\n    return  ( uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0)  ).xy;\n}   \n\nvoid main(void)\n{\n    gl_Position = filterVertexPosition(aPosition);\n    vTextureCoord = filterTextureCoord(aPosition);\n    vMaskCoord = getFilterCoord(aPosition);\n}\n";

    var source = "struct GlobalFilterUniforms {\n  uInputSize:vec4<f32>,\n  uInputPixel:vec4<f32>,\n  uInputClamp:vec4<f32>,\n  uOutputFrame:vec4<f32>,\n  uGlobalFrame:vec4<f32>,\n  uOutputTexture:vec4<f32>,\n};\n\nstruct MaskUniforms {\n  uFilterMatrix:mat3x3<f32>,\n  uMaskClamp:vec4<f32>,\n  uAlpha:f32,\n  uInverse:f32,\n};\n\n@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler : sampler;\n\n@group(1) @binding(0) var<uniform> filterUniforms : MaskUniforms;\n@group(1) @binding(1) var uMaskTexture: texture_2d<f32>;\n\nstruct VSOutput {\n    @builtin(position) position: vec4<f32>,\n    @location(0) uv : vec2<f32>,\n    @location(1) filterUv : vec2<f32>,\n};\n\nfn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>\n{\n    var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n    position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n    position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n    return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n    return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\nfn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return  (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);\n}\n\nfn getFilterCoord(aPosition:vec2<f32> ) -> vec2<f32>\n{\n  return ( filterUniforms.uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0)  ).xy;\n}\n\nfn getSize() -> vec2<f32>\n{\n  return gfu.uGlobalFrame.zw;\n}\n\n@vertex\nfn mainVertex(\n  @location(0) aPosition : vec2<f32>,\n) -> VSOutput {\n  return VSOutput(\n   filterVertexPosition(aPosition),\n   filterTextureCoord(aPosition),\n   getFilterCoord(aPosition)\n  );\n}\n\n@fragment\nfn mainFragment(\n  @location(0) uv: vec2<f32>,\n  @location(1) filterUv: vec2<f32>,\n  @builtin(position) position: vec4<f32>\n) -> @location(0) vec4<f32> {\n\n    var maskClamp = filterUniforms.uMaskClamp;\n    var uAlpha = filterUniforms.uAlpha;\n\n    var clip = step(3.5,\n      step(maskClamp.x, filterUv.x) +\n      step(maskClamp.y, filterUv.y) +\n      step(filterUv.x, maskClamp.z) +\n      step(filterUv.y, maskClamp.w));\n\n    var mask = textureSample(uMaskTexture, uSampler, filterUv);\n    var source = textureSample(uTexture, uSampler, uv);\n    var alphaMul = 1.0 - uAlpha * (1.0 - mask.a);\n\n    var a: f32 = alphaMul * mask.r * uAlpha * clip;\n\n    if (filterUniforms.uInverse == 1.0) {\n        a = 1.0 - a;\n    }\n\n    return source * a;\n}\n";

    "use strict";
    var __defProp$w = Object.defineProperty;
    var __defProps$e = Object.defineProperties;
    var __getOwnPropDescs$e = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$y = Object.getOwnPropertySymbols;
    var __hasOwnProp$y = Object.prototype.hasOwnProperty;
    var __propIsEnum$y = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$w = (obj, key, value) => key in obj ? __defProp$w(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$w = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$y.call(b, prop))
          __defNormalProp$w(a, prop, b[prop]);
      if (__getOwnPropSymbols$y)
        for (var prop of __getOwnPropSymbols$y(b)) {
          if (__propIsEnum$y.call(b, prop))
            __defNormalProp$w(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$e = (a, b) => __defProps$e(a, __getOwnPropDescs$e(b));
    var __objRest$d = (source2, exclude) => {
      var target = {};
      for (var prop in source2)
        if (__hasOwnProp$y.call(source2, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source2[prop];
      if (source2 != null && __getOwnPropSymbols$y)
        for (var prop of __getOwnPropSymbols$y(source2)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$y.call(source2, prop))
            target[prop] = source2[prop];
        }
      return target;
    };
    class MaskFilter extends Filter {
      constructor(options) {
        const _a = options, { sprite } = _a, rest = __objRest$d(_a, ["sprite"]);
        const textureMatrix = new TextureMatrix(sprite.texture);
        const filterUniforms = new UniformGroup({
          uFilterMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uMaskClamp: { value: textureMatrix.uClampFrame, type: "vec4<f32>" },
          uAlpha: { value: 1, type: "f32" },
          uInverse: { value: options.inverse ? 1 : 0, type: "f32" }
        });
        const gpuProgram = GpuProgram.from({
          vertex: {
            source,
            entryPoint: "mainVertex"
          },
          fragment: {
            source,
            entryPoint: "mainFragment"
          }
        });
        const glProgram = GlProgram.from({
          vertex,
          fragment,
          name: "mask-filter"
        });
        super(__spreadProps$e(__spreadValues$w({}, rest), {
          gpuProgram,
          glProgram,
          clipToViewport: false,
          resources: {
            filterUniforms,
            uMaskTexture: sprite.texture.source
          }
        }));
        this.sprite = sprite;
        this._textureMatrix = textureMatrix;
      }
      set inverse(value) {
        this.resources.filterUniforms.uniforms.uInverse = value ? 1 : 0;
      }
      get inverse() {
        return this.resources.filterUniforms.uniforms.uInverse === 1;
      }
      apply(filterManager, input, output, clearMode) {
        this._textureMatrix.texture = this.sprite.texture;
        filterManager.calculateSpriteMatrix(
          this.resources.filterUniforms.uniforms.uFilterMatrix,
          this.sprite
        ).prepend(this._textureMatrix.mapCoord);
        this.resources.uMaskTexture = this.sprite.texture.source;
        filterManager.applyFilter(this, input, output, clearMode);
      }
    }

    var hsl = "fn getLuminosity(c: vec3<f32>) -> f32 {\n  return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;\n}\n\nfn setLuminosity(c: vec3<f32>, lum: f32) -> vec3<f32> {\n  let d: f32 = lum - getLuminosity(c);\n  let newColor: vec3<f32> = c.rgb + vec3<f32>(d, d, d);\n\n  // clip back into legal range\n  let newLum: f32 = getLuminosity(newColor);\n  let cMin: f32 = min(newColor.r, min(newColor.g, newColor.b));\n  let cMax: f32 = max(newColor.r, max(newColor.g, newColor.b));\n\n  let t1: f32 = newLum / (newLum - cMin);\n  let t2: f32 = (1.0 - newLum) / (cMax - newLum);\n\n  let finalColor = mix(vec3<f32>(newLum, newLum, newLum), newColor, select(select(1.0, t2, cMax > 1.0), t1, cMin < 0.0));\n\n  return finalColor;\n}\n\nfn getSaturation(c: vec3<f32>) -> f32 {\n  return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));\n}\n\n// Set saturation if color components are sorted in ascending order.\nfn setSaturationMinMidMax(cSorted: vec3<f32>, s: f32) -> vec3<f32> {\n  var result: vec3<f32>;\n  if (cSorted.z > cSorted.x) {\n    let newY = (((cSorted.y - cSorted.x) * s) / (cSorted.z - cSorted.x));\n    result = vec3<f32>(0.0, newY, s);\n  } else {\n    result = vec3<f32>(0.0, 0.0, 0.0);\n  }\n  return vec3<f32>(result.x, result.y, result.z);\n}\n\nfn setSaturation(c: vec3<f32>, s: f32) -> vec3<f32> {\n    var result: vec3<f32> = c;\n\n    if (c.r <= c.g && c.r <= c.b) {\n        if (c.g <= c.b) {\n            result = setSaturationMinMidMax(result, s);\n        } else {\n            var temp: vec3<f32> = vec3<f32>(result.r, result.b, result.g);\n            temp = setSaturationMinMidMax(temp, s);\n            result = vec3<f32>(temp.r, temp.b, temp.g);\n        }\n    } else if (c.g <= c.r && c.g <= c.b) {\n        if (c.r <= c.b) {\n            var temp: vec3<f32> = vec3<f32>(result.g, result.r, result.b);\n            temp = setSaturationMinMidMax(temp, s);\n            result = vec3<f32>(temp.g, temp.r, temp.b);\n        } else {\n            var temp: vec3<f32> = vec3<f32>(result.g, result.b, result.r);\n            temp = setSaturationMinMidMax(temp, s);\n            result = vec3<f32>(temp.g, temp.b, temp.r);\n        }\n    } else {\n        if (c.r <= c.g) {\n            var temp: vec3<f32> = vec3<f32>(result.b, result.r, result.g);\n            temp = setSaturationMinMidMax(temp, s);\n            result = vec3<f32>(temp.b, temp.r, temp.g);\n        } else {\n            var temp: vec3<f32> = vec3<f32>(result.b, result.g, result.r);\n            temp = setSaturationMinMidMax(temp, s);\n            result = vec3<f32>(temp.b, temp.g, temp.r);\n        }\n    }\n\n    return result;\n}";

    "use strict";

    "use strict";
    const _PrepareBase = class _PrepareBase {
      /**
       * @param {Renderer} renderer - A reference to the current renderer
       */
      constructor(renderer) {
        /** called per frame by the ticker, defer processing to next tick */
        this._tick = () => {
          if (this._destroyed)
            return;
          this.timeout = setTimeout(this._processQueue, 0);
        };
        /** process the queue up to max item limit per frame */
        this._processQueue = () => {
          if (this._destroyed)
            return;
          const { queue } = this;
          let itemsProcessed = 0;
          while (queue.length && itemsProcessed < _PrepareBase.uploadsPerFrame) {
            const queueItem = queue.shift();
            this.uploadQueueItem(queueItem);
            itemsProcessed++;
          }
          if (queue.length) {
            Ticker.system.addOnce(this._tick, this, UPDATE_PRIORITY.UTILITY);
          } else {
            this._resolve();
          }
        };
        this.renderer = renderer;
        this.queue = [];
        this.resolves = [];
      }
      /**
       * Return a copy of the queue
       * @returns {PrepareQueueItem[]} The queue
       */
      getQueue() {
        return [...this.queue];
      }
      /**
       * Add a textures or graphics resource to the queue
       * @param {PrepareSourceItem | PrepareSourceItem[]} resource
       */
      add(resource) {
        const resourceArray = Array.isArray(resource) ? resource : [resource];
        for (const resourceItem of resourceArray) {
          if (resourceItem instanceof Container) {
            this._addContainer(resourceItem);
          } else {
            this.resolveQueueItem(resourceItem, this.queue);
          }
        }
        return this;
      }
      /**
       * Recursively add a container and its children to the queue
       * @param {Container} container - The container to add to the queue
       */
      _addContainer(container) {
        this.resolveQueueItem(container, this.queue);
        for (const child of container.children) {
          this._addContainer(child);
        }
      }
      /**
       * Upload all the textures and graphics to the GPU (optionally add more resources to the queue first)
       * @param {PrepareSourceItem | PrepareSourceItem[] | undefined} resource
       */
      upload(resource) {
        if (resource) {
          this.add(resource);
        }
        return new Promise((resolve) => {
          if (this.queue.length) {
            this.resolves.push(resolve);
            this.dedupeQueue();
            Ticker.system.addOnce(this._tick, this, UPDATE_PRIORITY.UTILITY);
          } else {
            resolve();
          }
        });
      }
      /** eliminate duplicates before processing */
      dedupeQueue() {
        const hash = /* @__PURE__ */ Object.create(null);
        let nextUnique = 0;
        for (let i = 0; i < this.queue.length; i++) {
          const current = this.queue[i];
          if (!hash[current.uid]) {
            hash[current.uid] = true;
            this.queue[nextUnique++] = current;
          }
        }
        this.queue.length = nextUnique;
      }
      destroy() {
        this._destroyed = true;
        clearTimeout(this.timeout);
      }
      /** Call all the resolve callbacks */
      _resolve() {
        const { resolves } = this;
        const array = resolves.slice(0);
        resolves.length = 0;
        for (const resolve of array) {
          resolve();
        }
      }
    };
    /** The number of uploads to process per frame */
    _PrepareBase.uploadsPerFrame = 4;
    let PrepareBase = _PrepareBase;

    "use strict";
    var __defProp$v = Object.defineProperty;
    var __getOwnPropSymbols$x = Object.getOwnPropertySymbols;
    var __hasOwnProp$x = Object.prototype.hasOwnProperty;
    var __propIsEnum$x = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$v = (obj, key, value) => key in obj ? __defProp$v(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$v = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$x.call(b, prop))
          __defNormalProp$v(a, prop, b[prop]);
      if (__getOwnPropSymbols$x)
        for (var prop of __getOwnPropSymbols$x(b)) {
          if (__propIsEnum$x.call(b, prop))
            __defNormalProp$v(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$c = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$x.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$x)
        for (var prop of __getOwnPropSymbols$x(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$x.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class Mesh extends ViewContainer {
      constructor(...args) {
        var _b;
        let options = args[0];
        if (options instanceof Geometry) {
          deprecation(v8_0_0, "Mesh: use new Mesh({ geometry, shader }) instead");
          options = {
            geometry: options,
            shader: args[1]
          };
          if (args[3]) {
            deprecation(v8_0_0, "Mesh: drawMode argument has been removed, use geometry.topology instead");
            options.geometry.topology = args[3];
          }
        }
        const _a = options, { geometry, shader, texture, roundPixels, state } = _a, rest = __objRest$c(_a, ["geometry", "shader", "texture", "roundPixels", "state"]);
        super(__spreadValues$v({
          label: "Mesh"
        }, rest));
        /** @internal */
        this.renderPipeId = "mesh";
        /** @internal */
        this._shader = null;
        this.allowChildren = false;
        this.shader = shader != null ? shader : null;
        this.texture = (_b = texture != null ? texture : shader == null ? void 0 : shader.texture) != null ? _b : Texture.WHITE;
        this.state = state != null ? state : State.for2d();
        this._geometry = geometry;
        this._geometry.on("update", this.onViewUpdate, this);
        this.roundPixels = roundPixels != null ? roundPixels : false;
      }
      /** Alias for {@link Mesh#shader}. */
      get material() {
        deprecation(v8_0_0, "mesh.material property has been removed, use mesh.shader instead");
        return this._shader;
      }
      /**
       * Represents the vertex and fragment shaders that processes the geometry and runs on the GPU.
       * Can be shared between multiple Mesh objects.
       */
      set shader(value) {
        if (this._shader === value)
          return;
        this._shader = value;
        this.onViewUpdate();
      }
      get shader() {
        return this._shader;
      }
      /**
       * Includes vertex positions, face indices, colors, UVs, and
       * custom attributes within buffers, reducing the cost of passing all
       * this data to the GPU. Can be shared between multiple Mesh objects.
       */
      set geometry(value) {
        var _a;
        if (this._geometry === value)
          return;
        (_a = this._geometry) == null ? void 0 : _a.off("update", this.onViewUpdate, this);
        value.on("update", this.onViewUpdate, this);
        this._geometry = value;
        this.onViewUpdate();
      }
      get geometry() {
        return this._geometry;
      }
      /** The texture that the Mesh uses. Null for non-MeshMaterial shaders */
      set texture(value) {
        value || (value = Texture.EMPTY);
        const currentTexture = this._texture;
        if (currentTexture === value)
          return;
        if (currentTexture && currentTexture.dynamic)
          currentTexture.off("update", this.onViewUpdate, this);
        if (value.dynamic)
          value.on("update", this.onViewUpdate, this);
        if (this.shader) {
          this.shader.texture = value;
        }
        this._texture = value;
        this.onViewUpdate();
      }
      get texture() {
        return this._texture;
      }
      get batched() {
        if (this._shader)
          return false;
        if ((this.state.data & 12) !== 0)
          return false;
        if (this._geometry instanceof MeshGeometry) {
          if (this._geometry.batchMode === "auto") {
            return this._geometry.positions.length / 2 <= 100;
          }
          return this._geometry.batchMode === "batch";
        }
        return false;
      }
      /**
       * The local bounds of the mesh.
       * @type {Bounds}
       */
      get bounds() {
        return this._geometry.bounds;
      }
      /**
       * Update local bounds of the mesh.
       * @private
       */
      updateBounds() {
        this._bounds = this._geometry.bounds;
      }
      /**
       * Checks if the object contains the given point.
       * @param point - The point to check
       */
      containsPoint(point) {
        const { x, y } = point;
        if (!this.bounds.containsPoint(x, y))
          return false;
        const vertices = this.geometry.getBuffer("aPosition").data;
        const step = this.geometry.topology === "triangle-strip" ? 3 : 1;
        if (this.geometry.getIndex()) {
          const indices = this.geometry.getIndex().data;
          const len = indices.length;
          for (let i = 0; i + 2 < len; i += step) {
            const ind0 = indices[i] * 2;
            const ind1 = indices[i + 1] * 2;
            const ind2 = indices[i + 2] * 2;
            if (pointInTriangle(
              x,
              y,
              vertices[ind0],
              vertices[ind0 + 1],
              vertices[ind1],
              vertices[ind1 + 1],
              vertices[ind2],
              vertices[ind2 + 1]
            )) {
              return true;
            }
          }
        } else {
          const len = vertices.length / 2;
          for (let i = 0; i + 2 < len; i += step) {
            const ind0 = i * 2;
            const ind1 = (i + 1) * 2;
            const ind2 = (i + 2) * 2;
            if (pointInTriangle(
              x,
              y,
              vertices[ind0],
              vertices[ind0 + 1],
              vertices[ind1],
              vertices[ind1 + 1],
              vertices[ind2],
              vertices[ind2 + 1]
            )) {
              return true;
            }
          }
        }
        return false;
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * mesh.destroy();
       * mesh.destroy(true);
       * mesh.destroy({ texture: true, textureSource: true });
       */
      destroy(options) {
        var _a;
        super.destroy(options);
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          this._texture.destroy(destroyTextureSource);
        }
        (_a = this._geometry) == null ? void 0 : _a.off("update", this.onViewUpdate, this);
        this._texture = null;
        this._geometry = null;
        this._shader = null;
      }
    }

    "use strict";
    var __defProp$u = Object.defineProperty;
    var __defProps$d = Object.defineProperties;
    var __getOwnPropDescs$d = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$w = Object.getOwnPropertySymbols;
    var __hasOwnProp$w = Object.prototype.hasOwnProperty;
    var __propIsEnum$w = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$u = (obj, key, value) => key in obj ? __defProp$u(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$u = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$w.call(b, prop))
          __defNormalProp$u(a, prop, b[prop]);
      if (__getOwnPropSymbols$w)
        for (var prop of __getOwnPropSymbols$w(b)) {
          if (__propIsEnum$w.call(b, prop))
            __defNormalProp$u(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$d = (a, b) => __defProps$d(a, __getOwnPropDescs$d(b));
    var __objRest$b = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$w.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$w)
        for (var prop of __getOwnPropSymbols$w(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$w.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class AnimatedSprite extends Sprite {
      constructor(...args) {
        let options = args[0];
        if (Array.isArray(args[0])) {
          options = {
            textures: args[0],
            autoUpdate: args[1]
          };
        }
        const _a = options, {
          animationSpeed = 1,
          autoPlay = false,
          autoUpdate = true,
          loop = true,
          onComplete = null,
          onFrameChange = null,
          onLoop = null,
          textures,
          updateAnchor = false
        } = _a, rest = __objRest$b(_a, [
          "animationSpeed",
          "autoPlay",
          "autoUpdate",
          "loop",
          "onComplete",
          "onFrameChange",
          "onLoop",
          "textures",
          "updateAnchor"
        ]);
        const [firstFrame] = textures;
        super(__spreadProps$d(__spreadValues$u({}, rest), {
          texture: firstFrame instanceof Texture ? firstFrame : firstFrame.texture
        }));
        this._textures = null;
        this._durations = null;
        this._autoUpdate = autoUpdate;
        this._isConnectedToTicker = false;
        this.animationSpeed = animationSpeed;
        this.loop = loop;
        this.updateAnchor = updateAnchor;
        this.onComplete = onComplete;
        this.onFrameChange = onFrameChange;
        this.onLoop = onLoop;
        this._currentTime = 0;
        this._playing = false;
        this._previousFrame = null;
        this.textures = textures;
        if (autoPlay) {
          this.play();
        }
      }
      /**
       * Stops the animation playback and freezes the current frame.
       * Does not reset the current frame or animation progress.
       * @example
       * ```ts
       * // Create an animated sprite
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('walk1.png'),
       *         Texture.from('walk2.png'),
       *         Texture.from('walk3.png')
       *     ],
       *     autoPlay: true
       * });
       *
       * // Stop at current frame
       * sprite.stop();
       *
       * // Stop at specific frame
       * sprite.gotoAndStop(1); // Stops at second frame
       *
       * // Stop and reset
       * sprite.stop();
       * sprite.currentFrame = 0;
       *
       * // Stop with completion check
       * if (sprite.playing) {
       *     sprite.stop();
       *     sprite.onComplete?.();
       * }
       * ```
       * @see {@link AnimatedSprite#play} For starting playback
       * @see {@link AnimatedSprite#gotoAndStop} For stopping at a specific frame
       * @see {@link AnimatedSprite#playing} For checking play state
       */
      stop() {
        if (!this._playing) {
          return;
        }
        this._playing = false;
        if (this._autoUpdate && this._isConnectedToTicker) {
          Ticker.shared.remove(this.update, this);
          this._isConnectedToTicker = false;
        }
      }
      /**
       * Starts or resumes the animation playback.
       * If the animation was previously stopped, it will continue from where it left off.
       * @example
       * ```ts
       * // Basic playback
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('walk1.png'),
       *         Texture.from('walk2.png'),
       *     ],
       *     autoPlay: false
       * });
       * sprite.play();
       *
       * // Play after stopping
       * sprite.stop();
       * sprite.currentFrame = 0; // Reset to start
       * sprite.play(); // Play from beginning
       *
       * // Play with auto-update disabled
       * sprite.autoUpdate = false;
       * sprite.play();
       * app.ticker.add(() => {
       *     sprite.update(app.ticker); // Manual updates
       * });
       * ```
       * @see {@link AnimatedSprite#stop} For stopping playback
       * @see {@link AnimatedSprite#gotoAndPlay} For playing from a specific frame
       * @see {@link AnimatedSprite#playing} For checking play state
       */
      play() {
        if (this._playing) {
          return;
        }
        this._playing = true;
        if (this._autoUpdate && !this._isConnectedToTicker) {
          Ticker.shared.add(this.update, this, UPDATE_PRIORITY.HIGH);
          this._isConnectedToTicker = true;
        }
      }
      /**
       * Stops the AnimatedSprite and sets it to a specific frame.
       * @example
       * ```ts
       * // Create an animated sprite
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('walk1.png'),
       *         Texture.from('walk2.png'),
       *         Texture.from('walk3.png'),
       *     ]
       * });
       *
       * // Go to specific frames
       * sprite.gotoAndStop(0);  // First frame
       * sprite.gotoAndStop(2);  // Third frame
       *
       * // Jump to last frame
       * sprite.gotoAndStop(sprite.totalFrames - 1);
       * ```
       * @param frameNumber - Frame index to stop at (0-based)
       * @throws {Error} If frameNumber is out of bounds
       * @see {@link AnimatedSprite#gotoAndPlay} For going to a frame and playing
       * @see {@link AnimatedSprite#currentFrame} For getting/setting current frame
       * @see {@link AnimatedSprite#totalFrames} For total number of frames
       */
      gotoAndStop(frameNumber) {
        this.stop();
        this.currentFrame = frameNumber;
      }
      /**
       * Goes to a specific frame and begins playing the AnimatedSprite from that point.
       * Combines frame navigation and playback start in one operation.
       * @example
       * ```ts
       * // Start from specific frame
       * sprite.gotoAndPlay(1); // Starts playing from second frame
       * ```
       * @param frameNumber - Frame index to start playing from (0-based)
       * @throws {Error} If frameNumber is out of bounds
       * @see {@link AnimatedSprite#gotoAndStop} For going to a frame without playing
       * @see {@link AnimatedSprite#play} For playing from current frame
       * @see {@link AnimatedSprite#currentFrame} For getting/setting current frame
       */
      gotoAndPlay(frameNumber) {
        this.currentFrame = frameNumber;
        this.play();
      }
      /**
       * Updates the object transform for rendering. This method handles animation timing, frame updates,
       * and manages looping behavior.
       * @example
       * ```ts
       * // Create an animated sprite with manual updates
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('frame1.png'),
       *         Texture.from('frame2.png'),
       *         Texture.from('frame3.png')
       *     ],
       *     autoUpdate: false // Disable automatic updates
       * });
       *
       * // Manual update with app ticker
       * app.ticker.add((ticker) => {
       *     sprite.update(ticker);
       * });
       * ```
       * @param ticker - The ticker to use for updating the animation timing
       * @see {@link AnimatedSprite#autoUpdate} For controlling automatic updates
       * @see {@link AnimatedSprite#animationSpeed} For controlling animation speed
       * @see {@link Ticker} For timing system details
       */
      update(ticker) {
        if (!this._playing) {
          return;
        }
        const deltaTime = ticker.deltaTime;
        const elapsed = this.animationSpeed * deltaTime;
        const previousFrame = this.currentFrame;
        if (this._durations !== null) {
          let lag = this._currentTime % 1 * this._durations[this.currentFrame];
          lag += elapsed / 60 * 1e3;
          while (lag < 0) {
            this._currentTime--;
            lag += this._durations[this.currentFrame];
          }
          const sign = Math.sign(this.animationSpeed * deltaTime);
          this._currentTime = Math.floor(this._currentTime);
          while (lag >= this._durations[this.currentFrame]) {
            lag -= this._durations[this.currentFrame] * sign;
            this._currentTime += sign;
          }
          this._currentTime += lag / this._durations[this.currentFrame];
        } else {
          this._currentTime += elapsed;
        }
        if (this._currentTime < 0 && !this.loop) {
          this.gotoAndStop(0);
          if (this.onComplete) {
            this.onComplete();
          }
        } else if (this._currentTime >= this._textures.length && !this.loop) {
          this.gotoAndStop(this._textures.length - 1);
          if (this.onComplete) {
            this.onComplete();
          }
        } else if (previousFrame !== this.currentFrame) {
          if (this.loop && this.onLoop) {
            if (this.animationSpeed > 0 && this.currentFrame < previousFrame || this.animationSpeed < 0 && this.currentFrame > previousFrame) {
              this.onLoop();
            }
          }
          this._updateTexture();
        }
      }
      /** Updates the displayed texture to match the current frame index. */
      _updateTexture() {
        const currentFrame = this.currentFrame;
        if (this._previousFrame === currentFrame) {
          return;
        }
        this._previousFrame = currentFrame;
        this.texture = this._textures[currentFrame];
        if (this.updateAnchor && this.texture.defaultAnchor) {
          this.anchor.copyFrom(this.texture.defaultAnchor);
        }
        if (this.onFrameChange) {
          this.onFrameChange(this.currentFrame);
        }
      }
      /**
       * Stops the AnimatedSprite and destroys it.
       * This method stops the animation playback, removes it from the ticker,
       * and cleans up any resources associated with the sprite.
       * @param options - Options for destroying the sprite, such as whether to remove from parent
       * @example
       * ```ts
       * // Destroy the sprite when done
       * sprite.destroy();
       * // Or with options
       * sprite.destroy({ children: true, texture: true, textureSource: true });
       * ```
       */
      destroy(options = false) {
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          this._textures.forEach((texture) => {
            if (this.texture !== texture) {
              texture.destroy(destroyTextureSource);
            }
          });
        }
        this._textures = [];
        this._durations = null;
        this.stop();
        super.destroy(options);
        this.onComplete = null;
        this.onFrameChange = null;
        this.onLoop = null;
      }
      /**
       * A short hand way of creating an AnimatedSprite from an array of frame ids.
       * Uses texture frames from the cache to create an animation sequence.
       * @example
       * ```ts
       * // Create from frame IDs
       * const frameIds = [
       *     'walk_001.png',
       *     'walk_002.png',
       *     'walk_003.png'
       * ];
       *
       * const walkingAnimation = AnimatedSprite.fromFrames(frameIds);
       * walkingAnimation.play();
       * ```
       * @param frames - The array of frame ids to use for the animation
       * @returns A new animated sprite using the frames
       * @see {@link Texture.from} For texture creation from frames
       * @see {@link Spritesheet} For loading spritesheets
       */
      static fromFrames(frames) {
        const textures = [];
        for (let i = 0; i < frames.length; ++i) {
          textures.push(Texture.from(frames[i]));
        }
        return new AnimatedSprite(textures);
      }
      /**
       * A short hand way of creating an AnimatedSprite from an array of image urls.
       * Each image will be used as a frame in the animation.
       * @example
       * ```ts
       * // Create from image URLs
       * const images = [
       *     'assets/walk1.png',
       *     'assets/walk2.png',
       *     'assets/walk3.png'
       * ];
       *
       * const walkingSprite = AnimatedSprite.fromImages(images);
       * walkingSprite.play();
       * ```
       * @param images - The array of image urls to use as frames
       * @returns A new animated sprite using the images as frames
       * @see {@link Assets} For asset loading and management
       * @see {@link Texture.from} For texture creation from images
       */
      static fromImages(images) {
        const textures = [];
        for (let i = 0; i < images.length; ++i) {
          textures.push(Texture.from(images[i]));
        }
        return new AnimatedSprite(textures);
      }
      /**
       * The total number of frames in the AnimatedSprite. This is the same as number of textures
       * assigned to the AnimatedSprite.
       * @example
       * ```ts
       * // Create an animated sprite
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('frame1.png'),
       *         Texture.from('frame2.png'),
       *         Texture.from('frame3.png')
       *     ]
       * });
       *
       * // Get total frames
       * console.log(sprite.totalFrames); // Outputs: 3
       *
       * // Use with frame navigation
       * sprite.gotoAndStop(sprite.totalFrames - 1); // Go to last frame
       * ```
       * @readonly
       * @see {@link AnimatedSprite#currentFrame} For the current frame index
       * @see {@link AnimatedSprite#textures} For the array of textures
       * @returns {number} The total number of frames
       */
      get totalFrames() {
        return this._textures.length;
      }
      /**
       * The array of textures or frame objects used for the animation sequence.
       * Can be set to either an array of Textures or an array of FrameObjects with custom timing.
       * @example
       * ```ts
       * // Update textures at runtime
       * sprite.textures = [
       *     Texture.from('run1.png'),
       *     Texture.from('run2.png')
       * ];
       *
       * // Use custom frame timing
       * sprite.textures = [
       *     { texture: Texture.from('explosion1.png'), time: 100 },
       *     { texture: Texture.from('explosion2.png'), time: 200 },
       *     { texture: Texture.from('explosion3.png'), time: 300 }
       * ];
       *
       * // Use with spritesheet
       * const sheet = await Assets.load('animations.json');
       * sprite.textures = sheet.animations['walk'];
       * ```
       * @type {AnimatedSpriteFrames}
       * @see {@link FrameObject} For frame timing options
       * @see {@link Spritesheet} For loading from spritesheets
       */
      get textures() {
        return this._textures;
      }
      set textures(value) {
        if (value[0] instanceof Texture) {
          this._textures = value;
          this._durations = null;
        } else {
          this._textures = [];
          this._durations = [];
          for (let i = 0; i < value.length; i++) {
            this._textures.push(value[i].texture);
            this._durations.push(value[i].time);
          }
        }
        this._previousFrame = null;
        this.gotoAndStop(0);
        this._updateTexture();
      }
      /**
       * Gets or sets the current frame index of the animation.
       * When setting, the value will be clamped between 0 and totalFrames - 1.
       * @example
       * ```ts
       * // Create an animated sprite
       * const sprite = new AnimatedSprite({
       *     textures: [
       *         Texture.from('walk1.png'),
       *         Texture.from('walk2.png'),
       *         Texture.from('walk3.png')
       *     ]
       * });
       *
       * // Get current frame
       * console.log(sprite.currentFrame); // 0
       *
       * // Set specific frame
       * sprite.currentFrame = 1; // Show second frame
       *
       * // Use with frame callbacks
       * sprite.onFrameChange = (frame) => {
       *     console.log(`Now showing frame: ${frame}`);
       * };
       * sprite.currentFrame = 2;
       * ```
       * @throws {Error} If attempting to set a frame index out of bounds
       * @see {@link AnimatedSprite#totalFrames} For the total number of frames
       * @see {@link AnimatedSprite#gotoAndPlay} For playing from a specific frame
       * @see {@link AnimatedSprite#gotoAndStop} For stopping at a specific frame
       */
      get currentFrame() {
        let currentFrame = Math.floor(this._currentTime) % this._textures.length;
        if (currentFrame < 0) {
          currentFrame += this._textures.length;
        }
        return currentFrame;
      }
      set currentFrame(value) {
        if (value < 0 || value > this.totalFrames - 1) {
          throw new Error(`[AnimatedSprite]: Invalid frame index value ${value}, expected to be between 0 and totalFrames ${this.totalFrames}.`);
        }
        const previousFrame = this.currentFrame;
        this._currentTime = value;
        if (previousFrame !== this.currentFrame) {
          this._updateTexture();
        }
      }
      /**
       * Indicates if the AnimatedSprite is currently playing.
       * This is a read-only property that reflects the current playback state.
       * @example
       * ```ts
       * // Check if animation is playing
       * console.log('Playing:', sprite.playing); // true
       *
       * // Use with play control
       * if (!sprite.playing) {
       *     sprite.play();
       * }
       * ```
       * @readonly
       * @returns {boolean} True if the animation is currently playing
       * @see {@link AnimatedSprite#play} For starting playback
       * @see {@link AnimatedSprite#stop} For stopping playback
       * @see {@link AnimatedSprite#loop} For controlling looping behavior
       */
      get playing() {
        return this._playing;
      }
      /**
       * Controls whether the animation automatically updates using the shared ticker.
       * When enabled, the animation will update on each frame. When disabled, you must
       * manually call update() to advance the animation.
       * @example
       * ```ts
       * // Create sprite with auto-update disabled
       * const sprite = new AnimatedSprite({
       *     textures: [],
       *     autoUpdate: false
       * });
       *
       * // Manual update with app ticker
       * app.ticker.add((ticker) => {
       *     sprite.update(ticker);
       * });
       *
       * // Enable auto-update later
       * sprite.autoUpdate = true;
       * ```
       * @default true
       * @see {@link AnimatedSprite#update} For manual animation updates
       * @see {@link Ticker} For the timing system
       */
      get autoUpdate() {
        return this._autoUpdate;
      }
      set autoUpdate(value) {
        if (value !== this._autoUpdate) {
          this._autoUpdate = value;
          if (!this._autoUpdate && this._isConnectedToTicker) {
            Ticker.shared.remove(this.update, this);
            this._isConnectedToTicker = false;
          } else if (this._autoUpdate && !this._isConnectedToTicker && this._playing) {
            Ticker.shared.add(this.update, this);
            this._isConnectedToTicker = true;
          }
        }
      }
    }

    "use strict";
    class Transform {
      /**
       * @param options - Options for the transform.
       * @param options.matrix - The matrix to use.
       * @param options.observer - The observer to use.
       */
      constructor({ matrix, observer } = {}) {
        this.dirty = true;
        this._matrix = matrix != null ? matrix : new Matrix();
        this.observer = observer;
        this.position = new ObservablePoint(this, 0, 0);
        this.scale = new ObservablePoint(this, 1, 1);
        this.pivot = new ObservablePoint(this, 0, 0);
        this.skew = new ObservablePoint(this, 0, 0);
        this._rotation = 0;
        this._cx = 1;
        this._sx = 0;
        this._cy = 0;
        this._sy = 1;
      }
      /**
       * The transformation matrix computed from the transform's properties.
       * Combines position, scale, rotation, skew, and pivot into a single matrix.
       * @example
       * ```ts
       * // Get current matrix
       * const matrix = transform.matrix;
       * console.log(matrix.toString());
       * ```
       * @readonly
       * @see {@link Matrix} For matrix operations
       * @see {@link Transform.setFromMatrix} For setting transform from matrix
       */
      get matrix() {
        const lt = this._matrix;
        if (!this.dirty)
          return lt;
        lt.a = this._cx * this.scale.x;
        lt.b = this._sx * this.scale.x;
        lt.c = this._cy * this.scale.y;
        lt.d = this._sy * this.scale.y;
        lt.tx = this.position.x - (this.pivot.x * lt.a + this.pivot.y * lt.c);
        lt.ty = this.position.y - (this.pivot.x * lt.b + this.pivot.y * lt.d);
        this.dirty = false;
        return lt;
      }
      /**
       * Called when a value changes.
       * @param point
       * @internal
       */
      _onUpdate(point) {
        var _a;
        this.dirty = true;
        if (point === this.skew) {
          this.updateSkew();
        }
        (_a = this.observer) == null ? void 0 : _a._onUpdate(this);
      }
      /** Called when the skew or the rotation changes. */
      updateSkew() {
        this._cx = Math.cos(this._rotation + this.skew.y);
        this._sx = Math.sin(this._rotation + this.skew.y);
        this._cy = -Math.sin(this._rotation - this.skew.x);
        this._sy = Math.cos(this._rotation - this.skew.x);
        this.dirty = true;
      }
      toString() {
        return `[pixi.js/math:Transform position=(${this.position.x}, ${this.position.y}) rotation=${this.rotation} scale=(${this.scale.x}, ${this.scale.y}) skew=(${this.skew.x}, ${this.skew.y}) ]`;
      }
      /**
       * Decomposes a matrix and sets the transforms properties based on it.
       * @example
       * ```ts
       * // Basic matrix decomposition
       * const transform = new Transform();
       * const matrix = new Matrix()
       *     .translate(100, 100)
       *     .rotate(Math.PI / 4)
       *     .scale(2, 2);
       *
       * transform.setFromMatrix(matrix);
       * console.log(transform.position.x); // 100
       * console.log(transform.rotation); // ~0.785 (π/4)
       * ```
       * @param matrix - The matrix to decompose
       * @see {@link Matrix#decompose} For the decomposition logic
       * @see {@link Transform#matrix} For getting the current matrix
       */
      setFromMatrix(matrix) {
        matrix.decompose(this);
        this.dirty = true;
      }
      /**
       * The rotation of the object in radians.
       * @example
       * ```ts
       * // Basic rotation
       * transform.rotation = Math.PI / 4; // 45 degrees
       *
       * // Rotate around pivot point
       * transform.pivot.set(50, 50);
       * transform.rotation = Math.PI; // 180 degrees around pivot
       *
       * // Animate rotation
       * app.ticker.add(() => {
       *     transform.rotation += 0.1;
       * });
       * ```
       * @see {@link Transform#pivot} For rotation point
       * @see {@link Transform#skew} For skew effects
       */
      get rotation() {
        return this._rotation;
      }
      set rotation(value) {
        if (this._rotation !== value) {
          this._rotation = value;
          this._onUpdate(this.skew);
        }
      }
    }

    "use strict";
    var __defProp$t = Object.defineProperty;
    var __getOwnPropSymbols$v = Object.getOwnPropertySymbols;
    var __hasOwnProp$v = Object.prototype.hasOwnProperty;
    var __propIsEnum$v = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$t = (obj, key, value) => key in obj ? __defProp$t(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$t = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$v.call(b, prop))
          __defNormalProp$t(a, prop, b[prop]);
      if (__getOwnPropSymbols$v)
        for (var prop of __getOwnPropSymbols$v(b)) {
          if (__propIsEnum$v.call(b, prop))
            __defNormalProp$t(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$a = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$v.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$v)
        for (var prop of __getOwnPropSymbols$v(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$v.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const _TilingSprite = class _TilingSprite extends ViewContainer {
      constructor(...args) {
        let options = args[0] || {};
        if (options instanceof Texture) {
          options = { texture: options };
        }
        if (args.length > 1) {
          deprecation(v8_0_0, "use new TilingSprite({ texture, width:100, height:100 }) instead");
          options.width = args[1];
          options.height = args[2];
        }
        options = __spreadValues$t(__spreadValues$t({}, _TilingSprite.defaultOptions), options);
        const _a = options != null ? options : {}, {
          texture,
          anchor,
          tilePosition,
          tileScale,
          tileRotation,
          width,
          height,
          applyAnchorToTexture,
          roundPixels
        } = _a, rest = __objRest$a(_a, [
          "texture",
          "anchor",
          "tilePosition",
          "tileScale",
          "tileRotation",
          "width",
          "height",
          "applyAnchorToTexture",
          "roundPixels"
        ]);
        super(__spreadValues$t({
          label: "TilingSprite"
        }, rest));
        /** @internal */
        this.renderPipeId = "tilingSprite";
        /** @advanced */
        this.batched = true;
        this.allowChildren = false;
        this._anchor = new ObservablePoint(
          {
            _onUpdate: () => {
              this.onViewUpdate();
            }
          }
        );
        this.applyAnchorToTexture = applyAnchorToTexture;
        this.texture = texture;
        this._width = width != null ? width : texture.width;
        this._height = height != null ? height : texture.height;
        this._tileTransform = new Transform({
          observer: {
            _onUpdate: () => this.onViewUpdate()
          }
        });
        if (anchor)
          this.anchor = anchor;
        this.tilePosition = tilePosition;
        this.tileScale = tileScale;
        this.tileRotation = tileRotation;
        this.roundPixels = roundPixels != null ? roundPixels : false;
      }
      /**
       * Creates a new tiling sprite based on a source texture or image path.
       * This is a convenience method that automatically creates and manages textures.
       * @example
       * ```ts
       * // Create a new tiling sprite from an image path
       * const pattern = TilingSprite.from('pattern.png');
       * pattern.width = 300; // Set the width of the tiling area
       * pattern.height = 200; // Set the height of the tiling area
       *
       * // Create from options
       * const texture = Texture.from('pattern.png');
       * const pattern = TilingSprite.from(texture, {
       *     width: 300,
       *     height: 200,
       *     tileScale: { x: 0.5, y: 0.5 }
       * });
       * ```
       * @param source - The source to create the sprite from. Can be a path to an image or a texture
       * @param options - Additional options for the tiling sprite
       * @returns A new tiling sprite based on the source
       * @see {@link Texture.from} For texture creation details
       * @see {@link Assets} For asset loading and management
       */
      static from(source, options = {}) {
        if (typeof source === "string") {
          return new _TilingSprite(__spreadValues$t({
            texture: Cache.get(source)
          }, options));
        }
        return new _TilingSprite(__spreadValues$t({
          texture: source
        }, options));
      }
      /**
       * @see {@link TilingSpriteOptions.applyAnchorToTexture}
       * @deprecated since 8.0.0
       * @advanced
       */
      get uvRespectAnchor() {
        deprecation(v8_0_0, "uvRespectAnchor is deprecated, please use applyAnchorToTexture instead");
        return this.applyAnchorToTexture;
      }
      /** @advanced */
      set uvRespectAnchor(value) {
        deprecation(v8_0_0, "uvRespectAnchor is deprecated, please use applyAnchorToTexture instead");
        this.applyAnchorToTexture = value;
      }
      /**
       * Changes frame clamping in corresponding textureMatrix
       * Change to -0.5 to add a pixel to the edge, recommended for transparent trimmed textures in atlas
       * @default 0.5
       * @type {number}
       * @advanced
       */
      get clampMargin() {
        return this._texture.textureMatrix.clampMargin;
      }
      /** @advanced */
      set clampMargin(value) {
        this._texture.textureMatrix.clampMargin = value;
      }
      /**
       * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
       * and passed to the constructor.
       *
       * - The default is `(0,0)`, this means the sprite's origin is the top left.
       * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
       * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
       *
       * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
       * @example
       * ```ts
       * // Center the anchor point
       * sprite.anchor = 0.5; // Sets both x and y to 0.5
       * sprite.position.set(400, 300); // Sprite will be centered at this position
       *
       * // Set specific x/y anchor points
       * sprite.anchor = {
       *     x: 1, // Right edge
       *     y: 0  // Top edge
       * };
       *
       * // Using individual coordinates
       * sprite.anchor.set(0.5, 1); // Center-bottom
       *
       * // For rotation around center
       * sprite.anchor.set(0.5);
       * sprite.rotation = Math.PI / 4; // 45 degrees around center
       *
       * // For scaling from center
       * sprite.anchor.set(0.5);
       * sprite.scale.set(2); // Scales from center point
       * ```
       */
      get anchor() {
        return this._anchor;
      }
      set anchor(value) {
        typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
      }
      /**
       * The offset of the tiling texture.
       * Used to scroll or position the repeated pattern.
       * @example
       * ```ts
       * // Offset the tiling pattern by 100 pixels in both x and y directions
       * tilingSprite.tilePosition = { x: 100, y: 100 };
       * ```
       * @default {x: 0, y: 0}
       */
      get tilePosition() {
        return this._tileTransform.position;
      }
      set tilePosition(value) {
        this._tileTransform.position.copyFrom(value);
      }
      /**
       * Scale of the tiling texture.
       * Affects the size of each repeated instance of the texture.
       * @example
       * ```ts
       * // Scale the texture by 1.5 in both x and y directions
       * tilingSprite.tileScale = { x: 1.5, y: 1.5 };
       * ```
       * @default {x: 1, y: 1}
       */
      get tileScale() {
        return this._tileTransform.scale;
      }
      set tileScale(value) {
        typeof value === "number" ? this._tileTransform.scale.set(value) : this._tileTransform.scale.copyFrom(value);
      }
      set tileRotation(value) {
        this._tileTransform.rotation = value;
      }
      /**
       * Rotation of the tiling texture in radians.
       * This controls the rotation applied to the texture before tiling.
       * @example
       * ```ts
       * // Rotate the texture by 45 degrees (in radians)
       * tilingSprite.tileRotation = Math.PI / 4; // 45 degrees
       * ```
       * @default 0
       */
      get tileRotation() {
        return this._tileTransform.rotation;
      }
      /**
       * The transform object that controls the tiling texture's position, scale, and rotation.
       * This transform is independent of the sprite's own transform properties.
       * @example
       * ```ts
       * // Access transform properties directly
       * sprite.tileTransform.position.set(100, 50);
       * sprite.tileTransform.scale.set(2);
       * sprite.tileTransform.rotation = Math.PI / 4;
       *
       * // Create smooth scrolling animation
       * app.ticker.add(() => {
       *     sprite.tileTransform.position.x += 1;
       *     sprite.tileTransform.rotation += 0.01;
       * });
       *
       * // Reset transform
       * sprite.tileTransform.position.set(0);
       * sprite.tileTransform.scale.set(1);
       * sprite.tileTransform.rotation = 0;
       * ```
       * @returns {Transform} The transform object for the tiling texture
       * @see {@link Transform} For transform operations
       * @see {@link TilingSprite#tilePosition} For position control
       * @see {@link TilingSprite#tileScale} For scale control
       * @see {@link TilingSprite#tileRotation} For rotation control
       * @advanced
       */
      get tileTransform() {
        return this._tileTransform;
      }
      set texture(value) {
        value || (value = Texture.EMPTY);
        const currentTexture = this._texture;
        if (currentTexture === value)
          return;
        if (currentTexture && currentTexture.dynamic)
          currentTexture.off("update", this.onViewUpdate, this);
        if (value.dynamic)
          value.on("update", this.onViewUpdate, this);
        this._texture = value;
        this.onViewUpdate();
      }
      /**
       * The texture to use for tiling.
       * This is the image that will be repeated across the sprite.
       * @example
       * ```ts
       * // Use a texture from the asset cache
       * tilingSprite.texture = Texture.from('assets/pattern.png');
       * ```
       * @default Texture.WHITE
       */
      get texture() {
        return this._texture;
      }
      /**
       * The width of the tiling area. This defines how wide the area is that the texture will be tiled across.
       * @example
       * ```ts
       * // Create a tiling sprite
       * const sprite = new TilingSprite({
       *     texture: Texture.from('pattern.png'),
       *     width: 500,
       *     height: 300
       * });
       *
       * // Adjust width dynamically
       * sprite.width = 800; // Expands tiling area
       *
       * // Update on resize
       * window.addEventListener('resize', () => {
       *     sprite.width = app.screen.width;
       * });
       * ```
       * @see {@link TilingSprite#setSize} For setting both width and height efficiently
       * @see {@link TilingSprite#height} For setting height
       */
      set width(value) {
        this._width = value;
        this.onViewUpdate();
      }
      get width() {
        return this._width;
      }
      set height(value) {
        this._height = value;
        this.onViewUpdate();
      }
      /**
       * The height of the tiling area. This defines how tall the area is that the texture will be tiled across.
       * @example
       * ```ts
       * // Create a tiling sprite
       * const sprite = new TilingSprite({
       *     texture: Texture.from('pattern.png'),
       *     width: 500,
       *     height: 300
       * });
       *
       * // Adjust width dynamically
       * sprite.height = 800; // Expands tiling area
       *
       * // Update on resize
       * window.addEventListener('resize', () => {
       *     sprite.height = app.screen.height;
       * });
       * ```
       * @see {@link TilingSprite#setSize} For setting both width and height efficiently
       * @see {@link TilingSprite#width} For setting width
       */
      get height() {
        return this._height;
      }
      /**
       * Sets the size of the TilingSprite to the specified width and height.
       * This is faster than setting width and height separately as it only triggers one update.
       * @example
       * ```ts
       * // Set specific dimensions
       * sprite.setSize(300, 200); // Width: 300, Height: 200
       *
       * // Set uniform size (square)
       * sprite.setSize(400); // Width: 400, Height: 400
       *
       * // Set size using object
       * sprite.setSize({
       *     width: 500,
       *     height: 300
       * });
       * ```
       * @param value - This can be either a number for uniform sizing or a Size object with width/height properties
       * @param height - The height to set. Defaults to the value of `width` if not provided
       * @see {@link TilingSprite#width} For setting width only
       * @see {@link TilingSprite#height} For setting height only
       */
      setSize(value, height) {
        var _a;
        if (typeof value === "object") {
          height = (_a = value.height) != null ? _a : value.width;
          value = value.width;
        }
        this._width = value;
        this._height = height != null ? height : value;
        this.onViewUpdate();
      }
      /**
       * Retrieves the size of the TilingSprite as a {@link Size} object.
       * This method is more efficient than getting width and height separately as it only allocates one object.
       * @example
       * ```ts
       * // Get basic size
       * const size = sprite.getSize();
       * console.log(`Size: ${size.width}x${size.height}`);
       *
       * // Reuse existing size object
       * const reuseSize = { width: 0, height: 0 };
       * sprite.getSize(reuseSize);
       * ```
       * @param out - Optional object to store the size in, to avoid allocating a new object
       * @returns The size of the TilingSprite
       * @see {@link TilingSprite#width} For getting just the width
       * @see {@link TilingSprite#height} For getting just the height
       * @see {@link TilingSprite#setSize} For setting both width and height efficiently
       */
      getSize(out) {
        out || (out = {});
        out.width = this._width;
        out.height = this._height;
        return out;
      }
      /** @private */
      updateBounds() {
        const bounds = this._bounds;
        const anchor = this._anchor;
        const width = this._width;
        const height = this._height;
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
      /**
       * Checks if the object contains the given point in local coordinates.
       * Takes into account the anchor offset when determining boundaries.
       * @example
       * ```ts
       * // Create a tiling sprite
       * const sprite = new TilingSprite({
       *     texture: Texture.from('pattern.png'),
       *     width: 200,
       *     height: 100,
       *     anchor: 0.5 // Center anchor
       * });
       *
       * // Basic point check
       * const contains = sprite.containsPoint({ x: 50, y: 25 });
       * console.log('Point is inside:', contains);
       *
       * // Check with different anchors
       * sprite.anchor.set(0); // Top-left anchor
       * console.log('Contains point:', sprite.containsPoint({ x: 150, y: 75 }));
       * ```
       * @param point - The point to check in local coordinates
       * @returns True if the point is within the sprite's bounds
       * @see {@link TilingSprite#toLocal} For converting global coordinates to local
       * @see {@link TilingSprite#anchor} For understanding boundary calculations
       */
      containsPoint(point) {
        const width = this._width;
        const height = this._height;
        const x1 = -width * this._anchor._x;
        let y1 = 0;
        if (point.x >= x1 && point.x <= x1 + width) {
          y1 = -height * this._anchor._y;
          if (point.y >= y1 && point.y <= y1 + height)
            return true;
        }
        return false;
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * tilingSprite.destroy();
       * tilingSprite.destroy(true);
       * tilingSprite.destroy({ texture: true, textureSource: true });
       */
      destroy(options = false) {
        super.destroy(options);
        this._anchor = null;
        this._tileTransform = null;
        this._bounds = null;
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          this._texture.destroy(destroyTextureSource);
        }
        this._texture = null;
      }
    };
    /**
     * Default options used when creating a TilingSprite instance.
     * These values are used as fallbacks when specific options are not provided.
     * @example
     * ```ts
     * // Override default options globally
     * TilingSprite.defaultOptions.texture = Texture.from('defaultPattern.png');
     * TilingSprite.defaultOptions.tileScale = { x: 2, y: 2 };
     *
     * // Create sprite using default options
     * const sprite = new TilingSprite();
     * // Will use defaultPattern.png and scale 2x
     * ```
     * @type {TilingSpriteOptions}
     * @see {@link TilingSpriteOptions} For all available options
     * @see {@link TilingSprite.from} For creating sprites with custom options
     * @see {@link Texture.EMPTY} For the default empty texture
     */
    _TilingSprite.defaultOptions = {
      /** The texture to use for the sprite. */
      texture: Texture.EMPTY,
      /** The anchor point of the sprite */
      anchor: { x: 0, y: 0 },
      /** The offset of the image that is being tiled. */
      tilePosition: { x: 0, y: 0 },
      /** Scaling of the image that is being tiled. */
      tileScale: { x: 1, y: 1 },
      /** The rotation of the image that is being tiled. */
      tileRotation: 0,
      /**
       * Flags whether the tiling pattern should originate from the origin instead of the top-left corner in
       * local space.
       *
       * This will make the texture coordinates assigned to each vertex dependent on the value of the anchor. Without
       * this, the top-left corner always gets the (0, 0) texture coordinate.
       * @default false
       */
      applyAnchorToTexture: false
    };
    let TilingSprite = _TilingSprite;

    "use strict";
    var __defProp$s = Object.defineProperty;
    var __getOwnPropSymbols$u = Object.getOwnPropertySymbols;
    var __hasOwnProp$u = Object.prototype.hasOwnProperty;
    var __propIsEnum$u = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$s = (obj, key, value) => key in obj ? __defProp$s(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$s = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$u.call(b, prop))
          __defNormalProp$s(a, prop, b[prop]);
      if (__getOwnPropSymbols$u)
        for (var prop of __getOwnPropSymbols$u(b)) {
          if (__propIsEnum$u.call(b, prop))
            __defNormalProp$s(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$9 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$u.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$u)
        for (var prop of __getOwnPropSymbols$u(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$u.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class AbstractText extends ViewContainer {
      constructor(options, styleClass) {
        const _a = options, { text, resolution, style, anchor, width, height, roundPixels } = _a, rest = __objRest$9(_a, ["text", "resolution", "style", "anchor", "width", "height", "roundPixels"]);
        super(__spreadValues$s({}, rest));
        /** @internal */
        this.batched = true;
        /** @internal */
        this._resolution = null;
        /** @internal */
        this._autoResolution = true;
        /** @internal */
        this._didTextUpdate = true;
        this._styleClass = styleClass;
        this.text = text != null ? text : "";
        this.style = style;
        this.resolution = resolution != null ? resolution : null;
        this.allowChildren = false;
        this._anchor = new ObservablePoint(
          {
            _onUpdate: () => {
              this.onViewUpdate();
            }
          }
        );
        if (anchor)
          this.anchor = anchor;
        this.roundPixels = roundPixels != null ? roundPixels : false;
        if (width !== void 0)
          this.width = width;
        if (height !== void 0)
          this.height = height;
      }
      /**
       * The anchor point of the text that controls the origin point for positioning and rotation.
       * Can be a number (same value for x/y) or a PointData object.
       * - (0,0) is top-left
       * - (0.5,0.5) is center
       * - (1,1) is bottom-right
       * ```ts
       * // Set anchor to center
       * const text = new Text({
       *     text: 'Hello Pixi!',
       *     anchor: 0.5 // Same as { x: 0.5, y: 0.5 }
       * });
       * // Set anchor to top-left
       * const text2 = new Text({
       *     text: 'Hello Pixi!',
       *     anchor: { x: 0, y: 0 } // Top-left corner
       * });
       * // Set anchor to bottom-right
       * const text3 = new Text({
       *     text: 'Hello Pixi!',
       *     anchor: { x: 1, y: 1 } // Bottom-right corner
       * });
       * ```
       * @default { x: 0, y: 0 }
       */
      get anchor() {
        return this._anchor;
      }
      set anchor(value) {
        typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
      }
      /**
       * The text content to display. Use '\n' for line breaks.
       * Accepts strings, numbers, or objects with toString() method.
       * @example
       * ```ts
       * const text = new Text({
       *     text: 'Hello Pixi!',
       * });
       * const multilineText = new Text({
       *     text: 'Line 1\nLine 2\nLine 3',
       * });
       * const numberText = new Text({
       *     text: 12345, // Will be converted to '12345'
       * });
       * const objectText = new Text({
       *     text: { toString: () => 'Object Text' }, // Custom toString
       * });
       *
       * // Update text dynamically
       * text.text = 'Updated Text'; // Re-renders with new text
       * text.text = 67890; // Updates to '67890'
       * text.text = { toString: () => 'Dynamic Text' }; // Uses custom toString method
       * // Clear text
       * text.text = ''; // Clears the text
       * ```
       * @default ''
       */
      set text(value) {
        value = value.toString();
        if (this._text === value)
          return;
        this._text = value;
        this.onViewUpdate();
      }
      get text() {
        return this._text;
      }
      /**
       * The resolution/device pixel ratio for rendering.
       * Higher values result in sharper text at the cost of performance.
       * Set to null for auto-resolution based on device.
       * @example
       * ```ts
       * const text = new Text({
       *     text: 'Hello Pixi!',
       *     resolution: 2 // High DPI for sharper text
       * });
       * const autoResText = new Text({
       *     text: 'Auto Resolution',
       *     resolution: null // Use device's pixel ratio
       * });
       * ```
       * @default null
       */
      set resolution(value) {
        this._autoResolution = value === null;
        this._resolution = value;
        this.onViewUpdate();
      }
      get resolution() {
        return this._resolution;
      }
      get style() {
        return this._style;
      }
      /**
       * The style configuration for the text.
       * Can be a TextStyle instance or a configuration object.
       * Supports canvas text styles, HTML text styles, and bitmap text styles.
       * @example
       * ```ts
       * const text = new Text({
       *     text: 'Styled Text',
       *     style: {
       *         fontSize: 24,
       *         fill: 0xff1010, // Red color
       *         fontFamily: 'Arial',
       *         align: 'center', // Center alignment
       *         stroke: { color: '#4a1850', width: 5 }, // Purple stroke
       *         dropShadow: {
       *             color: '#000000', // Black shadow
       *             blur: 4, // Shadow blur
       *             distance: 6 // Shadow distance
       *         }
       *     }
       * });
       * const htmlText = new HTMLText({
       *     text: 'HTML Styled Text',
       *     style: {
       *         fontSize: '20px',
       *         fill: 'blue',
       *         fontFamily: 'Verdana',
       *     }
       * });
       * const bitmapText = new BitmapText({
       *     text: 'Bitmap Styled Text',
       *     style: {
       *         fontName: 'Arial',
       *         fontSize: 32,
       *     }
       * })
       *
       * // Update style dynamically
       * text.style = {
       *     fontSize: 30, // Change font size
       *     fill: 0x00ff00, // Change color to green
       *     align: 'right', // Change alignment to right
       *     stroke: { color: '#000000', width: 2 }, // Add black stroke
       * }
       */
      set style(style) {
        var _a;
        style || (style = {});
        (_a = this._style) == null ? void 0 : _a.off("update", this.onViewUpdate, this);
        if (style instanceof this._styleClass) {
          this._style = style;
        } else {
          this._style = new this._styleClass(style);
        }
        this._style.on("update", this.onViewUpdate, this);
        this.onViewUpdate();
      }
      /**
       * The width of the sprite, setting this will actually modify the scale to achieve the value set.
       * @example
       * ```ts
       * // Set width directly
       * texture.width = 200;
       * console.log(texture.scale.x); // Scale adjusted to match width
       *
       * // For better performance when setting both width and height
       * texture.setSize(300, 400); // Avoids recalculating bounds twice
       * ```
       */
      get width() {
        return Math.abs(this.scale.x) * this.bounds.width;
      }
      set width(value) {
        this._setWidth(value, this.bounds.width);
      }
      /**
       * The height of the sprite, setting this will actually modify the scale to achieve the value set.
       * @example
       * ```ts
       * // Set height directly
       * texture.height = 200;
       * console.log(texture.scale.y); // Scale adjusted to match height
       *
       * // For better performance when setting both width and height
       * texture.setSize(300, 400); // Avoids recalculating bounds twice
       * ```
       */
      get height() {
        return Math.abs(this.scale.y) * this.bounds.height;
      }
      set height(value) {
        this._setHeight(value, this.bounds.height);
      }
      /**
       * Retrieves the size of the Text as a [Size]{@link Size} object based on the texture dimensions and scale.
       * This is faster than getting width and height separately as it only calculates the bounds once.
       * @example
       * ```ts
       * // Basic size retrieval
       * const text = new Text({
       *     text: 'Hello Pixi!',
       *     style: { fontSize: 24 }
       * });
       * const size = text.getSize();
       * console.log(`Size: ${size.width}x${size.height}`);
       *
       * // Reuse existing size object
       * const reuseSize = { width: 0, height: 0 };
       * text.getSize(reuseSize);
       * ```
       * @param out - Optional object to store the size in, to avoid allocating a new object
       * @returns The size of the Sprite
       * @see {@link Text#width} For getting just the width
       * @see {@link Text#height} For getting just the height
       * @see {@link Text#setSize} For setting both width and height
       */
      getSize(out) {
        out || (out = {});
        out.width = Math.abs(this.scale.x) * this.bounds.width;
        out.height = Math.abs(this.scale.y) * this.bounds.height;
        return out;
      }
      /**
       * Sets the size of the Text to the specified width and height.
       * This is faster than setting width and height separately as it only recalculates bounds once.
       * @example
       * ```ts
       * // Basic size setting
       * const text = new Text({
       *    text: 'Hello Pixi!',
       *    style: { fontSize: 24 }
       * });
       * text.setSize(100, 200); // Width: 100, Height: 200
       *
       * // Set uniform size
       * text.setSize(100); // Sets both width and height to 100
       *
       * // Set size with object
       * text.setSize({
       *     width: 200,
       *     height: 300
       * });
       * ```
       * @param value - This can be either a number or a {@link Size} object
       * @param height - The height to set. Defaults to the value of `width` if not provided
       * @see {@link Text#width} For setting width only
       * @see {@link Text#height} For setting height only
       */
      setSize(value, height) {
        var _a;
        if (typeof value === "object") {
          height = (_a = value.height) != null ? _a : value.width;
          value = value.width;
        } else {
          height != null ? height : height = value;
        }
        value !== void 0 && this._setWidth(value, this.bounds.width);
        height !== void 0 && this._setHeight(height, this.bounds.height);
      }
      /**
       * Checks if the object contains the given point in local coordinates.
       * Uses the text's bounds for hit testing.
       * @example
       * ```ts
       * // Basic point check
       * const localPoint = { x: 50, y: 25 };
       * const contains = text.containsPoint(localPoint);
       * console.log('Point is inside:', contains);
       * ```
       * @param point - The point to check in local coordinates
       * @returns True if the point is within the text's bounds
       * @see {@link Container#toLocal} For converting global coordinates to local
       */
      containsPoint(point) {
        const width = this.bounds.width;
        const height = this.bounds.height;
        const x1 = -width * this.anchor.x;
        let y1 = 0;
        if (point.x >= x1 && point.x <= x1 + width) {
          y1 = -height * this.anchor.y;
          if (point.y >= y1 && point.y <= y1 + height)
            return true;
        }
        return false;
      }
      /** @internal */
      onViewUpdate() {
        if (!this.didViewUpdate)
          this._didTextUpdate = true;
        super.onViewUpdate();
      }
      /**
       * Destroys this text renderable and optionally its style texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * // Destroys the text and its style
       * text.destroy({ style: true, texture: true, textureSource: true });
       * text.destroy(true);
       * text.destroy() // Destroys the text, but not its style
       */
      destroy(options = false) {
        super.destroy(options);
        this.owner = null;
        this._bounds = null;
        this._anchor = null;
        if (typeof options === "boolean" ? options : options == null ? void 0 : options.style) {
          this._style.destroy(options);
        }
        this._style = null;
        this._text = null;
      }
      /**
       * Returns a unique key for this instance.
       * This key is used for caching.
       * @returns {string} Unique key for the instance
       */
      get styleKey() {
        return `${this._text}:${this._style.styleKey}:${this._resolution}`;
      }
    }
    function ensureTextOptions(args, name) {
      var _a;
      let options = (_a = args[0]) != null ? _a : {};
      if (typeof options === "string" || args[1]) {
        deprecation(v8_0_0, `use new ${name}({ text: "hi!", style }) instead`);
        options = {
          text: options,
          style: args[1]
        };
      }
      return options;
    }

    "use strict";
    class Text extends AbstractText {
      constructor(...args) {
        const options = ensureTextOptions(args, "Text");
        super(options, TextStyle);
        /** @internal */
        this.renderPipeId = "text";
        if (options.textureStyle) {
          this.textureStyle = options.textureStyle instanceof TextureStyle ? options.textureStyle : new TextureStyle(options.textureStyle);
        }
      }
      /** @private */
      updateBounds() {
        const bounds = this._bounds;
        const anchor = this._anchor;
        let width = 0;
        let height = 0;
        if (this._style.trim) {
          const { frame, canvasAndContext } = CanvasTextGenerator.getCanvasAndContext({
            text: this.text,
            style: this._style,
            resolution: 1
          });
          CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);
          width = frame.width;
          height = frame.height;
        } else {
          const canvasMeasurement = CanvasTextMetrics.measureText(
            this._text,
            this._style
          );
          width = canvasMeasurement.width;
          height = canvasMeasurement.height;
        }
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
    }

    "use strict";
    class PrepareQueue extends PrepareBase {
      /**
       * Resolve the given resource type and return an item for the queue
       * @param source
       * @param queue
       */
      resolveQueueItem(source, queue) {
        if (source instanceof Container) {
          this.resolveContainerQueueItem(source, queue);
        } else if (source instanceof TextureSource || source instanceof Texture) {
          queue.push(source.source);
        } else if (source instanceof GraphicsContext) {
          queue.push(source);
        }
        return null;
      }
      /**
       * Resolve the given container and return an item for the queue
       * @param container
       * @param queue
       */
      resolveContainerQueueItem(container, queue) {
        if (container instanceof Sprite || container instanceof TilingSprite || container instanceof Mesh) {
          queue.push(container.texture.source);
        } else if (container instanceof Text) {
          queue.push(container);
        } else if (container instanceof Graphics) {
          queue.push(container.context);
        } else if (container instanceof AnimatedSprite) {
          container.textures.forEach((textureOrFrame) => {
            if (textureOrFrame.source) {
              queue.push(textureOrFrame.source);
            } else {
              queue.push(textureOrFrame.texture.source);
            }
          });
        }
      }
      /**
       * Resolve the given graphics context and return an item for the queue
       * @param graphicsContext
       */
      resolveGraphicsContextQueueItem(graphicsContext) {
        this.renderer.graphicsContext.getGpuContext(graphicsContext);
        const { instructions } = graphicsContext;
        for (const instruction of instructions) {
          if (instruction.action === "texture") {
            const { image } = instruction.data;
            return image.source;
          } else if (instruction.action === "fill") {
            const { texture } = instruction.data.style;
            return texture.source;
          }
        }
        return null;
      }
    }

    "use strict";
    class BitmapText extends AbstractText {
      constructor(...args) {
        var _a, _b, _c;
        const options = ensureTextOptions(args, "BitmapText");
        (_a = options.style) != null ? _a : options.style = options.style || {};
        (_c = (_b = options.style).fill) != null ? _c : _b.fill = 16777215;
        super(options, TextStyle);
        /** @internal */
        this.renderPipeId = "bitmapText";
      }
      /**
       * @param now - The current time in milliseconds.
       * @internal
       */
      _onTouch(now) {
        var _a;
        this._gcLastUsed = now;
        for (const key in this._gpuData) {
          (_a = this._gpuData[key]) == null ? void 0 : _a._onTouch(now);
        }
      }
      /** @private */
      updateBounds() {
        const bounds = this._bounds;
        const anchor = this._anchor;
        const bitmapMeasurement = BitmapFontManager.measureText(this.text, this._style);
        const scale = bitmapMeasurement.scale;
        const offset = bitmapMeasurement.offsetY * scale;
        let width = bitmapMeasurement.width * scale;
        let height = bitmapMeasurement.height * scale;
        const stroke = this._style._stroke;
        if (stroke) {
          width += stroke.width;
          height += stroke.width;
        }
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * (height + offset);
        bounds.maxY = bounds.minY + height;
      }
      /**
       * The resolution / device pixel ratio for text rendering.
       * Unlike other text types, BitmapText resolution is managed by the BitmapFont.
       * Individual resolution changes are not supported.
       * @example
       * ```ts
       * // ❌ Incorrect: Setting resolution directly (will trigger warning)
       * const text = new BitmapText({
       *     text: 'Hello',
       *     resolution: 2 // This will be ignored
       * });
       *
       * // ✅ Correct: Set resolution when installing the font
       * BitmapFont.install({
       *     name: 'MyFont',
       *     style: {
       *         fontFamily: 'Arial',
       *     },
       *     resolution: 2 // Resolution is set here
       * });
       *
       * const text = new BitmapText({
       *     text: 'Hello',
       *     style: {
       *         fontFamily: 'MyFont' // Uses font's resolution
       *     }
       * });
       * ```
       * @default 1
       * @see {@link BitmapFont.install} For setting font resolution
       * @throws {Warning} When attempting to change resolution directly
       * @readonly
       */
      set resolution(value) {
        if (value !== null) {
          warn(
            // eslint-disable-next-line max-len
            "[BitmapText] dynamically updating the resolution is not supported. Resolution should be managed by the BitmapFont."
          );
        }
      }
      get resolution() {
        return this._resolution;
      }
    }

    "use strict";
    function textStyleToCSS(style) {
      const stroke = style._stroke;
      const fill = style._fill;
      const cssStyleString = [
        `color: ${Color.shared.setValue(fill.color).toHex()}`,
        `font-size: ${style.fontSize}px`,
        `font-family: ${style.fontFamily}`,
        `font-weight: ${style.fontWeight}`,
        `font-style: ${style.fontStyle}`,
        `font-variant: ${style.fontVariant}`,
        `letter-spacing: ${style.letterSpacing}px`,
        `text-align: ${style.align}`,
        `padding: ${style.padding}px`,
        `white-space: ${style.whiteSpace === "pre" && style.wordWrap ? "pre-wrap" : style.whiteSpace}`,
        ...style.lineHeight ? [`line-height: ${style.lineHeight}px`] : [],
        ...style.wordWrap ? [
          `word-wrap: ${style.breakWords ? "break-all" : "break-word"}`,
          `max-width: ${style.wordWrapWidth}px`
        ] : [],
        ...stroke ? [strokeToCSS(stroke)] : [],
        ...style.dropShadow ? [dropShadowToCSS(style.dropShadow)] : [],
        ...style.cssOverrides
      ].join(";");
      const cssStyles = [`div { ${cssStyleString} }`];
      tagStyleToCSS(style.tagStyles, cssStyles);
      return cssStyles.join(" ");
    }
    function dropShadowToCSS(dropShadowStyle) {
      const color = Color.shared.setValue(dropShadowStyle.color).setAlpha(dropShadowStyle.alpha).toHexa();
      const x = Math.round(Math.cos(dropShadowStyle.angle) * dropShadowStyle.distance);
      const y = Math.round(Math.sin(dropShadowStyle.angle) * dropShadowStyle.distance);
      const position = `${x}px ${y}px`;
      if (dropShadowStyle.blur > 0) {
        return `text-shadow: ${position} ${dropShadowStyle.blur}px ${color}`;
      }
      return `text-shadow: ${position} ${color}`;
    }
    function strokeToCSS(stroke) {
      return [
        `-webkit-text-stroke-width: ${stroke.width}px`,
        `-webkit-text-stroke-color: ${Color.shared.setValue(stroke.color).toHex()}`,
        `text-stroke-width: ${stroke.width}px`,
        `text-stroke-color: ${Color.shared.setValue(stroke.color).toHex()}`,
        "paint-order: stroke"
      ].join(";");
    }
    const templates = {
      fontSize: `font-size: {{VALUE}}px`,
      fontFamily: `font-family: {{VALUE}}`,
      fontWeight: `font-weight: {{VALUE}}`,
      fontStyle: `font-style: {{VALUE}}`,
      fontVariant: `font-variant: {{VALUE}}`,
      letterSpacing: `letter-spacing: {{VALUE}}px`,
      align: `text-align: {{VALUE}}`,
      padding: `padding: {{VALUE}}px`,
      whiteSpace: `white-space: {{VALUE}}`,
      lineHeight: `line-height: {{VALUE}}px`,
      wordWrapWidth: `max-width: {{VALUE}}px`
    };
    const transform = {
      fill: (value) => `color: ${Color.shared.setValue(value).toHex()}`,
      breakWords: (value) => `word-wrap: ${value ? "break-all" : "break-word"}`,
      stroke: strokeToCSS,
      dropShadow: dropShadowToCSS
    };
    function tagStyleToCSS(tagStyles, out) {
      for (const i in tagStyles) {
        const tagStyle = tagStyles[i];
        const cssTagStyle = [];
        for (const j in tagStyle) {
          if (transform[j]) {
            cssTagStyle.push(transform[j](tagStyle[j]));
          } else if (templates[j]) {
            cssTagStyle.push(templates[j].replace("{{VALUE}}", tagStyle[j]));
          }
        }
        out.push(`${i} { ${cssTagStyle.join(";")} }`);
      }
    }

    "use strict";
    var __defProp$r = Object.defineProperty;
    var __getOwnPropSymbols$t = Object.getOwnPropertySymbols;
    var __hasOwnProp$t = Object.prototype.hasOwnProperty;
    var __propIsEnum$t = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$r = (obj, key, value) => key in obj ? __defProp$r(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$r = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$t.call(b, prop))
          __defNormalProp$r(a, prop, b[prop]);
      if (__getOwnPropSymbols$t)
        for (var prop of __getOwnPropSymbols$t(b)) {
          if (__propIsEnum$t.call(b, prop))
            __defNormalProp$r(a, prop, b[prop]);
        }
      return a;
    };
    class HTMLTextStyle extends TextStyle {
      constructor(options = {}) {
        var _a, _b;
        super(options);
        this._cssOverrides = [];
        this.cssOverrides = (_a = options.cssOverrides) != null ? _a : [];
        this.tagStyles = (_b = options.tagStyles) != null ? _b : {};
      }
      /**
       * List of CSS style overrides to apply to the HTML text.
       * These styles are added after the built-in styles and can override any default styling.
       * @advanced
       */
      set cssOverrides(value) {
        this._cssOverrides = value instanceof Array ? value : [value];
        this.update();
      }
      /** @advanced */
      get cssOverrides() {
        return this._cssOverrides;
      }
      /**
       * Updates the text style and triggers a refresh of the CSS style cache.
       * This method is called automatically when style properties are changed.
       * @example
       * ```ts
       * // Update after multiple changes
       * const text = new HTMLText({
       *     text: 'Hello World',
       *     style
       * });
       *
       * style.fontSize = 32;
       * style.fill = '#00ff00';
       * style.fontFamily = 'Arial';
       * style.update(); // Apply all changes at once
       * ```
       * @advanced
       * @see {@link HTMLTextStyle#cssStyle} For accessing the generated CSS
       * @see {@link HTMLTextStyle#cssOverrides} For managing CSS overrides
       */
      update() {
        this._cssStyle = null;
        super.update();
      }
      /**
       * Creates a new HTMLTextStyle object with the same values as this one.
       * This creates a deep copy of all style properties, including dropShadow and tag styles.
       * @example
       * ```ts
       * // Create original style
       * const originalStyle = new HTMLTextStyle({
       *     fontSize: 24,
       *     fill: '#ff0000',
       *     tagStyles: {
       *         header: { fontSize: 32, fill: '#00ff00' }
       *     }
       * });
       *
       * // Clone the style
       * const clonedStyle = originalStyle.clone();
       *
       * // Modify cloned style independently
       * clonedStyle.fontSize = 36;
       * clonedStyle.fill = '#0000ff';
       *
       * // Original style remains unchanged
       * console.log(originalStyle.fontSize); // Still 24
       * console.log(originalStyle.fill); // Still '#ff0000'
       * ```
       *
       * Properties that are cloned:
       * - Basic text properties (fontSize, fontFamily, etc.)
       * - Fill and stroke styles
       * - Drop shadow configuration
       * - CSS overrides
       * - Tag styles (deep copied)
       * - Word wrap settings
       * - Alignment and spacing
       * @returns {HTMLTextStyle} A new HTMLTextStyle instance with the same properties
       * @see {@link HTMLTextStyle} For available style properties
       * @see {@link HTMLTextStyle#cssOverrides} For CSS override handling
       * @see {@link HTMLTextStyle#tagStyles} For tag style configuration
       * @standard
       */
      clone() {
        return new HTMLTextStyle({
          align: this.align,
          breakWords: this.breakWords,
          dropShadow: this.dropShadow ? __spreadValues$r({}, this.dropShadow) : null,
          fill: this._fill,
          fontFamily: this.fontFamily,
          fontSize: this.fontSize,
          fontStyle: this.fontStyle,
          fontVariant: this.fontVariant,
          fontWeight: this.fontWeight,
          letterSpacing: this.letterSpacing,
          lineHeight: this.lineHeight,
          padding: this.padding,
          stroke: this._stroke,
          whiteSpace: this.whiteSpace,
          wordWrap: this.wordWrap,
          wordWrapWidth: this.wordWrapWidth,
          cssOverrides: this.cssOverrides,
          tagStyles: __spreadValues$r({}, this.tagStyles)
        });
      }
      /**
       * The CSS style string that will be applied to the HTML text.
       * @advanced
       */
      get cssStyle() {
        if (!this._cssStyle) {
          this._cssStyle = textStyleToCSS(this);
        }
        return this._cssStyle;
      }
      /**
       * Add a style override, this can be any CSS property
       * it will override any built-in style. This is the
       * property and the value as a string (e.g., `color: red`).
       * This will override any other internal style.
       * @param {string} value - CSS style(s) to add.
       * @example
       * style.addOverride('background-color: red');
       * @advanced
       */
      addOverride(...value) {
        const toAdd = value.filter((v) => !this.cssOverrides.includes(v));
        if (toAdd.length > 0) {
          this.cssOverrides.push(...toAdd);
          this.update();
        }
      }
      /**
       * Remove any overrides that match the value.
       * @param {string} value - CSS style to remove.
       * @example
       * style.removeOverride('background-color: red');
       * @advanced
       */
      removeOverride(...value) {
        const toRemove = value.filter((v) => this.cssOverrides.includes(v));
        if (toRemove.length > 0) {
          this.cssOverrides = this.cssOverrides.filter((v) => !toRemove.includes(v));
          this.update();
        }
      }
      /**
       * Sets the fill style for the text. HTML text only supports color fills (string or number values).
       * Texture fills are not supported and will trigger a warning in debug mode.
       * @example
       * ```ts
       * // Using hex colors
       * const text = new HTMLText({
       *     text: 'Colored Text',
       *     style: {
       *         fill: 0xff0000 // Red color
       *     }
       * });
       *
       * // Using CSS color strings
       * text.style.fill = '#00ff00';     // Hex string (Green)
       * text.style.fill = 'blue';        // Named color
       * text.style.fill = 'rgb(255,0,0)' // RGB
       * text.style.fill = '#f0f';        // Short hex
       *
       * // Invalid usage (will trigger warning in debug)
       * text.style.fill = {
       *     type: 'pattern',
       *     texture: Texture.from('pattern.png')
       * }; // Not supported, falls back to default
       * ```
       * @param value - The fill color to use. Must be a string or number.
       * @throws {Warning} In debug mode when attempting to use unsupported fill types
       * @see {@link TextStyle#fill} For full fill options in canvas text
       * @standard
       */
      set fill(value) {
        if (typeof value !== "string" && typeof value !== "number") {
          warn("[HTMLTextStyle] only color fill is not supported by HTMLText");
        }
        super.fill = value;
      }
      /**
       * Sets the stroke style for the text. HTML text only supports color strokes (string or number values).
       * Texture strokes are not supported and will trigger a warning in debug mode.
       * @example
       * ```ts
       * // Using hex colors
       * const text = new HTMLText({
       *     text: 'Outlined Text',
       *     style: {
       *         stroke: 0xff0000 // Red outline
       *     }
       * });
       *
       * // Using CSS color strings
       * text.style.stroke = '#00ff00';     // Hex string (Green)
       * text.style.stroke = 'blue';        // Named color
       * text.style.stroke = 'rgb(255,0,0)' // RGB
       * text.style.stroke = '#f0f';        // Short hex
       *
       * // Using stroke width
       * text.style = {
       *     stroke: {
       *         color: '#ff0000',
       *         width: 2
       *     }
       * };
       *
       * // Remove stroke
       * text.style.stroke = null;
       *
       * // Invalid usage (will trigger warning in debug)
       * text.style.stroke = {
       *     type: 'pattern',
       *     texture: Texture.from('pattern.png')
       * }; // Not supported, falls back to default
       * ```
       * @param value - The stroke style to use. Must be a string, number, or stroke configuration object
       * @throws {Warning} In debug mode when attempting to use unsupported stroke types
       * @see {@link TextStyle#stroke} For full stroke options in canvas text
       * @standard
       */
      set stroke(value) {
        if (value && typeof value !== "string" && typeof value !== "number") {
          warn("[HTMLTextStyle] only color stroke is not supported by HTMLText");
        }
        super.stroke = value;
      }
    }

    "use strict";
    class HTMLText extends AbstractText {
      constructor(...args) {
        const options = ensureTextOptions(args, "HtmlText");
        super(options, HTMLTextStyle);
        /** @internal */
        this.renderPipeId = "htmlText";
        if (options.textureStyle) {
          this.textureStyle = options.textureStyle instanceof TextureStyle ? options.textureStyle : new TextureStyle(options.textureStyle);
        }
      }
      /** @private */
      updateBounds() {
        const bounds = this._bounds;
        const anchor = this._anchor;
        const htmlMeasurement = measureHtmlText(this.text, this._style);
        const { width, height } = htmlMeasurement;
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
      get text() {
        return this._text;
      }
      /**
       * The text content to display. Use '\n' for line breaks.
       * Accepts strings, numbers, or objects with toString() method.
       * @example
       * ```ts
       * const text = new HTMLText({
       *     text: 'Hello Pixi!',
       * });
       * const multilineText = new HTMLText({
       *     text: 'Line 1\nLine 2\nLine 3',
       * });
       * const numberText = new HTMLText({
       *     text: 12345, // Will be converted to '12345'
       * });
       * const objectText = new HTMLText({
       *     text: { toString: () => 'Object Text' }, // Custom toString
       * });
       *
       * // Update text dynamically
       * text.text = 'Updated Text'; // Re-renders with new text
       * text.text = 67890; // Updates to '67890'
       * text.text = { toString: () => 'Dynamic Text' }; // Uses custom toString method
       * // Clear text
       * text.text = ''; // Clears the text
       * ```
       * @default ''
       */
      set text(text) {
        const sanitisedText = this._sanitiseText(text.toString());
        super.text = sanitisedText;
      }
      /**
       * Sanitise text - replace `<br>` with `<br/>`, `&nbsp;` with `&#160;`
       * @param text
       * @see https://www.sitepoint.com/community/t/xhtml-1-0-transitional-xml-parsing-error-entity-nbsp-not-defined/3392/3
       */
      _sanitiseText(text) {
        return this._removeInvalidHtmlTags(text.replace(/<br>/gi, "<br/>").replace(/<hr>/gi, "<hr/>").replace(/&nbsp;/gi, "&#160;"));
      }
      _removeInvalidHtmlTags(input) {
        const brokenTagPattern = /<[^>]*?(?=<|$)/g;
        return input.replace(brokenTagPattern, "");
      }
    }

    "use strict";
    class PrepareUpload extends PrepareQueue {
      /**
       * Upload the given queue item
       * @param item
       */
      uploadQueueItem(item) {
        if (item instanceof TextureSource) {
          this.uploadTextureSource(item);
        } else if (item instanceof Text) {
          this.uploadText(item);
        } else if (item instanceof HTMLText) {
          this.uploadHTMLText(item);
        } else if (item instanceof BitmapText) {
          this.uploadBitmapText(item);
        } else if (item instanceof GraphicsContext) {
          this.uploadGraphicsContext(item);
        }
      }
      uploadTextureSource(textureSource) {
        this.renderer.texture.initSource(textureSource);
      }
      uploadText(_text) {
        this.renderer.renderPipes.text.initGpuText(_text);
      }
      uploadBitmapText(_text) {
        this.renderer.renderPipes.bitmapText.initGpuText(_text);
      }
      uploadHTMLText(_text) {
        this.renderer.renderPipes.htmlText.initGpuText(_text);
      }
      /**
       * Resolve the given graphics context and return an item for the queue
       * @param graphicsContext
       */
      uploadGraphicsContext(graphicsContext) {
        this.renderer.graphicsContext.getGpuContext(graphicsContext);
        const { instructions } = graphicsContext;
        for (const instruction of instructions) {
          if (instruction.action === "texture") {
            const { image } = instruction.data;
            this.uploadTextureSource(image.source);
          } else if (instruction.action === "fill") {
            const { texture } = instruction.data.style;
            this.uploadTextureSource(texture.source);
          }
        }
        return null;
      }
    }

    "use strict";
    class PrepareSystem extends PrepareUpload {
      /** Destroys the plugin, don't use after this. */
      destroy() {
        super.destroy();
        clearTimeout(this.timeout);
        this.renderer = null;
        this.queue = null;
        this.resolves = null;
      }
    }
    /** @ignore */
    PrepareSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "prepare"
    };

    "use strict";

    "use strict";
    class GlBatchAdaptor {
      constructor() {
        this._tempState = State.for2d();
        /**
         * We only want to sync the a batched shaders uniforms once on first use
         * this is a hash of shader uids to a boolean value.  When the shader is first bound
         * we set the value to true.  When the shader is bound again we check the value and
         * if it is true we know that the uniforms have already been synced and we skip it.
         */
        this._didUploadHash = {};
      }
      init(batcherPipe) {
        batcherPipe.renderer.runners.contextChange.add(this);
      }
      contextChange() {
        this._didUploadHash = {};
      }
      start(batchPipe, geometry, shader) {
        const renderer = batchPipe.renderer;
        const didUpload = this._didUploadHash[shader.uid];
        renderer.shader.bind(shader, didUpload);
        if (!didUpload) {
          this._didUploadHash[shader.uid] = true;
        }
        renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);
        renderer.geometry.bind(geometry, shader.glProgram);
      }
      execute(batchPipe, batch) {
        const renderer = batchPipe.renderer;
        this._tempState.blendMode = batch.blendMode;
        renderer.state.set(this._tempState);
        const textures = batch.textures.textures;
        for (let i = 0; i < batch.textures.count; i++) {
          renderer.texture.bind(textures[i], i);
        }
        renderer.geometry.draw(batch.topology, batch.size, batch.start);
      }
    }
    /** @ignore */
    GlBatchAdaptor.extension = {
      type: [
        ExtensionType.WebGLPipesAdaptor
      ],
      name: "batch"
    };

    "use strict";
    function generateGPULayout(maxTextures) {
      const gpuLayout = [];
      let bindIndex = 0;
      for (let i = 0; i < maxTextures; i++) {
        gpuLayout[bindIndex] = {
          texture: {
            sampleType: "float",
            viewDimension: "2d",
            multisampled: false
          },
          binding: bindIndex,
          visibility: GPUShaderStage.FRAGMENT
        };
        bindIndex++;
        gpuLayout[bindIndex] = {
          sampler: {
            type: "filtering"
          },
          binding: bindIndex,
          visibility: GPUShaderStage.FRAGMENT
        };
        bindIndex++;
      }
      return gpuLayout;
    }

    "use strict";
    function generateLayout(maxTextures) {
      const layout = {};
      let bindIndex = 0;
      for (let i = 0; i < maxTextures; i++) {
        layout[`textureSource${i + 1}`] = bindIndex++;
        layout[`textureSampler${i + 1}`] = bindIndex++;
      }
      return layout;
    }

    "use strict";
    const tempState = State.for2d();
    class GpuBatchAdaptor {
      start(batchPipe, geometry, shader) {
        const renderer = batchPipe.renderer;
        const encoder = renderer.encoder;
        const program = shader.gpuProgram;
        this._shader = shader;
        this._geometry = geometry;
        encoder.setGeometry(geometry, program);
        tempState.blendMode = "normal";
        renderer.pipeline.getPipeline(
          geometry,
          program,
          tempState
        );
        const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
        encoder.resetBindGroup(1);
        encoder.setBindGroup(0, globalUniformsBindGroup, program);
      }
      execute(batchPipe, batch) {
        const program = this._shader.gpuProgram;
        const renderer = batchPipe.renderer;
        const encoder = renderer.encoder;
        if (!batch.bindGroup) {
          const textureBatch = batch.textures;
          batch.bindGroup = getTextureBatchBindGroup(
            textureBatch.textures,
            textureBatch.count,
            renderer.limits.maxBatchableTextures
          );
        }
        tempState.blendMode = batch.blendMode;
        const gpuBindGroup = renderer.bindGroup.getBindGroup(
          batch.bindGroup,
          program,
          1
        );
        const pipeline = renderer.pipeline.getPipeline(
          this._geometry,
          program,
          tempState,
          batch.topology
        );
        batch.bindGroup._touch(renderer.gc.now, renderer.tick);
        encoder.setPipeline(pipeline);
        encoder.renderPassEncoder.setBindGroup(1, gpuBindGroup);
        encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
      }
    }
    /** @ignore */
    GpuBatchAdaptor.extension = {
      type: [
        ExtensionType.WebGPUPipesAdaptor
      ],
      name: "batch"
    };

    "use strict";
    const _BatcherPipe = class _BatcherPipe {
      constructor(renderer, adaptor) {
        this.state = State.for2d();
        this._batchersByInstructionSet = /* @__PURE__ */ Object.create(null);
        /** A record of all active batchers, keyed by their names */
        this._activeBatches = /* @__PURE__ */ Object.create(null);
        var _a, _b;
        this.renderer = renderer;
        this._adaptor = adaptor;
        (_b = (_a = this._adaptor).init) == null ? void 0 : _b.call(_a, this);
      }
      static getBatcher(name) {
        return new this._availableBatchers[name]();
      }
      buildStart(instructionSet) {
        let batchers = this._batchersByInstructionSet[instructionSet.uid];
        if (!batchers) {
          batchers = this._batchersByInstructionSet[instructionSet.uid] = /* @__PURE__ */ Object.create(null);
          batchers.default || (batchers.default = new DefaultBatcher({
            maxTextures: this.renderer.limits.maxBatchableTextures
          }));
        }
        this._activeBatches = batchers;
        this._activeBatch = this._activeBatches.default;
        for (const i in this._activeBatches) {
          this._activeBatches[i].begin();
        }
      }
      addToBatch(batchableObject, instructionSet) {
        if (this._activeBatch.name !== batchableObject.batcherName) {
          this._activeBatch.break(instructionSet);
          let batch = this._activeBatches[batchableObject.batcherName];
          if (!batch) {
            batch = this._activeBatches[batchableObject.batcherName] = _BatcherPipe.getBatcher(batchableObject.batcherName);
            batch.begin();
          }
          this._activeBatch = batch;
        }
        this._activeBatch.add(batchableObject);
      }
      break(instructionSet) {
        this._activeBatch.break(instructionSet);
      }
      buildEnd(instructionSet) {
        this._activeBatch.break(instructionSet);
        const batches = this._activeBatches;
        for (const i in batches) {
          const batch = batches[i];
          const geometry = batch.geometry;
          geometry.indexBuffer.setDataWithSize(batch.indexBuffer, batch.indexSize, true);
          geometry.buffers[0].setDataWithSize(batch.attributeBuffer.float32View, batch.attributeSize, false);
        }
      }
      upload(instructionSet) {
        const batchers = this._batchersByInstructionSet[instructionSet.uid];
        for (const i in batchers) {
          const batcher = batchers[i];
          const geometry = batcher.geometry;
          if (batcher.dirty) {
            batcher.dirty = false;
            geometry.buffers[0].update(batcher.attributeSize * 4);
          }
        }
      }
      execute(batch) {
        if (batch.action === "startBatch") {
          const batcher = batch.batcher;
          const geometry = batcher.geometry;
          const shader = batcher.shader;
          this._adaptor.start(this, geometry, shader);
        }
        this._adaptor.execute(this, batch);
      }
      destroy() {
        this.state = null;
        this.renderer = null;
        this._adaptor = null;
        for (const i in this._activeBatches) {
          this._activeBatches[i].destroy();
        }
        this._activeBatches = null;
      }
    };
    /** @ignore */
    _BatcherPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "batch"
    };
    _BatcherPipe._availableBatchers = /* @__PURE__ */ Object.create(null);
    let BatcherPipe = _BatcherPipe;
    extensions.handleByMap(ExtensionType.Batcher, BatcherPipe._availableBatchers);
    extensions.add(DefaultBatcher);

    "use strict";

    "use strict";
    function formatShader(shader) {
      const spl = shader.split(/([\n{}])/g).map((a) => a.trim()).filter((a) => a.length);
      let indent = "";
      const formatted = spl.map((a) => {
        let indentedLine = indent + a;
        if (a === "{") {
          indent += "    ";
        } else if (a === "}") {
          indent = indent.substr(0, indent.length - 4);
          indentedLine = indent + a;
        }
        return indentedLine;
      }).join("\n");
      return formatted;
    }

    "use strict";
    const textureBit = {
      name: "texture-bit",
      vertex: {
        header: (
          /* wgsl */
          `

        struct TextureUniforms {
            uTextureMatrix:mat3x3<f32>,
        }

        @group(2) @binding(2) var<uniform> textureUniforms : TextureUniforms;
        `
        ),
        main: (
          /* wgsl */
          `
            uv = (textureUniforms.uTextureMatrix * vec3(uv, 1.0)).xy;
        `
        )
      },
      fragment: {
        header: (
          /* wgsl */
          `
            @group(2) @binding(0) var uTexture: texture_2d<f32>;
            @group(2) @binding(1) var uSampler: sampler;


        `
        ),
        main: (
          /* wgsl */
          `
            outColor = textureSample(uTexture, uSampler, vUV);
        `
        )
      }
    };
    const textureBitGl = {
      name: "texture-bit",
      vertex: {
        header: (
          /* glsl */
          `
            uniform mat3 uTextureMatrix;
        `
        ),
        main: (
          /* glsl */
          `
            uv = (uTextureMatrix * vec3(uv, 1.0)).xy;
        `
        )
      },
      fragment: {
        header: (
          /* glsl */
          `
        uniform sampler2D uTexture;


        `
        ),
        main: (
          /* glsl */
          `
            outColor = texture(uTexture, vUV);
        `
        )
      }
    };

    "use strict";
    const tempBounds$1 = new Bounds();
    class AlphaMaskEffect extends FilterEffect {
      constructor() {
        super();
        this.filters = [new MaskFilter({
          sprite: new Sprite(Texture.EMPTY),
          inverse: false,
          resolution: "inherit",
          antialias: "inherit"
        })];
      }
      get sprite() {
        return this.filters[0].sprite;
      }
      set sprite(value) {
        this.filters[0].sprite = value;
      }
      get inverse() {
        return this.filters[0].inverse;
      }
      set inverse(value) {
        this.filters[0].inverse = value;
      }
    }
    class AlphaMaskPipe {
      constructor(renderer) {
        this._activeMaskStage = [];
        this._renderer = renderer;
      }
      push(mask, maskedContainer, instructionSet) {
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "alphaMask",
          action: "pushMaskBegin",
          mask,
          inverse: maskedContainer._maskOptions.inverse,
          canBundle: false,
          maskedContainer
        });
        mask.inverse = maskedContainer._maskOptions.inverse;
        if (mask.renderMaskToTexture) {
          const maskContainer = mask.mask;
          maskContainer.includeInBuild = true;
          maskContainer.collectRenderables(
            instructionSet,
            renderer,
            null
          );
          maskContainer.includeInBuild = false;
        }
        renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "alphaMask",
          action: "pushMaskEnd",
          mask,
          maskedContainer,
          inverse: maskedContainer._maskOptions.inverse,
          canBundle: false
        });
      }
      pop(mask, _maskedContainer, instructionSet) {
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "alphaMask",
          action: "popMaskEnd",
          mask,
          inverse: _maskedContainer._maskOptions.inverse,
          canBundle: false
        });
      }
      execute(instruction) {
        const renderer = this._renderer;
        const renderMask = instruction.mask.renderMaskToTexture;
        if (instruction.action === "pushMaskBegin") {
          const filterEffect = BigPool.get(AlphaMaskEffect);
          filterEffect.inverse = instruction.inverse;
          if (renderMask) {
            instruction.mask.mask.measurable = true;
            const bounds = getGlobalBounds(instruction.mask.mask, true, tempBounds$1);
            instruction.mask.mask.measurable = false;
            bounds.ceil();
            const colorTextureSource = renderer.renderTarget.renderTarget.colorTexture.source;
            const filterTexture = TexturePool.getOptimalTexture(
              bounds.width,
              bounds.height,
              colorTextureSource._resolution,
              colorTextureSource.antialias
            );
            renderer.renderTarget.push(filterTexture, true);
            renderer.globalUniforms.push({
              offset: bounds,
              worldColor: 4294967295
            });
            const sprite = filterEffect.sprite;
            sprite.texture = filterTexture;
            sprite.worldTransform.tx = bounds.minX;
            sprite.worldTransform.ty = bounds.minY;
            this._activeMaskStage.push({
              filterEffect,
              maskedContainer: instruction.maskedContainer,
              filterTexture
            });
          } else {
            filterEffect.sprite = instruction.mask.mask;
            this._activeMaskStage.push({
              filterEffect,
              maskedContainer: instruction.maskedContainer
            });
          }
        } else if (instruction.action === "pushMaskEnd") {
          const maskData = this._activeMaskStage[this._activeMaskStage.length - 1];
          if (renderMask) {
            if (renderer.type === RendererType.WEBGL) {
              renderer.renderTarget.finishRenderPass();
            }
            renderer.renderTarget.pop();
            renderer.globalUniforms.pop();
          }
          renderer.filter.push({
            renderPipeId: "filter",
            action: "pushFilter",
            container: maskData.maskedContainer,
            filterEffect: maskData.filterEffect,
            canBundle: false
          });
        } else if (instruction.action === "popMaskEnd") {
          renderer.filter.pop();
          const maskData = this._activeMaskStage.pop();
          if (renderMask) {
            TexturePool.returnTexture(maskData.filterTexture);
          }
          BigPool.return(maskData.filterEffect);
        }
      }
      destroy() {
        this._renderer = null;
        this._activeMaskStage = null;
      }
    }
    /** @ignore */
    AlphaMaskPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "alphaMask"
    };

    "use strict";
    class ColorMaskPipe {
      constructor(renderer) {
        this._colorStack = [];
        this._colorStackIndex = 0;
        this._currentColor = 0;
        this._renderer = renderer;
      }
      buildStart() {
        this._colorStack[0] = 15;
        this._colorStackIndex = 1;
        this._currentColor = 15;
      }
      push(mask, _container, instructionSet) {
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        const colorStack = this._colorStack;
        colorStack[this._colorStackIndex] = colorStack[this._colorStackIndex - 1] & mask.mask;
        const currentColor = this._colorStack[this._colorStackIndex];
        if (currentColor !== this._currentColor) {
          this._currentColor = currentColor;
          instructionSet.add({
            renderPipeId: "colorMask",
            colorMask: currentColor,
            canBundle: false
          });
        }
        this._colorStackIndex++;
      }
      pop(_mask, _container, instructionSet) {
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        const colorStack = this._colorStack;
        this._colorStackIndex--;
        const currentColor = colorStack[this._colorStackIndex - 1];
        if (currentColor !== this._currentColor) {
          this._currentColor = currentColor;
          instructionSet.add({
            renderPipeId: "colorMask",
            colorMask: currentColor,
            canBundle: false
          });
        }
      }
      execute(instruction) {
        const renderer = this._renderer;
        renderer.colorMask.setMask(instruction.colorMask);
      }
      destroy() {
        this._renderer = null;
        this._colorStack = null;
      }
    }
    /** @ignore */
    ColorMaskPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "colorMask"
    };

    "use strict";
    class ScissorMask {
      constructor(mask) {
        this.priority = 0;
        this.pipe = "scissorMask";
        this.mask = mask;
        this.mask.renderable = false;
        this.mask.measurable = false;
      }
      addBounds(bounds, skipUpdateTransform) {
        addMaskBounds(this.mask, bounds, skipUpdateTransform);
      }
      addLocalBounds(bounds, localRoot) {
        addMaskLocalBounds(this.mask, bounds, localRoot);
      }
      containsPoint(point, hitTestFn) {
        const mask = this.mask;
        return hitTestFn(mask, point);
      }
      reset() {
        if (this.mask === null)
          return;
        this.mask.measurable = true;
        this.mask = null;
      }
      destroy() {
        this.reset();
      }
    }

    "use strict";
    class StencilMaskPipe {
      constructor(renderer) {
        // used when building and also when executing..
        this._maskStackHash = {};
        this._maskHash = /* @__PURE__ */ new WeakMap();
        this._renderer = renderer;
      }
      push(mask, _container, instructionSet) {
        var _a, _b;
        const effect = mask;
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
        instructionSet.add({
          renderPipeId: "stencilMask",
          action: "pushMaskBegin",
          mask,
          inverse: _container._maskOptions.inverse,
          canBundle: false
        });
        const maskContainer = effect.mask;
        maskContainer.includeInBuild = true;
        if (!this._maskHash.has(effect)) {
          this._maskHash.set(effect, {
            instructionsStart: 0,
            instructionsLength: 0
          });
        }
        const maskData = this._maskHash.get(effect);
        maskData.instructionsStart = instructionSet.instructionSize;
        maskContainer.collectRenderables(
          instructionSet,
          renderer,
          null
        );
        maskContainer.includeInBuild = false;
        renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "stencilMask",
          action: "pushMaskEnd",
          mask,
          inverse: _container._maskOptions.inverse,
          canBundle: false
        });
        const instructionsLength = instructionSet.instructionSize - maskData.instructionsStart - 1;
        maskData.instructionsLength = instructionsLength;
        const renderTargetUid = renderer.renderTarget.renderTarget.uid;
        (_b = (_a = this._maskStackHash)[renderTargetUid]) != null ? _b : _a[renderTargetUid] = 0;
      }
      pop(mask, _container, instructionSet) {
        const effect = mask;
        const renderer = this._renderer;
        renderer.renderPipes.batch.break(instructionSet);
        renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
        instructionSet.add({
          renderPipeId: "stencilMask",
          action: "popMaskBegin",
          inverse: _container._maskOptions.inverse,
          canBundle: false
        });
        const maskData = this._maskHash.get(mask);
        for (let i = 0; i < maskData.instructionsLength; i++) {
          instructionSet.instructions[instructionSet.instructionSize++] = instructionSet.instructions[maskData.instructionsStart++];
        }
        instructionSet.add({
          renderPipeId: "stencilMask",
          action: "popMaskEnd",
          canBundle: false
        });
      }
      execute(instruction) {
        var _a, _b;
        const renderer = this._renderer;
        const renderTargetUid = renderer.renderTarget.renderTarget.uid;
        let maskStackIndex = (_b = (_a = this._maskStackHash)[renderTargetUid]) != null ? _b : _a[renderTargetUid] = 0;
        if (instruction.action === "pushMaskBegin") {
          renderer.renderTarget.ensureDepthStencil();
          renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);
          maskStackIndex++;
          renderer.colorMask.setMask(0);
        } else if (instruction.action === "pushMaskEnd") {
          if (instruction.inverse) {
            renderer.stencil.setStencilMode(STENCIL_MODES.INVERSE_MASK_ACTIVE, maskStackIndex);
          } else {
            renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
          }
          renderer.colorMask.setMask(15);
        } else if (instruction.action === "popMaskBegin") {
          renderer.colorMask.setMask(0);
          if (maskStackIndex !== 0) {
            renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);
          } else {
            renderer.renderTarget.clear(null, CLEAR.STENCIL);
            renderer.stencil.setStencilMode(STENCIL_MODES.DISABLED, maskStackIndex);
          }
          maskStackIndex--;
        } else if (instruction.action === "popMaskEnd") {
          if (instruction.inverse) {
            renderer.stencil.setStencilMode(STENCIL_MODES.INVERSE_MASK_ACTIVE, maskStackIndex);
          } else {
            renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
          }
          renderer.colorMask.setMask(15);
        }
        this._maskStackHash[renderTargetUid] = maskStackIndex;
      }
      destroy() {
        this._renderer = null;
        this._maskStackHash = null;
        this._maskHash = null;
      }
    }
    StencilMaskPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "stencilMask"
    };

    "use strict";
    var BUFFER_TYPE = /* @__PURE__ */ ((BUFFER_TYPE2) => {
      BUFFER_TYPE2[BUFFER_TYPE2["ELEMENT_ARRAY_BUFFER"] = 34963] = "ELEMENT_ARRAY_BUFFER";
      BUFFER_TYPE2[BUFFER_TYPE2["ARRAY_BUFFER"] = 34962] = "ARRAY_BUFFER";
      BUFFER_TYPE2[BUFFER_TYPE2["UNIFORM_BUFFER"] = 35345] = "UNIFORM_BUFFER";
      return BUFFER_TYPE2;
    })(BUFFER_TYPE || {});

    "use strict";
    class GlBuffer {
      constructor(buffer, type) {
        this._lastBindBaseLocation = -1;
        this._lastBindCallId = -1;
        this.buffer = buffer || null;
        this.updateID = -1;
        this.byteLength = -1;
        this.type = type;
      }
      destroy() {
        this.buffer = null;
        this.updateID = -1;
        this.byteLength = -1;
        this.type = -1;
        this._lastBindBaseLocation = -1;
        this._lastBindCallId = -1;
      }
    }

    "use strict";
    class GlBufferSystem {
      /**
       * @param {Renderer} renderer - The renderer this System works for.
       */
      constructor(renderer) {
        /** Cache keeping track of the base bound buffer bases */
        this._boundBufferBases = /* @__PURE__ */ Object.create(null);
        this._minBaseLocation = 0;
        this._nextBindBaseIndex = this._minBaseLocation;
        this._bindCallId = 0;
        this._renderer = renderer;
        this._managedBuffers = new GCManagedHash({
          renderer,
          type: "resource",
          onUnload: this.onBufferUnload.bind(this),
          name: "glBuffer"
        });
      }
      /** @ignore */
      destroy() {
        this._managedBuffers.destroy();
        this._renderer = null;
        this._gl = null;
        this._boundBufferBases = {};
      }
      /** Sets up the renderer context and necessary buffers. */
      contextChange() {
        this._gl = this._renderer.gl;
        this.destroyAll(true);
        this._maxBindings = this._renderer.limits.maxUniformBindings;
      }
      getGlBuffer(buffer) {
        buffer._gcLastUsed = this._renderer.gc.now;
        return buffer._gpuData[this._renderer.uid] || this.createGLBuffer(buffer);
      }
      /**
       * This binds specified buffer. On first run, it will create the webGL buffers for the context too
       * @param buffer - the buffer to bind to the renderer
       */
      bind(buffer) {
        const { _gl: gl } = this;
        const glBuffer = this.getGlBuffer(buffer);
        gl.bindBuffer(glBuffer.type, glBuffer.buffer);
      }
      /**
       * Binds an uniform buffer to at the given index.
       *
       * A cache is used so a buffer will not be bound again if already bound.
       * @param glBuffer - the buffer to bind
       * @param index - the base index to bind it to.
       */
      bindBufferBase(glBuffer, index) {
        const { _gl: gl } = this;
        if (this._boundBufferBases[index] !== glBuffer) {
          this._boundBufferBases[index] = glBuffer;
          glBuffer._lastBindBaseLocation = index;
          gl.bindBufferBase(gl.UNIFORM_BUFFER, index, glBuffer.buffer);
        }
      }
      nextBindBase(hasTransformFeedback) {
        this._bindCallId++;
        this._minBaseLocation = 0;
        if (hasTransformFeedback) {
          this._boundBufferBases[0] = null;
          this._minBaseLocation = 1;
          if (this._nextBindBaseIndex < 1) {
            this._nextBindBaseIndex = 1;
          }
        }
      }
      freeLocationForBufferBase(glBuffer) {
        let freeIndex = this.getLastBindBaseLocation(glBuffer);
        if (freeIndex >= this._minBaseLocation) {
          glBuffer._lastBindCallId = this._bindCallId;
          return freeIndex;
        }
        let loop = 0;
        let nextIndex = this._nextBindBaseIndex;
        while (loop < 2) {
          if (nextIndex >= this._maxBindings) {
            nextIndex = this._minBaseLocation;
            loop++;
          }
          const curBuf = this._boundBufferBases[nextIndex];
          if (curBuf && curBuf._lastBindCallId === this._bindCallId) {
            nextIndex++;
            continue;
          }
          break;
        }
        freeIndex = nextIndex;
        this._nextBindBaseIndex = nextIndex + 1;
        if (loop >= 2) {
          return -1;
        }
        glBuffer._lastBindCallId = this._bindCallId;
        this._boundBufferBases[freeIndex] = null;
        return freeIndex;
      }
      getLastBindBaseLocation(glBuffer) {
        const index = glBuffer._lastBindBaseLocation;
        if (this._boundBufferBases[index] === glBuffer) {
          return index;
        }
        return -1;
      }
      /**
       * Binds a buffer whilst also binding its range.
       * This will make the buffer start from the offset supplied rather than 0 when it is read.
       * @param glBuffer - the buffer to bind
       * @param index - the base index to bind at, defaults to 0
       * @param offset - the offset to bind at (this is blocks of 256). 0 = 0, 1 = 256, 2 = 512 etc
       * @param size - the size to bind at (this is blocks of 256).
       */
      bindBufferRange(glBuffer, index, offset, size) {
        const { _gl: gl } = this;
        offset || (offset = 0);
        index || (index = 0);
        this._boundBufferBases[index] = null;
        gl.bindBufferRange(gl.UNIFORM_BUFFER, index || 0, glBuffer.buffer, offset * 256, size || 256);
      }
      /**
       * Will ensure the data in the buffer is uploaded to the GPU.
       * @param {Buffer} buffer - the buffer to update
       */
      updateBuffer(buffer) {
        const { _gl: gl } = this;
        const glBuffer = this.getGlBuffer(buffer);
        if (buffer._updateID === glBuffer.updateID) {
          return glBuffer;
        }
        glBuffer.updateID = buffer._updateID;
        gl.bindBuffer(glBuffer.type, glBuffer.buffer);
        const data = buffer.data;
        const drawType = buffer.descriptor.usage & BufferUsage.STATIC ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
        if (data) {
          if (glBuffer.byteLength >= data.byteLength) {
            gl.bufferSubData(glBuffer.type, 0, data, 0, buffer._updateSize / data.BYTES_PER_ELEMENT);
          } else {
            glBuffer.byteLength = data.byteLength;
            gl.bufferData(glBuffer.type, data, drawType);
          }
        } else {
          glBuffer.byteLength = buffer.descriptor.size;
          gl.bufferData(glBuffer.type, glBuffer.byteLength, drawType);
        }
        return glBuffer;
      }
      /**
       * dispose all WebGL resources of all managed buffers
       * @param contextLost
       */
      destroyAll(contextLost = false) {
        this._managedBuffers.removeAll(contextLost);
      }
      onBufferUnload(buffer, contextLost = false) {
        const glBuffer = buffer._gpuData[this._renderer.uid];
        if (!glBuffer)
          return;
        if (!contextLost)
          this._gl.deleteBuffer(glBuffer.buffer);
      }
      /**
       * creates and attaches a GLBuffer object tied to the current context.
       * @param buffer
       * @protected
       */
      createGLBuffer(buffer) {
        const { _gl: gl } = this;
        let type = BUFFER_TYPE.ARRAY_BUFFER;
        if (buffer.descriptor.usage & BufferUsage.INDEX) {
          type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
        } else if (buffer.descriptor.usage & BufferUsage.UNIFORM) {
          type = BUFFER_TYPE.UNIFORM_BUFFER;
        }
        const glBuffer = new GlBuffer(gl.createBuffer(), type);
        buffer._gpuData[this._renderer.uid] = glBuffer;
        this._managedBuffers.add(buffer);
        return glBuffer;
      }
      resetState() {
        this._boundBufferBases = /* @__PURE__ */ Object.create(null);
      }
    }
    /** @ignore */
    GlBufferSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "buffer"
    };

    "use strict";
    var __defProp$q = Object.defineProperty;
    var __defProps$c = Object.defineProperties;
    var __getOwnPropDescs$c = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$s = Object.getOwnPropertySymbols;
    var __hasOwnProp$s = Object.prototype.hasOwnProperty;
    var __propIsEnum$s = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$q = (obj, key, value) => key in obj ? __defProp$q(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$q = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$s.call(b, prop))
          __defNormalProp$q(a, prop, b[prop]);
      if (__getOwnPropSymbols$s)
        for (var prop of __getOwnPropSymbols$s(b)) {
          if (__propIsEnum$s.call(b, prop))
            __defNormalProp$q(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$c = (a, b) => __defProps$c(a, __getOwnPropDescs$c(b));
    const _GlContextSystem = class _GlContextSystem {
      /** @param renderer - The renderer this System works for. */
      constructor(renderer) {
        /**
         * Features supported by current renderer.
         * @type {object}
         * @readonly
         */
        this.supports = {
          /** Support for 32-bit indices buffer. */
          uint32Indices: true,
          /** Support for UniformBufferObjects */
          uniformBufferObject: true,
          /** Support for VertexArrayObjects */
          vertexArrayObject: true,
          /** Support for SRGB texture format */
          srgbTextures: true,
          /** Support for wrapping modes if a texture is non-power of two */
          nonPowOf2wrapping: true,
          /** Support for MSAA (antialiasing of dynamic textures) */
          msaa: true,
          /** Support for mipmaps if a texture is non-power of two */
          nonPowOf2mipmaps: true
        };
        this._renderer = renderer;
        this.extensions = /* @__PURE__ */ Object.create(null);
        this.handleContextLost = this.handleContextLost.bind(this);
        this.handleContextRestored = this.handleContextRestored.bind(this);
      }
      /**
       * `true` if the context is lost
       * @readonly
       */
      get isLost() {
        return !this.gl || this.gl.isContextLost();
      }
      /**
       * Handles the context change event.
       * @param {WebGLRenderingContext} gl - New WebGL context.
       */
      contextChange(gl) {
        this.gl = gl;
        this._renderer.gl = gl;
      }
      init(options) {
        var _a, _b;
        options = __spreadValues$q(__spreadValues$q({}, _GlContextSystem.defaultOptions), options);
        let multiView = this.multiView = options.multiView;
        if (options.context && multiView) {
          warn("Renderer created with both a context and multiview enabled. Disabling multiView as both cannot work together.");
          multiView = false;
        }
        if (multiView) {
          this.canvas = DOMAdapter.get().createCanvas(this._renderer.canvas.width, this._renderer.canvas.height);
        } else {
          this.canvas = this._renderer.view.canvas;
        }
        if (options.context) {
          this.initFromContext(options.context);
        } else {
          const alpha = this._renderer.background.alpha < 1;
          const premultipliedAlpha = (_a = options.premultipliedAlpha) != null ? _a : true;
          const antialias = options.antialias && !this._renderer.backBuffer.useBackBuffer;
          this.createContext(options.preferWebGLVersion, {
            alpha,
            premultipliedAlpha,
            antialias,
            stencil: true,
            preserveDrawingBuffer: options.preserveDrawingBuffer,
            powerPreference: (_b = options.powerPreference) != null ? _b : "default"
          });
        }
      }
      ensureCanvasSize(targetCanvas) {
        if (!this.multiView) {
          if (targetCanvas !== this.canvas) {
            warn("multiView is disabled, but targetCanvas is not the main canvas");
          }
          return;
        }
        const { canvas } = this;
        if (canvas.width < targetCanvas.width || canvas.height < targetCanvas.height) {
          canvas.width = Math.max(targetCanvas.width, targetCanvas.width);
          canvas.height = Math.max(targetCanvas.height, targetCanvas.height);
        }
      }
      /**
       * Initializes the context.
       * @protected
       * @param {WebGLRenderingContext} gl - WebGL context
       */
      initFromContext(gl) {
        this.gl = gl;
        this.webGLVersion = gl instanceof DOMAdapter.get().getWebGLRenderingContext() ? 1 : 2;
        this.getExtensions();
        this.validateContext(gl);
        this._renderer.runners.contextChange.emit(gl);
        const element = this._renderer.view.canvas;
        element.addEventListener("webglcontextlost", this.handleContextLost, false);
        element.addEventListener("webglcontextrestored", this.handleContextRestored, false);
      }
      /**
       * Initialize from context options
       * @protected
       * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
       * @param preferWebGLVersion
       * @param {object} options - context attributes
       */
      createContext(preferWebGLVersion, options) {
        let gl;
        const canvas = this.canvas;
        if (preferWebGLVersion === 2) {
          gl = canvas.getContext("webgl2", options);
        }
        if (!gl) {
          gl = canvas.getContext("webgl", options);
          if (!gl) {
            throw new Error("This browser does not support WebGL. Try using the canvas renderer");
          }
        }
        this.gl = gl;
        this.initFromContext(this.gl);
      }
      /** Auto-populate the {@link GlContextSystem.extensions extensions}. */
      getExtensions() {
        const { gl } = this;
        const common = {
          anisotropicFiltering: gl.getExtension("EXT_texture_filter_anisotropic"),
          floatTextureLinear: gl.getExtension("OES_texture_float_linear"),
          s3tc: gl.getExtension("WEBGL_compressed_texture_s3tc"),
          s3tc_sRGB: gl.getExtension("WEBGL_compressed_texture_s3tc_srgb"),
          // eslint-disable-line camelcase
          etc: gl.getExtension("WEBGL_compressed_texture_etc"),
          etc1: gl.getExtension("WEBGL_compressed_texture_etc1"),
          pvrtc: gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"),
          atc: gl.getExtension("WEBGL_compressed_texture_atc"),
          astc: gl.getExtension("WEBGL_compressed_texture_astc"),
          bptc: gl.getExtension("EXT_texture_compression_bptc"),
          rgtc: gl.getExtension("EXT_texture_compression_rgtc"),
          loseContext: gl.getExtension("WEBGL_lose_context")
        };
        if (this.webGLVersion === 1) {
          this.extensions = __spreadProps$c(__spreadValues$q({}, common), {
            drawBuffers: gl.getExtension("WEBGL_draw_buffers"),
            depthTexture: gl.getExtension("WEBGL_depth_texture"),
            vertexArrayObject: gl.getExtension("OES_vertex_array_object") || gl.getExtension("MOZ_OES_vertex_array_object") || gl.getExtension("WEBKIT_OES_vertex_array_object"),
            uint32ElementIndex: gl.getExtension("OES_element_index_uint"),
            // Floats and half-floats
            floatTexture: gl.getExtension("OES_texture_float"),
            floatTextureLinear: gl.getExtension("OES_texture_float_linear"),
            textureHalfFloat: gl.getExtension("OES_texture_half_float"),
            textureHalfFloatLinear: gl.getExtension("OES_texture_half_float_linear"),
            vertexAttribDivisorANGLE: gl.getExtension("ANGLE_instanced_arrays"),
            srgb: gl.getExtension("EXT_sRGB")
          });
        } else {
          this.extensions = __spreadProps$c(__spreadValues$q({}, common), {
            colorBufferFloat: gl.getExtension("EXT_color_buffer_float")
          });
          const provokeExt = gl.getExtension("WEBGL_provoking_vertex");
          if (provokeExt) {
            provokeExt.provokingVertexWEBGL(provokeExt.FIRST_VERTEX_CONVENTION_WEBGL);
          }
        }
      }
      /**
       * Handles a lost webgl context
       * @param {WebGLContextEvent} event - The context lost event.
       */
      handleContextLost(event) {
        event.preventDefault();
        if (this._contextLossForced) {
          this._contextLossForced = false;
          setTimeout(() => {
            var _a;
            if (this.gl.isContextLost()) {
              (_a = this.extensions.loseContext) == null ? void 0 : _a.restoreContext();
            }
          }, 0);
        }
      }
      /** Handles a restored webgl context. */
      handleContextRestored() {
        this.getExtensions();
        this._renderer.runners.contextChange.emit(this.gl);
      }
      destroy() {
        var _a;
        const element = this._renderer.view.canvas;
        this._renderer = null;
        element.removeEventListener("webglcontextlost", this.handleContextLost);
        element.removeEventListener("webglcontextrestored", this.handleContextRestored);
        this.gl.useProgram(null);
        (_a = this.extensions.loseContext) == null ? void 0 : _a.loseContext();
      }
      /**
       * this function can be called to force a webGL context loss
       * this will release all resources on the GPU.
       * Useful if you need to put Pixi to sleep, and save some GPU memory
       *
       * As soon as render is called - all resources will be created again.
       */
      forceContextLoss() {
        var _a;
        (_a = this.extensions.loseContext) == null ? void 0 : _a.loseContext();
        this._contextLossForced = true;
      }
      /**
       * Validate context.
       * @param {WebGLRenderingContext} gl - Render context.
       */
      validateContext(gl) {
        const attributes = gl.getContextAttributes();
        if (attributes && !attributes.stencil) {
          warn("Provided WebGL context does not have a stencil buffer, masks may not render correctly");
        }
        const supports = this.supports;
        const isWebGl2 = this.webGLVersion === 2;
        const extensions = this.extensions;
        supports.uint32Indices = isWebGl2 || !!extensions.uint32ElementIndex;
        supports.uniformBufferObject = isWebGl2;
        supports.vertexArrayObject = isWebGl2 || !!extensions.vertexArrayObject;
        supports.srgbTextures = isWebGl2 || !!extensions.srgb;
        supports.nonPowOf2wrapping = isWebGl2;
        supports.nonPowOf2mipmaps = isWebGl2;
        supports.msaa = isWebGl2;
        if (!supports.uint32Indices) {
          warn("Provided WebGL context does not support 32 index buffer, large scenes may not render correctly");
        }
      }
    };
    /** @ignore */
    _GlContextSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "context"
    };
    /** The default options for the system. */
    _GlContextSystem.defaultOptions = {
      /**
       * {@link WebGLOptions.context}
       * @default null
       */
      context: null,
      /**
       * {@link WebGLOptions.premultipliedAlpha}
       * @default true
       */
      premultipliedAlpha: true,
      /**
       * {@link WebGLOptions.preserveDrawingBuffer}
       * @default false
       */
      preserveDrawingBuffer: false,
      /**
       * {@link WebGLOptions.powerPreference}
       * @default default
       */
      powerPreference: void 0,
      /**
       * {@link WebGLOptions.webGLVersion}
       * @default 2
       */
      preferWebGLVersion: 2,
      /**
       * {@link WebGLOptions.multiView}
       * @default false
       */
      multiView: false
    };
    let GlContextSystem = _GlContextSystem;

    "use strict";

    "use strict";

    "use strict";
    function ensureAttributes(geometry, extractedData) {
      var _a, _b, _c;
      for (const i in geometry.attributes) {
        const attribute = geometry.attributes[i];
        const attributeData = extractedData[i];
        if (attributeData) {
          (_a = attribute.format) != null ? _a : attribute.format = attributeData.format;
          (_b = attribute.offset) != null ? _b : attribute.offset = attributeData.offset;
          (_c = attribute.instance) != null ? _c : attribute.instance = attributeData.instance;
        } else {
          warn(`Attribute ${i} is not present in the shader, but is present in the geometry. Unable to infer attribute details.`);
        }
      }
      ensureStartAndStride(geometry);
    }
    function ensureStartAndStride(geometry) {
      var _a, _b;
      const { buffers, attributes } = geometry;
      const tempStride = {};
      const tempStart = {};
      for (const j in buffers) {
        const buffer = buffers[j];
        tempStride[buffer.uid] = 0;
        tempStart[buffer.uid] = 0;
      }
      for (const j in attributes) {
        const attribute = attributes[j];
        tempStride[attribute.buffer.uid] += getAttributeInfoFromFormat(attribute.format).stride;
      }
      for (const j in attributes) {
        const attribute = attributes[j];
        (_a = attribute.stride) != null ? _a : attribute.stride = tempStride[attribute.buffer.uid];
        (_b = attribute.start) != null ? _b : attribute.start = tempStart[attribute.buffer.uid];
        tempStart[attribute.buffer.uid] += getAttributeInfoFromFormat(attribute.format).stride;
      }
    }

    "use strict";
    var GL_FORMATS = /* @__PURE__ */ ((GL_FORMATS2) => {
      GL_FORMATS2[GL_FORMATS2["RGBA"] = 6408] = "RGBA";
      GL_FORMATS2[GL_FORMATS2["RGB"] = 6407] = "RGB";
      GL_FORMATS2[GL_FORMATS2["RG"] = 33319] = "RG";
      GL_FORMATS2[GL_FORMATS2["RED"] = 6403] = "RED";
      GL_FORMATS2[GL_FORMATS2["RGBA_INTEGER"] = 36249] = "RGBA_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RGB_INTEGER"] = 36248] = "RGB_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RG_INTEGER"] = 33320] = "RG_INTEGER";
      GL_FORMATS2[GL_FORMATS2["RED_INTEGER"] = 36244] = "RED_INTEGER";
      GL_FORMATS2[GL_FORMATS2["ALPHA"] = 6406] = "ALPHA";
      GL_FORMATS2[GL_FORMATS2["LUMINANCE"] = 6409] = "LUMINANCE";
      GL_FORMATS2[GL_FORMATS2["LUMINANCE_ALPHA"] = 6410] = "LUMINANCE_ALPHA";
      GL_FORMATS2[GL_FORMATS2["DEPTH_COMPONENT"] = 6402] = "DEPTH_COMPONENT";
      GL_FORMATS2[GL_FORMATS2["DEPTH_STENCIL"] = 34041] = "DEPTH_STENCIL";
      return GL_FORMATS2;
    })(GL_FORMATS || {});
    var GL_TARGETS = /* @__PURE__ */ ((GL_TARGETS2) => {
      GL_TARGETS2[GL_TARGETS2["TEXTURE_2D"] = 3553] = "TEXTURE_2D";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP"] = 34067] = "TEXTURE_CUBE_MAP";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_2D_ARRAY"] = 35866] = "TEXTURE_2D_ARRAY";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_X"] = 34069] = "TEXTURE_CUBE_MAP_POSITIVE_X";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_X"] = 34070] = "TEXTURE_CUBE_MAP_NEGATIVE_X";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_Y"] = 34071] = "TEXTURE_CUBE_MAP_POSITIVE_Y";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_Y"] = 34072] = "TEXTURE_CUBE_MAP_NEGATIVE_Y";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_Z"] = 34073] = "TEXTURE_CUBE_MAP_POSITIVE_Z";
      GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_Z"] = 34074] = "TEXTURE_CUBE_MAP_NEGATIVE_Z";
      return GL_TARGETS2;
    })(GL_TARGETS || {});
    var GL_WRAP_MODES = /* @__PURE__ */ ((GL_WRAP_MODES2) => {
      GL_WRAP_MODES2[GL_WRAP_MODES2["CLAMP"] = 33071] = "CLAMP";
      GL_WRAP_MODES2[GL_WRAP_MODES2["REPEAT"] = 10497] = "REPEAT";
      GL_WRAP_MODES2[GL_WRAP_MODES2["MIRRORED_REPEAT"] = 33648] = "MIRRORED_REPEAT";
      return GL_WRAP_MODES2;
    })(GL_WRAP_MODES || {});
    var GL_TYPES = /* @__PURE__ */ ((GL_TYPES2) => {
      GL_TYPES2[GL_TYPES2["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_6_5"] = 33635] = "UNSIGNED_SHORT_5_6_5";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_4_4_4_4"] = 32819] = "UNSIGNED_SHORT_4_4_4_4";
      GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_5_5_1"] = 32820] = "UNSIGNED_SHORT_5_5_5_1";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT"] = 5125] = "UNSIGNED_INT";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_10F_11F_11F_REV"] = 35899] = "UNSIGNED_INT_10F_11F_11F_REV";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_2_10_10_10_REV"] = 33640] = "UNSIGNED_INT_2_10_10_10_REV";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_24_8"] = 34042] = "UNSIGNED_INT_24_8";
      GL_TYPES2[GL_TYPES2["UNSIGNED_INT_5_9_9_9_REV"] = 35902] = "UNSIGNED_INT_5_9_9_9_REV";
      GL_TYPES2[GL_TYPES2["BYTE"] = 5120] = "BYTE";
      GL_TYPES2[GL_TYPES2["SHORT"] = 5122] = "SHORT";
      GL_TYPES2[GL_TYPES2["INT"] = 5124] = "INT";
      GL_TYPES2[GL_TYPES2["FLOAT"] = 5126] = "FLOAT";
      GL_TYPES2[GL_TYPES2["FLOAT_32_UNSIGNED_INT_24_8_REV"] = 36269] = "FLOAT_32_UNSIGNED_INT_24_8_REV";
      GL_TYPES2[GL_TYPES2["HALF_FLOAT"] = 36193] = "HALF_FLOAT";
      return GL_TYPES2;
    })(GL_TYPES || {});

    "use strict";
    const infoMap = {
      uint8x2: GL_TYPES.UNSIGNED_BYTE,
      uint8x4: GL_TYPES.UNSIGNED_BYTE,
      sint8x2: GL_TYPES.BYTE,
      sint8x4: GL_TYPES.BYTE,
      unorm8x2: GL_TYPES.UNSIGNED_BYTE,
      unorm8x4: GL_TYPES.UNSIGNED_BYTE,
      snorm8x2: GL_TYPES.BYTE,
      snorm8x4: GL_TYPES.BYTE,
      uint16x2: GL_TYPES.UNSIGNED_SHORT,
      uint16x4: GL_TYPES.UNSIGNED_SHORT,
      sint16x2: GL_TYPES.SHORT,
      sint16x4: GL_TYPES.SHORT,
      unorm16x2: GL_TYPES.UNSIGNED_SHORT,
      unorm16x4: GL_TYPES.UNSIGNED_SHORT,
      snorm16x2: GL_TYPES.SHORT,
      snorm16x4: GL_TYPES.SHORT,
      float16x2: GL_TYPES.HALF_FLOAT,
      float16x4: GL_TYPES.HALF_FLOAT,
      float32: GL_TYPES.FLOAT,
      float32x2: GL_TYPES.FLOAT,
      float32x3: GL_TYPES.FLOAT,
      float32x4: GL_TYPES.FLOAT,
      uint32: GL_TYPES.UNSIGNED_INT,
      uint32x2: GL_TYPES.UNSIGNED_INT,
      uint32x3: GL_TYPES.UNSIGNED_INT,
      uint32x4: GL_TYPES.UNSIGNED_INT,
      sint32: GL_TYPES.INT,
      sint32x2: GL_TYPES.INT,
      sint32x3: GL_TYPES.INT,
      sint32x4: GL_TYPES.INT
    };
    function getGlTypeFromFormat(format) {
      var _a;
      return (_a = infoMap[format]) != null ? _a : infoMap.float32;
    }

    "use strict";
    const topologyToGlMap = {
      "point-list": 0,
      "line-list": 1,
      "line-strip": 3,
      "triangle-list": 4,
      "triangle-strip": 5
    };
    class GlGeometryGpuData {
      constructor() {
        this.vaoCache = /* @__PURE__ */ Object.create(null);
      }
      destroy() {
        this.vaoCache = /* @__PURE__ */ Object.create(null);
      }
    }
    class GlGeometrySystem {
      /** @param renderer - The renderer this System works for. */
      constructor(renderer) {
        this._renderer = renderer;
        this._activeGeometry = null;
        this._activeVao = null;
        this.hasVao = true;
        this.hasInstance = true;
        this._managedGeometries = new GCManagedHash({
          renderer,
          type: "resource",
          onUnload: this.onGeometryUnload.bind(this),
          name: "glGeometry"
        });
      }
      /** Sets up the renderer context and necessary buffers. */
      contextChange() {
        const gl = this.gl = this._renderer.gl;
        if (!this._renderer.context.supports.vertexArrayObject) {
          throw new Error("[PixiJS] Vertex Array Objects are not supported on this device");
        }
        this.destroyAll(true);
        const nativeVaoExtension = this._renderer.context.extensions.vertexArrayObject;
        if (nativeVaoExtension) {
          gl.createVertexArray = () => nativeVaoExtension.createVertexArrayOES();
          gl.bindVertexArray = (vao) => nativeVaoExtension.bindVertexArrayOES(vao);
          gl.deleteVertexArray = (vao) => nativeVaoExtension.deleteVertexArrayOES(vao);
        }
        const nativeInstancedExtension = this._renderer.context.extensions.vertexAttribDivisorANGLE;
        if (nativeInstancedExtension) {
          gl.drawArraysInstanced = (a, b, c, d) => {
            nativeInstancedExtension.drawArraysInstancedANGLE(a, b, c, d);
          };
          gl.drawElementsInstanced = (a, b, c, d, e) => {
            nativeInstancedExtension.drawElementsInstancedANGLE(a, b, c, d, e);
          };
          gl.vertexAttribDivisor = (a, b) => nativeInstancedExtension.vertexAttribDivisorANGLE(a, b);
        }
        this._activeGeometry = null;
        this._activeVao = null;
      }
      /**
       * Binds geometry so that is can be drawn. Creating a Vao if required
       * @param geometry - Instance of geometry to bind.
       * @param program - Instance of program to use vao for.
       */
      bind(geometry, program) {
        const gl = this.gl;
        this._activeGeometry = geometry;
        const vao = this.getVao(geometry, program);
        if (this._activeVao !== vao) {
          this._activeVao = vao;
          gl.bindVertexArray(vao);
        }
        this.updateBuffers();
      }
      /** Reset and unbind any active VAO and geometry. */
      resetState() {
        this.unbind();
      }
      /** Update buffers of the currently bound geometry. */
      updateBuffers() {
        const geometry = this._activeGeometry;
        const bufferSystem = this._renderer.buffer;
        for (let i = 0; i < geometry.buffers.length; i++) {
          const buffer = geometry.buffers[i];
          bufferSystem.updateBuffer(buffer);
        }
        geometry._gcLastUsed = this._renderer.gc.now;
      }
      /**
       * Check compatibility between a geometry and a program
       * @param geometry - Geometry instance.
       * @param program - Program instance.
       */
      checkCompatibility(geometry, program) {
        const geometryAttributes = geometry.attributes;
        const shaderAttributes = program._attributeData;
        for (const j in shaderAttributes) {
          if (!geometryAttributes[j]) {
            throw new Error(`shader and geometry incompatible, geometry missing the "${j}" attribute`);
          }
        }
      }
      /**
       * Takes a geometry and program and generates a unique signature for them.
       * @param geometry - To get signature from.
       * @param program - To test geometry against.
       * @returns - Unique signature of the geometry and program
       */
      getSignature(geometry, program) {
        const attribs = geometry.attributes;
        const shaderAttributes = program._attributeData;
        const strings = ["g", geometry.uid];
        for (const i in attribs) {
          if (shaderAttributes[i]) {
            strings.push(i, shaderAttributes[i].location);
          }
        }
        return strings.join("-");
      }
      getVao(geometry, program) {
        var _a;
        return ((_a = geometry._gpuData[this._renderer.uid]) == null ? void 0 : _a.vaoCache[program._key]) || this.initGeometryVao(geometry, program);
      }
      /**
       * Creates or gets Vao with the same structure as the geometry and stores it on the geometry.
       * If vao is created, it is bound automatically. We use a shader to infer what and how to set up the
       * attribute locations.
       * @param geometry - Instance of geometry to to generate Vao for.
       * @param program
       * @param _incRefCount - Increment refCount of all geometry buffers.
       */
      initGeometryVao(geometry, program, _incRefCount = true) {
        const gl = this._renderer.gl;
        const bufferSystem = this._renderer.buffer;
        this._renderer.shader._getProgramData(program);
        this.checkCompatibility(geometry, program);
        const signature = this.getSignature(geometry, program);
        const gpuData = new GlGeometryGpuData();
        geometry._gpuData[this._renderer.uid] = gpuData;
        this._managedGeometries.add(geometry);
        const vaoObjectHash = gpuData.vaoCache;
        let vao = vaoObjectHash[signature];
        if (vao) {
          vaoObjectHash[program._key] = vao;
          return vao;
        }
        ensureAttributes(geometry, program._attributeData);
        const buffers = geometry.buffers;
        vao = gl.createVertexArray();
        gl.bindVertexArray(vao);
        for (let i = 0; i < buffers.length; i++) {
          const buffer = buffers[i];
          bufferSystem.bind(buffer);
        }
        this.activateVao(geometry, program);
        vaoObjectHash[program._key] = vao;
        vaoObjectHash[signature] = vao;
        gl.bindVertexArray(null);
        return vao;
      }
      onGeometryUnload(geometry, contextLost = false) {
        const gpuData = geometry._gpuData[this._renderer.uid];
        if (!gpuData)
          return;
        const vaoCache = gpuData.vaoCache;
        if (!contextLost) {
          for (const i in vaoCache) {
            if (this._activeVao !== vaoCache[i]) {
              this.resetState();
            }
            this.gl.deleteVertexArray(vaoCache[i]);
          }
        }
      }
      /**
       * Dispose all WebGL resources of all managed geometries.
       * @param [contextLost=false] - If context was lost, we suppress `gl.delete` calls
       */
      destroyAll(contextLost = false) {
        this._managedGeometries.removeAll(contextLost);
      }
      /**
       * Activate vertex array object.
       * @param geometry - Geometry instance.
       * @param program - Shader program instance.
       */
      activateVao(geometry, program) {
        var _a, _b;
        const gl = this._renderer.gl;
        const bufferSystem = this._renderer.buffer;
        const attributes = geometry.attributes;
        if (geometry.indexBuffer) {
          bufferSystem.bind(geometry.indexBuffer);
        }
        let lastBuffer = null;
        for (const j in attributes) {
          const attribute = attributes[j];
          const buffer = attribute.buffer;
          const glBuffer = bufferSystem.getGlBuffer(buffer);
          const programAttrib = program._attributeData[j];
          if (programAttrib) {
            if (lastBuffer !== glBuffer) {
              bufferSystem.bind(buffer);
              lastBuffer = glBuffer;
            }
            const location = programAttrib.location;
            gl.enableVertexAttribArray(location);
            const attributeInfo = getAttributeInfoFromFormat(attribute.format);
            const type = getGlTypeFromFormat(attribute.format);
            if (((_a = programAttrib.format) == null ? void 0 : _a.substring(1, 4)) === "int") {
              gl.vertexAttribIPointer(
                location,
                attributeInfo.size,
                type,
                attribute.stride,
                attribute.offset
              );
            } else {
              gl.vertexAttribPointer(
                location,
                attributeInfo.size,
                type,
                attributeInfo.normalised,
                attribute.stride,
                attribute.offset
              );
            }
            if (attribute.instance) {
              if (this.hasInstance) {
                const divisor = (_b = attribute.divisor) != null ? _b : 1;
                gl.vertexAttribDivisor(location, divisor);
              } else {
                throw new Error("geometry error, GPU Instancing is not supported on this device");
              }
            }
          }
        }
      }
      /**
       * Draws the currently bound geometry.
       * @param topology - The type primitive to render.
       * @param size - The number of elements to be rendered. If not specified, all vertices after the
       *  starting vertex will be drawn.
       * @param start - The starting vertex in the geometry to start drawing from. If not specified,
       *  drawing will start from the first vertex.
       * @param instanceCount - The number of instances of the set of elements to execute. If not specified,
       *  all instances will be drawn.
       * @returns This instance of the geometry system.
       */
      draw(topology, size, start, instanceCount) {
        const { gl } = this._renderer;
        const geometry = this._activeGeometry;
        const glTopology = topologyToGlMap[topology || geometry.topology];
        instanceCount != null ? instanceCount : instanceCount = geometry.instanceCount;
        if (geometry.indexBuffer) {
          const byteSize = geometry.indexBuffer.data.BYTES_PER_ELEMENT;
          const glType = byteSize === 2 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
          if (instanceCount !== 1) {
            gl.drawElementsInstanced(glTopology, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize, instanceCount);
          } else {
            gl.drawElements(glTopology, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize);
          }
        } else if (instanceCount !== 1) {
          gl.drawArraysInstanced(glTopology, start || 0, size || geometry.getSize(), instanceCount);
        } else {
          gl.drawArrays(glTopology, start || 0, size || geometry.getSize());
        }
        return this;
      }
      /** Unbind/reset everything. */
      unbind() {
        this.gl.bindVertexArray(null);
        this._activeVao = null;
        this._activeGeometry = null;
      }
      destroy() {
        this._managedGeometries.destroy();
        this._renderer = null;
        this.gl = null;
        this._activeVao = null;
        this._activeGeometry = null;
      }
    }
    /** @ignore */
    GlGeometrySystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "geometry"
    };

    "use strict";
    var __defProp$p = Object.defineProperty;
    var __getOwnPropSymbols$r = Object.getOwnPropertySymbols;
    var __hasOwnProp$r = Object.prototype.hasOwnProperty;
    var __propIsEnum$r = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$p = (obj, key, value) => key in obj ? __defProp$p(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$p = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$r.call(b, prop))
          __defNormalProp$p(a, prop, b[prop]);
      if (__getOwnPropSymbols$r)
        for (var prop of __getOwnPropSymbols$r(b)) {
          if (__propIsEnum$r.call(b, prop))
            __defNormalProp$p(a, prop, b[prop]);
        }
      return a;
    };
    const bigTriangleGeometry = new Geometry({
      attributes: {
        aPosition: [
          -1,
          -1,
          // Bottom left corner
          3,
          -1,
          // Bottom right corner, extending beyond right edge
          -1,
          3
          // Top left corner, extending beyond top edge
        ]
      }
    });
    const _GlBackBufferSystem = class _GlBackBufferSystem {
      constructor(renderer) {
        /** if true, the back buffer is used */
        this.useBackBuffer = false;
        this._useBackBufferThisRender = false;
        this._renderer = renderer;
      }
      init(options = {}) {
        const { useBackBuffer, antialias } = __spreadValues$p(__spreadValues$p({}, _GlBackBufferSystem.defaultOptions), options);
        this.useBackBuffer = useBackBuffer;
        this._antialias = antialias;
        if (!this._renderer.context.supports.msaa) {
          warn("antialiasing, is not supported on when using the back buffer");
          this._antialias = false;
        }
        this._state = State.for2d();
        const bigTriangleProgram = new GlProgram({
          vertex: `
                attribute vec2 aPosition;
                out vec2 vUv;

                void main() {
                    gl_Position = vec4(aPosition, 0.0, 1.0);

                    vUv = (aPosition + 1.0) / 2.0;

                    // flip dem UVs
                    vUv.y = 1.0 - vUv.y;
                }`,
          fragment: `
                in vec2 vUv;
                out vec4 finalColor;

                uniform sampler2D uTexture;

                void main() {
                    finalColor = texture(uTexture, vUv);
                }`,
          name: "big-triangle"
        });
        this._bigTriangleShader = new Shader({
          glProgram: bigTriangleProgram,
          resources: {
            uTexture: Texture.WHITE.source
          }
        });
      }
      /**
       * This is called before the RenderTargetSystem is started. This is where
       * we replace the target with the back buffer if required.
       * @param options - The options for this render.
       */
      renderStart(options) {
        const renderTarget = this._renderer.renderTarget.getRenderTarget(options.target);
        this._useBackBufferThisRender = this.useBackBuffer && !!renderTarget.isRoot;
        if (this._useBackBufferThisRender) {
          const renderTarget2 = this._renderer.renderTarget.getRenderTarget(options.target);
          this._targetTexture = renderTarget2.colorTexture;
          options.target = this._getBackBufferTexture(renderTarget2.colorTexture);
        }
      }
      renderEnd() {
        this._presentBackBuffer();
      }
      _presentBackBuffer() {
        const renderer = this._renderer;
        renderer.renderTarget.finishRenderPass();
        if (!this._useBackBufferThisRender)
          return;
        renderer.renderTarget.bind(this._targetTexture, false);
        this._bigTriangleShader.resources.uTexture = this._backBufferTexture.source;
        renderer.encoder.draw({
          geometry: bigTriangleGeometry,
          shader: this._bigTriangleShader,
          state: this._state
        });
      }
      _getBackBufferTexture(targetSourceTexture) {
        this._backBufferTexture = this._backBufferTexture || new Texture({
          source: new TextureSource({
            width: targetSourceTexture.width,
            height: targetSourceTexture.height,
            resolution: targetSourceTexture._resolution,
            antialias: this._antialias
          })
        });
        this._backBufferTexture.source.resize(
          targetSourceTexture.width,
          targetSourceTexture.height,
          targetSourceTexture._resolution
        );
        return this._backBufferTexture;
      }
      /** destroys the back buffer */
      destroy() {
        if (this._backBufferTexture) {
          this._backBufferTexture.destroy();
          this._backBufferTexture = null;
        }
      }
    };
    /** @ignore */
    _GlBackBufferSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "backBuffer",
      priority: 1
    };
    /** default options for the back buffer system */
    _GlBackBufferSystem.defaultOptions = {
      /** if true will use the back buffer where required */
      useBackBuffer: false
    };
    let GlBackBufferSystem = _GlBackBufferSystem;

    "use strict";
    class GlColorMaskSystem {
      constructor(renderer) {
        this._colorMaskCache = 15;
        this._renderer = renderer;
      }
      setMask(colorMask) {
        if (this._colorMaskCache === colorMask)
          return;
        this._colorMaskCache = colorMask;
        this._renderer.gl.colorMask(
          !!(colorMask & 8),
          !!(colorMask & 4),
          !!(colorMask & 2),
          !!(colorMask & 1)
        );
      }
    }
    /** @ignore */
    GlColorMaskSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "colorMask"
    };

    "use strict";
    class GlEncoderSystem {
      constructor(renderer) {
        this.commandFinished = Promise.resolve();
        this._renderer = renderer;
      }
      setGeometry(geometry, shader) {
        this._renderer.geometry.bind(geometry, shader.glProgram);
      }
      finishRenderPass() {
      }
      draw(options) {
        const renderer = this._renderer;
        const { geometry, shader, state, skipSync, topology: type, size, start, instanceCount } = options;
        renderer.shader.bind(shader, skipSync);
        renderer.geometry.bind(geometry, renderer.shader._activeProgram);
        if (state) {
          renderer.state.set(state);
        }
        renderer.geometry.draw(type, size, start, instanceCount != null ? instanceCount : geometry.instanceCount);
      }
      destroy() {
        this._renderer = null;
      }
    }
    /** @ignore */
    GlEncoderSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "encoder"
    };

    "use strict";
    class GlLimitsSystem {
      constructor(renderer) {
        this._renderer = renderer;
      }
      contextChange() {
        const gl = this._renderer.gl;
        this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
        this.maxBatchableTextures = checkMaxIfStatementsInShader(this.maxTextures, gl);
        const isWebGl2 = this._renderer.context.webGLVersion === 2;
        this.maxUniformBindings = isWebGl2 ? gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS) : 0;
      }
      destroy() {
      }
    }
    /** @ignore */
    GlLimitsSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "limits"
    };

    "use strict";
    class GlRenderTarget {
      constructor() {
        this.width = -1;
        this.height = -1;
        this.msaa = false;
        this.msaaRenderBuffer = [];
      }
    }

    "use strict";
    const GpuStencilModesToPixi = [];
    GpuStencilModesToPixi[STENCIL_MODES.NONE] = void 0;
    GpuStencilModesToPixi[STENCIL_MODES.DISABLED] = {
      stencilWriteMask: 0,
      stencilReadMask: 0
    };
    GpuStencilModesToPixi[STENCIL_MODES.RENDERING_MASK_ADD] = {
      stencilFront: {
        compare: "equal",
        passOp: "increment-clamp"
      },
      stencilBack: {
        compare: "equal",
        passOp: "increment-clamp"
      }
    };
    GpuStencilModesToPixi[STENCIL_MODES.RENDERING_MASK_REMOVE] = {
      stencilFront: {
        compare: "equal",
        passOp: "decrement-clamp"
      },
      stencilBack: {
        compare: "equal",
        passOp: "decrement-clamp"
      }
    };
    GpuStencilModesToPixi[STENCIL_MODES.MASK_ACTIVE] = {
      stencilWriteMask: 0,
      stencilFront: {
        compare: "equal",
        passOp: "keep"
      },
      stencilBack: {
        compare: "equal",
        passOp: "keep"
      }
    };
    GpuStencilModesToPixi[STENCIL_MODES.INVERSE_MASK_ACTIVE] = {
      stencilWriteMask: 0,
      stencilFront: {
        compare: "not-equal",
        passOp: "keep"
      },
      stencilBack: {
        compare: "not-equal",
        passOp: "keep"
      }
    };

    "use strict";
    class GlStencilSystem {
      constructor(renderer) {
        this._stencilCache = {
          enabled: false,
          stencilReference: 0,
          stencilMode: STENCIL_MODES.NONE
        };
        this._renderTargetStencilState = /* @__PURE__ */ Object.create(null);
        renderer.renderTarget.onRenderTargetChange.add(this);
      }
      contextChange(gl) {
        this._gl = gl;
        this._comparisonFuncMapping = {
          always: gl.ALWAYS,
          never: gl.NEVER,
          equal: gl.EQUAL,
          "not-equal": gl.NOTEQUAL,
          less: gl.LESS,
          "less-equal": gl.LEQUAL,
          greater: gl.GREATER,
          "greater-equal": gl.GEQUAL
        };
        this._stencilOpsMapping = {
          keep: gl.KEEP,
          zero: gl.ZERO,
          replace: gl.REPLACE,
          invert: gl.INVERT,
          "increment-clamp": gl.INCR,
          "decrement-clamp": gl.DECR,
          "increment-wrap": gl.INCR_WRAP,
          "decrement-wrap": gl.DECR_WRAP
        };
        this.resetState();
      }
      onRenderTargetChange(renderTarget) {
        if (this._activeRenderTarget === renderTarget)
          return;
        this._activeRenderTarget = renderTarget;
        let stencilState = this._renderTargetStencilState[renderTarget.uid];
        if (!stencilState) {
          stencilState = this._renderTargetStencilState[renderTarget.uid] = {
            stencilMode: STENCIL_MODES.DISABLED,
            stencilReference: 0
          };
        }
        this.setStencilMode(stencilState.stencilMode, stencilState.stencilReference);
      }
      resetState() {
        this._stencilCache.enabled = false;
        this._stencilCache.stencilMode = STENCIL_MODES.NONE;
        this._stencilCache.stencilReference = 0;
      }
      setStencilMode(stencilMode, stencilReference) {
        const stencilState = this._renderTargetStencilState[this._activeRenderTarget.uid];
        const gl = this._gl;
        const mode = GpuStencilModesToPixi[stencilMode];
        const _stencilCache = this._stencilCache;
        stencilState.stencilMode = stencilMode;
        stencilState.stencilReference = stencilReference;
        if (stencilMode === STENCIL_MODES.DISABLED) {
          if (this._stencilCache.enabled) {
            this._stencilCache.enabled = false;
            gl.disable(gl.STENCIL_TEST);
          }
          return;
        }
        if (!this._stencilCache.enabled) {
          this._stencilCache.enabled = true;
          gl.enable(gl.STENCIL_TEST);
        }
        if (stencilMode !== _stencilCache.stencilMode || _stencilCache.stencilReference !== stencilReference) {
          _stencilCache.stencilMode = stencilMode;
          _stencilCache.stencilReference = stencilReference;
          gl.stencilFunc(this._comparisonFuncMapping[mode.stencilBack.compare], stencilReference, 255);
          gl.stencilOp(gl.KEEP, gl.KEEP, this._stencilOpsMapping[mode.stencilBack.passOp]);
        }
      }
    }
    /** @ignore */
    GlStencilSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "stencil"
    };

    "use strict";
    class UboSystem {
      constructor(adaptor) {
        /** Cache of uniform buffer layouts and sync functions, so we don't have to re-create them */
        this._syncFunctionHash = /* @__PURE__ */ Object.create(null);
        this._adaptor = adaptor;
        this._systemCheck();
      }
      /**
       * Overridable function by `pixi.js/unsafe-eval` to silence
       * throwing an error if platform doesn't support unsafe-evals.
       * @private
       */
      _systemCheck() {
        if (!unsafeEvalSupported()) {
          throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
        }
      }
      ensureUniformGroup(uniformGroup) {
        const uniformData = this.getUniformGroupData(uniformGroup);
        uniformGroup.buffer || (uniformGroup.buffer = new Buffer({
          data: new Float32Array(uniformData.layout.size / 4),
          usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST
        }));
      }
      getUniformGroupData(uniformGroup) {
        return this._syncFunctionHash[uniformGroup._signature] || this._initUniformGroup(uniformGroup);
      }
      _initUniformGroup(uniformGroup) {
        const uniformGroupSignature = uniformGroup._signature;
        let uniformData = this._syncFunctionHash[uniformGroupSignature];
        if (!uniformData) {
          const elements = Object.keys(uniformGroup.uniformStructures).map((i) => uniformGroup.uniformStructures[i]);
          const layout = this._adaptor.createUboElements(elements);
          const syncFunction = this._generateUboSync(layout.uboElements);
          uniformData = this._syncFunctionHash[uniformGroupSignature] = {
            layout,
            syncFunction
          };
        }
        return this._syncFunctionHash[uniformGroupSignature];
      }
      _generateUboSync(uboElements) {
        return this._adaptor.generateUboSync(uboElements);
      }
      syncUniformGroup(uniformGroup, data, offset) {
        const uniformGroupData = this.getUniformGroupData(uniformGroup);
        uniformGroup.buffer || (uniformGroup.buffer = new Buffer({
          data: new Float32Array(uniformGroupData.layout.size / 4),
          usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST
        }));
        let dataInt32 = null;
        if (!data) {
          data = uniformGroup.buffer.data;
          dataInt32 = uniformGroup.buffer.dataInt32;
        }
        offset || (offset = 0);
        uniformGroupData.syncFunction(uniformGroup.uniforms, data, dataInt32, offset);
        return true;
      }
      updateUniformGroup(uniformGroup) {
        if (uniformGroup.isStatic && !uniformGroup._dirtyId)
          return false;
        uniformGroup._dirtyId = 0;
        const synced = this.syncUniformGroup(uniformGroup);
        uniformGroup.buffer.update();
        return synced;
      }
      destroy() {
        this._syncFunctionHash = null;
      }
    }

    "use strict";
    const WGSL_TO_STD40_SIZE = {
      f32: 4,
      i32: 4,
      "vec2<f32>": 8,
      "vec3<f32>": 12,
      "vec4<f32>": 16,
      "vec2<i32>": 8,
      "vec3<i32>": 12,
      "vec4<i32>": 16,
      "mat2x2<f32>": 16 * 2,
      "mat3x3<f32>": 16 * 3,
      "mat4x4<f32>": 16 * 4
      // TODO - not essential for now but support these in the future
      // int:      4,
      // ivec2:    8,
      // ivec3:    12,
      // ivec4:    16,
      // uint:     4,
      // uvec2:    8,
      // uvec3:    12,
      // uvec4:    16,
      // bool:     4,
      // bvec2:    8,
      // bvec3:    12,
      // bvec4:    16,
      // mat2:     16 * 2,
      // mat3:     16 * 3,
      // mat4:     16 * 4,
    };
    function createUboElementsSTD40(uniformData) {
      const uboElements = uniformData.map((data) => ({
        data,
        offset: 0,
        size: 0
      }));
      const chunkSize = 16;
      let size = 0;
      let offset = 0;
      for (let i = 0; i < uboElements.length; i++) {
        const uboElement = uboElements[i];
        size = WGSL_TO_STD40_SIZE[uboElement.data.type];
        if (!size) {
          throw new Error(`Unknown type ${uboElement.data.type}`);
        }
        if (uboElement.data.size > 1) {
          size = Math.max(size, chunkSize) * uboElement.data.size;
        }
        const boundary = size === 12 ? 16 : size;
        uboElement.size = size;
        const curOffset = offset % chunkSize;
        if (curOffset > 0 && chunkSize - curOffset < boundary) {
          offset += (chunkSize - curOffset) % 16;
        } else {
          offset += (size - curOffset % size) % size;
        }
        uboElement.offset = offset;
        offset += size;
      }
      offset = Math.ceil(offset / 16) * 16;
      return { uboElements, size: offset };
    }

    "use strict";
    const uniformParsers = [
      // uploading pixi matrix object to mat3
      {
        type: "mat3x3<f32>",
        test: (data) => {
          const value = data.value;
          return value.a !== void 0;
        },
        ubo: `
            var matrix = uv[name].toArray(true);
            data[offset] = matrix[0];
            data[offset + 1] = matrix[1];
            data[offset + 2] = matrix[2];
            data[offset + 4] = matrix[3];
            data[offset + 5] = matrix[4];
            data[offset + 6] = matrix[5];
            data[offset + 8] = matrix[6];
            data[offset + 9] = matrix[7];
            data[offset + 10] = matrix[8];
        `,
        uniform: `
            gl.uniformMatrix3fv(ud[name].location, false, uv[name].toArray(true));
        `
      },
      // uploading a pixi rectangle as a vec4
      {
        type: "vec4<f32>",
        test: (data) => data.type === "vec4<f32>" && data.size === 1 && data.value.width !== void 0,
        ubo: `
            v = uv[name];
            data[offset] = v.x;
            data[offset + 1] = v.y;
            data[offset + 2] = v.width;
            data[offset + 3] = v.height;
        `,
        uniform: `
            cv = ud[name].value;
            v = uv[name];
            if (cv[0] !== v.x || cv[1] !== v.y || cv[2] !== v.width || cv[3] !== v.height) {
                cv[0] = v.x;
                cv[1] = v.y;
                cv[2] = v.width;
                cv[3] = v.height;
                gl.uniform4f(ud[name].location, v.x, v.y, v.width, v.height);
            }
        `
      },
      // uploading a pixi point as a vec2
      {
        type: "vec2<f32>",
        test: (data) => data.type === "vec2<f32>" && data.size === 1 && data.value.x !== void 0,
        ubo: `
            v = uv[name];
            data[offset] = v.x;
            data[offset + 1] = v.y;
        `,
        uniform: `
            cv = ud[name].value;
            v = uv[name];
            if (cv[0] !== v.x || cv[1] !== v.y) {
                cv[0] = v.x;
                cv[1] = v.y;
                gl.uniform2f(ud[name].location, v.x, v.y);
            }
        `
      },
      // uploading a pixi color as a vec4
      {
        type: "vec4<f32>",
        test: (data) => data.type === "vec4<f32>" && data.size === 1 && data.value.red !== void 0,
        ubo: `
            v = uv[name];
            data[offset] = v.red;
            data[offset + 1] = v.green;
            data[offset + 2] = v.blue;
            data[offset + 3] = v.alpha;
        `,
        uniform: `
            cv = ud[name].value;
            v = uv[name];
            if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue || cv[3] !== v.alpha) {
                cv[0] = v.red;
                cv[1] = v.green;
                cv[2] = v.blue;
                cv[3] = v.alpha;
                gl.uniform4f(ud[name].location, v.red, v.green, v.blue, v.alpha);
            }
        `
      },
      // uploading a pixi color as a vec3
      {
        type: "vec3<f32>",
        test: (data) => data.type === "vec3<f32>" && data.size === 1 && data.value.red !== void 0,
        ubo: `
            v = uv[name];
            data[offset] = v.red;
            data[offset + 1] = v.green;
            data[offset + 2] = v.blue;
        `,
        uniform: `
            cv = ud[name].value;
            v = uv[name];
            if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue) {
                cv[0] = v.red;
                cv[1] = v.green;
                cv[2] = v.blue;
                gl.uniform3f(ud[name].location, v.red, v.green, v.blue);
            }
        `
      }
    ];

    "use strict";
    function createUboSyncFunction(uboElements, parserCode, arrayGenerationFunction, singleSettersMap) {
      const funcFragments = [`
        var v = null;
        var v2 = null;
        var t = 0;
        var index = 0;
        var name = null;
        var arrayOffset = null;
    `];
      let prev = 0;
      for (let i = 0; i < uboElements.length; i++) {
        const uboElement = uboElements[i];
        const name = uboElement.data.name;
        let parsed = false;
        let offset = 0;
        for (let j = 0; j < uniformParsers.length; j++) {
          const uniformParser = uniformParsers[j];
          if (uniformParser.test(uboElement.data)) {
            offset = uboElement.offset / 4;
            funcFragments.push(
              `name = "${name}";`,
              `offset += ${offset - prev};`,
              uniformParsers[j][parserCode] || uniformParsers[j].ubo
            );
            parsed = true;
            break;
          }
        }
        if (!parsed) {
          if (uboElement.data.size > 1) {
            offset = uboElement.offset / 4;
            funcFragments.push(arrayGenerationFunction(uboElement, offset - prev));
          } else {
            const template = singleSettersMap[uboElement.data.type];
            offset = uboElement.offset / 4;
            funcFragments.push(
              /* wgsl */
              `
                    v = uv.${name};
                    offset += ${offset - prev};
                    ${template};
                `
            );
          }
        }
        prev = offset;
      }
      const fragmentSrc = funcFragments.join("\n");
      return new Function(
        "uv",
        "data",
        "dataInt32",
        "offset",
        fragmentSrc
      );
    }

    "use strict";
    var __defProp$o = Object.defineProperty;
    var __defProps$b = Object.defineProperties;
    var __getOwnPropDescs$b = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$q = Object.getOwnPropertySymbols;
    var __hasOwnProp$q = Object.prototype.hasOwnProperty;
    var __propIsEnum$q = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$o = (obj, key, value) => key in obj ? __defProp$o(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$o = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$q.call(b, prop))
          __defNormalProp$o(a, prop, b[prop]);
      if (__getOwnPropSymbols$q)
        for (var prop of __getOwnPropSymbols$q(b)) {
          if (__propIsEnum$q.call(b, prop))
            __defNormalProp$o(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$b = (a, b) => __defProps$b(a, __getOwnPropDescs$b(b));
    function loopMatrix(col, row) {
      const total = col * row;
      return `
        for (let i = 0; i < ${total}; i++) {
            data[offset + (((i / ${col})|0) * 4) + (i % ${col})] = v[i];
        }
    `;
    }
    const uboSyncFunctionsSTD40 = {
      f32: `
        data[offset] = v;`,
      i32: `
        dataInt32[offset] = v;`,
      "vec2<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];`,
      "vec3<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];
        data[offset + 2] = v[2];`,
      "vec4<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];
        data[offset + 2] = v[2];
        data[offset + 3] = v[3];`,
      "vec2<i32>": `
        dataInt32[offset] = v[0];
        dataInt32[offset + 1] = v[1];`,
      "vec3<i32>": `
        dataInt32[offset] = v[0];
        dataInt32[offset + 1] = v[1];
        dataInt32[offset + 2] = v[2];`,
      "vec4<i32>": `
        dataInt32[offset] = v[0];
        dataInt32[offset + 1] = v[1];
        dataInt32[offset + 2] = v[2];
        dataInt32[offset + 3] = v[3];`,
      "mat2x2<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];
        data[offset + 4] = v[2];
        data[offset + 5] = v[3];`,
      "mat3x3<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];
        data[offset + 2] = v[2];
        data[offset + 4] = v[3];
        data[offset + 5] = v[4];
        data[offset + 6] = v[5];
        data[offset + 8] = v[6];
        data[offset + 9] = v[7];
        data[offset + 10] = v[8];`,
      "mat4x4<f32>": `
        for (let i = 0; i < 16; i++) {
            data[offset + i] = v[i];
        }`,
      "mat3x2<f32>": loopMatrix(3, 2),
      "mat4x2<f32>": loopMatrix(4, 2),
      "mat2x3<f32>": loopMatrix(2, 3),
      "mat4x3<f32>": loopMatrix(4, 3),
      "mat2x4<f32>": loopMatrix(2, 4),
      "mat3x4<f32>": loopMatrix(3, 4)
    };
    const uboSyncFunctionsWGSL = __spreadProps$b(__spreadValues$o({}, uboSyncFunctionsSTD40), {
      "mat2x2<f32>": `
        data[offset] = v[0];
        data[offset + 1] = v[1];
        data[offset + 2] = v[2];
        data[offset + 3] = v[3];
    `
    });

    "use strict";
    function generateArraySyncSTD40(uboElement, offsetToAdd) {
      const rowSize = Math.max(WGSL_TO_STD40_SIZE[uboElement.data.type] / 16, 1);
      const elementSize = uboElement.data.value.length / uboElement.data.size;
      const remainder = (4 - elementSize % 4) % 4;
      const data = uboElement.data.type.indexOf("i32") >= 0 ? "dataInt32" : "data";
      return `
        v = uv.${uboElement.data.name};
        offset += ${offsetToAdd};

        arrayOffset = offset;

        t = 0;

        for(var i=0; i < ${uboElement.data.size * rowSize}; i++)
        {
            for(var j = 0; j < ${elementSize}; j++)
            {
                ${data}[arrayOffset++] = v[t++];
            }
            ${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
        }
    `;
    }

    "use strict";
    function createUboSyncFunctionSTD40(uboElements) {
      return createUboSyncFunction(
        uboElements,
        "uboStd40",
        generateArraySyncSTD40,
        uboSyncFunctionsSTD40
      );
    }

    "use strict";
    class GlUboSystem extends UboSystem {
      constructor() {
        super({
          createUboElements: createUboElementsSTD40,
          generateUboSync: createUboSyncFunctionSTD40
        });
      }
    }
    /** @ignore */
    GlUboSystem.extension = {
      type: [ExtensionType.WebGLSystem],
      name: "ubo"
    };

    "use strict";
    class GlRenderTargetAdaptor {
      constructor() {
        this._clearColorCache = [0, 0, 0, 0];
        this._viewPortCache = new Rectangle();
      }
      init(renderer, renderTargetSystem) {
        this._renderer = renderer;
        this._renderTargetSystem = renderTargetSystem;
        renderer.runners.contextChange.add(this);
      }
      contextChange() {
        this._clearColorCache = [0, 0, 0, 0];
        this._viewPortCache = new Rectangle();
        const gl = this._renderer.gl;
        this._drawBuffersCache = [];
        for (let i = 1; i <= 16; i++) {
          this._drawBuffersCache[i] = Array.from({ length: i }, (_, j) => gl.COLOR_ATTACHMENT0 + j);
        }
      }
      copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
        const renderTargetSystem = this._renderTargetSystem;
        const renderer = this._renderer;
        const glRenderTarget = renderTargetSystem.getGpuRenderTarget(sourceRenderSurfaceTexture);
        const gl = renderer.gl;
        this.finishRenderPass(sourceRenderSurfaceTexture);
        gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer);
        renderer.texture.bind(destinationTexture, 0);
        gl.copyTexSubImage2D(
          gl.TEXTURE_2D,
          0,
          originDest.x,
          originDest.y,
          originSrc.x,
          originSrc.y,
          size.width,
          size.height
        );
        return destinationTexture;
      }
      startRenderPass(renderTarget, clear = true, clearColor, viewport) {
        const renderTargetSystem = this._renderTargetSystem;
        const source = renderTarget.colorTexture;
        const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
        let viewPortY = viewport.y;
        if (renderTarget.isRoot) {
          viewPortY = source.pixelHeight - viewport.height - viewport.y;
        }
        renderTarget.colorTextures.forEach((texture) => {
          this._renderer.texture.unbind(texture);
        });
        const gl = this._renderer.gl;
        gl.bindFramebuffer(gl.FRAMEBUFFER, gpuRenderTarget.framebuffer);
        if (renderTarget.colorTextures.length > 1) {
          this._setDrawBuffers(renderTarget, gl);
        }
        const viewPortCache = this._viewPortCache;
        if (viewPortCache.x !== viewport.x || viewPortCache.y !== viewPortY || viewPortCache.width !== viewport.width || viewPortCache.height !== viewport.height) {
          viewPortCache.x = viewport.x;
          viewPortCache.y = viewPortY;
          viewPortCache.width = viewport.width;
          viewPortCache.height = viewport.height;
          gl.viewport(
            viewport.x,
            viewPortY,
            viewport.width,
            viewport.height
          );
        }
        if (!gpuRenderTarget.depthStencilRenderBuffer && (renderTarget.stencil || renderTarget.depth)) {
          this._initStencil(gpuRenderTarget);
        }
        this.clear(renderTarget, clear, clearColor);
      }
      finishRenderPass(renderTarget) {
        const renderTargetSystem = this._renderTargetSystem;
        const glRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
        if (!glRenderTarget.msaa)
          return;
        const gl = this._renderer.gl;
        gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer);
        gl.bindFramebuffer(gl.READ_FRAMEBUFFER, glRenderTarget.framebuffer);
        gl.blitFramebuffer(
          0,
          0,
          glRenderTarget.width,
          glRenderTarget.height,
          0,
          0,
          glRenderTarget.width,
          glRenderTarget.height,
          gl.COLOR_BUFFER_BIT,
          gl.NEAREST
        );
        gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.framebuffer);
      }
      initGpuRenderTarget(renderTarget) {
        const renderer = this._renderer;
        const gl = renderer.gl;
        const glRenderTarget = new GlRenderTarget();
        const colorTexture = renderTarget.colorTexture;
        if (colorTexture instanceof CanvasSource) {
          this._renderer.context.ensureCanvasSize(renderTarget.colorTexture.resource);
          glRenderTarget.framebuffer = null;
          return glRenderTarget;
        }
        this._initColor(renderTarget, glRenderTarget);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        return glRenderTarget;
      }
      destroyGpuRenderTarget(gpuRenderTarget) {
        const gl = this._renderer.gl;
        if (gpuRenderTarget.framebuffer) {
          gl.deleteFramebuffer(gpuRenderTarget.framebuffer);
          gpuRenderTarget.framebuffer = null;
        }
        if (gpuRenderTarget.resolveTargetFramebuffer) {
          gl.deleteFramebuffer(gpuRenderTarget.resolveTargetFramebuffer);
          gpuRenderTarget.resolveTargetFramebuffer = null;
        }
        if (gpuRenderTarget.depthStencilRenderBuffer) {
          gl.deleteRenderbuffer(gpuRenderTarget.depthStencilRenderBuffer);
          gpuRenderTarget.depthStencilRenderBuffer = null;
        }
        gpuRenderTarget.msaaRenderBuffer.forEach((renderBuffer) => {
          gl.deleteRenderbuffer(renderBuffer);
        });
        gpuRenderTarget.msaaRenderBuffer = null;
      }
      clear(_renderTarget, clear, clearColor) {
        if (!clear)
          return;
        const renderTargetSystem = this._renderTargetSystem;
        if (typeof clear === "boolean") {
          clear = clear ? CLEAR.ALL : CLEAR.NONE;
        }
        const gl = this._renderer.gl;
        if (clear & CLEAR.COLOR) {
          clearColor != null ? clearColor : clearColor = renderTargetSystem.defaultClearColor;
          const clearColorCache = this._clearColorCache;
          const clearColorArray = clearColor;
          if (clearColorCache[0] !== clearColorArray[0] || clearColorCache[1] !== clearColorArray[1] || clearColorCache[2] !== clearColorArray[2] || clearColorCache[3] !== clearColorArray[3]) {
            clearColorCache[0] = clearColorArray[0];
            clearColorCache[1] = clearColorArray[1];
            clearColorCache[2] = clearColorArray[2];
            clearColorCache[3] = clearColorArray[3];
            gl.clearColor(clearColorArray[0], clearColorArray[1], clearColorArray[2], clearColorArray[3]);
          }
        }
        gl.clear(clear);
      }
      resizeGpuRenderTarget(renderTarget) {
        if (renderTarget.isRoot)
          return;
        const renderTargetSystem = this._renderTargetSystem;
        const glRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
        this._resizeColor(renderTarget, glRenderTarget);
        if (renderTarget.stencil || renderTarget.depth) {
          this._resizeStencil(glRenderTarget);
        }
      }
      _initColor(renderTarget, glRenderTarget) {
        const renderer = this._renderer;
        const gl = renderer.gl;
        const resolveTargetFramebuffer = gl.createFramebuffer();
        glRenderTarget.resolveTargetFramebuffer = resolveTargetFramebuffer;
        gl.bindFramebuffer(gl.FRAMEBUFFER, resolveTargetFramebuffer);
        glRenderTarget.width = renderTarget.colorTexture.source.pixelWidth;
        glRenderTarget.height = renderTarget.colorTexture.source.pixelHeight;
        const colorTextures = renderTarget.colorTextures;
        colorTextures.forEach((colorTexture, i) => {
          const source = colorTexture.source;
          if (source.antialias) {
            if (renderer.context.supports.msaa) {
              glRenderTarget.msaa = true;
            } else {
              warn("[RenderTexture] Antialiasing on textures is not supported in WebGL1");
            }
          }
          renderer.texture.bindSource(source, 0);
          const glSource = renderer.texture.getGlSource(source);
          const glTexture = glSource.texture;
          gl.framebufferTexture2D(
            gl.FRAMEBUFFER,
            gl.COLOR_ATTACHMENT0 + i,
            3553,
            // texture.target,
            glTexture,
            0
          );
        });
        if (glRenderTarget.msaa) {
          const viewFramebuffer = gl.createFramebuffer();
          glRenderTarget.framebuffer = viewFramebuffer;
          gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer);
          renderTarget.colorTextures.forEach((_, i) => {
            const msaaRenderBuffer = gl.createRenderbuffer();
            glRenderTarget.msaaRenderBuffer[i] = msaaRenderBuffer;
          });
        } else {
          glRenderTarget.framebuffer = resolveTargetFramebuffer;
        }
        this._resizeColor(renderTarget, glRenderTarget);
      }
      _resizeColor(renderTarget, glRenderTarget) {
        const source = renderTarget.colorTexture.source;
        glRenderTarget.width = source.pixelWidth;
        glRenderTarget.height = source.pixelHeight;
        renderTarget.colorTextures.forEach((colorTexture, i) => {
          if (i === 0)
            return;
          colorTexture.source.resize(source.width, source.height, source._resolution);
        });
        if (glRenderTarget.msaa) {
          const renderer = this._renderer;
          const gl = renderer.gl;
          const viewFramebuffer = glRenderTarget.framebuffer;
          gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer);
          renderTarget.colorTextures.forEach((colorTexture, i) => {
            const source2 = colorTexture.source;
            renderer.texture.bindSource(source2, 0);
            const glSource = renderer.texture.getGlSource(source2);
            const glInternalFormat = glSource.internalFormat;
            const msaaRenderBuffer = glRenderTarget.msaaRenderBuffer[i];
            gl.bindRenderbuffer(
              gl.RENDERBUFFER,
              msaaRenderBuffer
            );
            gl.renderbufferStorageMultisample(
              gl.RENDERBUFFER,
              4,
              glInternalFormat,
              source2.pixelWidth,
              source2.pixelHeight
            );
            gl.framebufferRenderbuffer(
              gl.FRAMEBUFFER,
              gl.COLOR_ATTACHMENT0 + i,
              gl.RENDERBUFFER,
              msaaRenderBuffer
            );
          });
        }
      }
      _initStencil(glRenderTarget) {
        if (glRenderTarget.framebuffer === null)
          return;
        const gl = this._renderer.gl;
        const depthStencilRenderBuffer = gl.createRenderbuffer();
        glRenderTarget.depthStencilRenderBuffer = depthStencilRenderBuffer;
        gl.bindRenderbuffer(
          gl.RENDERBUFFER,
          depthStencilRenderBuffer
        );
        gl.framebufferRenderbuffer(
          gl.FRAMEBUFFER,
          gl.DEPTH_STENCIL_ATTACHMENT,
          gl.RENDERBUFFER,
          depthStencilRenderBuffer
        );
        this._resizeStencil(glRenderTarget);
      }
      _resizeStencil(glRenderTarget) {
        const gl = this._renderer.gl;
        gl.bindRenderbuffer(
          gl.RENDERBUFFER,
          glRenderTarget.depthStencilRenderBuffer
        );
        if (glRenderTarget.msaa) {
          gl.renderbufferStorageMultisample(
            gl.RENDERBUFFER,
            4,
            gl.DEPTH24_STENCIL8,
            glRenderTarget.width,
            glRenderTarget.height
          );
        } else {
          gl.renderbufferStorage(
            gl.RENDERBUFFER,
            this._renderer.context.webGLVersion === 2 ? gl.DEPTH24_STENCIL8 : gl.DEPTH_STENCIL,
            glRenderTarget.width,
            glRenderTarget.height
          );
        }
      }
      prerender(renderTarget) {
        const resource = renderTarget.colorTexture.resource;
        if (this._renderer.context.multiView && CanvasSource.test(resource)) {
          this._renderer.context.ensureCanvasSize(resource);
        }
      }
      postrender(renderTarget) {
        if (!this._renderer.context.multiView)
          return;
        if (CanvasSource.test(renderTarget.colorTexture.resource)) {
          const contextCanvas = this._renderer.context.canvas;
          const canvasSource = renderTarget.colorTexture;
          canvasSource.context2D.drawImage(
            contextCanvas,
            0,
            canvasSource.pixelHeight - contextCanvas.height
          );
        }
      }
      _setDrawBuffers(renderTarget, gl) {
        const count = renderTarget.colorTextures.length;
        const bufferArray = this._drawBuffersCache[count];
        if (this._renderer.context.webGLVersion === 1) {
          const ext = this._renderer.context.extensions.drawBuffers;
          if (!ext) {
            warn("[RenderTexture] This WebGL1 context does not support rendering to multiple targets");
          } else {
            ext.drawBuffersWEBGL(bufferArray);
          }
        } else {
          gl.drawBuffers(bufferArray);
        }
      }
    }

    "use strict";
    function calculateProjection(pm, x, y, width, height, flipY) {
      const sign = flipY ? 1 : -1;
      pm.identity();
      pm.a = 1 / width * 2;
      pm.d = sign * (1 / height * 2);
      pm.tx = -1 - x * pm.a;
      pm.ty = -sign - y * pm.d;
      return pm;
    }

    "use strict";
    var __defProp$n = Object.defineProperty;
    var __getOwnPropSymbols$p = Object.getOwnPropertySymbols;
    var __hasOwnProp$p = Object.prototype.hasOwnProperty;
    var __propIsEnum$p = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$n = (obj, key, value) => key in obj ? __defProp$n(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$n = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$p.call(b, prop))
          __defNormalProp$n(a, prop, b[prop]);
      if (__getOwnPropSymbols$p)
        for (var prop of __getOwnPropSymbols$p(b)) {
          if (__propIsEnum$p.call(b, prop))
            __defNormalProp$n(a, prop, b[prop]);
        }
      return a;
    };
    const canvasCache = /* @__PURE__ */ new Map();
    GlobalResourceRegistry.register(canvasCache);
    function getCanvasTexture(canvas, options) {
      if (!canvasCache.has(canvas)) {
        const texture = new Texture({
          source: new CanvasSource(__spreadValues$n({
            resource: canvas
          }, options))
        });
        const onDestroy = () => {
          if (canvasCache.get(canvas) === texture) {
            canvasCache.delete(canvas);
          }
        };
        texture.once("destroy", onDestroy);
        texture.source.once("destroy", onDestroy);
        canvasCache.set(canvas, texture);
      }
      return canvasCache.get(canvas);
    }
    function hasCachedCanvasTexture(canvas) {
      return canvasCache.has(canvas);
    }

    "use strict";
    function isRenderingToScreen(renderTarget) {
      const resource = renderTarget.colorTexture.source.resource;
      return globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement && document.body.contains(resource);
    }

    "use strict";
    var __defProp$m = Object.defineProperty;
    var __getOwnPropSymbols$o = Object.getOwnPropertySymbols;
    var __hasOwnProp$o = Object.prototype.hasOwnProperty;
    var __propIsEnum$o = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$m = (obj, key, value) => key in obj ? __defProp$m(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$m = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$o.call(b, prop))
          __defNormalProp$m(a, prop, b[prop]);
      if (__getOwnPropSymbols$o)
        for (var prop of __getOwnPropSymbols$o(b)) {
          if (__propIsEnum$o.call(b, prop))
            __defNormalProp$m(a, prop, b[prop]);
        }
      return a;
    };
    const _RenderTarget = class _RenderTarget {
      /**
       * @param [descriptor] - Options for creating a render target.
       */
      constructor(descriptor = {}) {
        /** unique id for this render target */
        this.uid = uid$1("renderTarget");
        /**
         * An array of textures that can be written to by the GPU - mostly this has one texture in Pixi, but you could
         * write to multiple if required! (eg deferred lighting)
         */
        this.colorTextures = [];
        this.dirtyId = 0;
        this.isRoot = false;
        this._size = new Float32Array(2);
        /** if true, then when the render target is destroyed, it will destroy all the textures that were created for it. */
        this._managedColorTextures = false;
        descriptor = __spreadValues$m(__spreadValues$m({}, _RenderTarget.defaultOptions), descriptor);
        this.stencil = descriptor.stencil;
        this.depth = descriptor.depth;
        this.isRoot = descriptor.isRoot;
        if (typeof descriptor.colorTextures === "number") {
          this._managedColorTextures = true;
          for (let i = 0; i < descriptor.colorTextures; i++) {
            this.colorTextures.push(
              new TextureSource({
                width: descriptor.width,
                height: descriptor.height,
                resolution: descriptor.resolution,
                antialias: descriptor.antialias
              })
            );
          }
        } else {
          this.colorTextures = [...descriptor.colorTextures.map((texture) => texture.source)];
          const colorSource = this.colorTexture.source;
          this.resize(colorSource.width, colorSource.height, colorSource._resolution);
        }
        this.colorTexture.source.on("resize", this.onSourceResize, this);
        if (descriptor.depthStencilTexture || this.stencil) {
          if (descriptor.depthStencilTexture instanceof Texture || descriptor.depthStencilTexture instanceof TextureSource) {
            this.depthStencilTexture = descriptor.depthStencilTexture.source;
          } else {
            this.ensureDepthStencilTexture();
          }
        }
      }
      get size() {
        const _size = this._size;
        _size[0] = this.pixelWidth;
        _size[1] = this.pixelHeight;
        return _size;
      }
      get width() {
        return this.colorTexture.source.width;
      }
      get height() {
        return this.colorTexture.source.height;
      }
      get pixelWidth() {
        return this.colorTexture.source.pixelWidth;
      }
      get pixelHeight() {
        return this.colorTexture.source.pixelHeight;
      }
      get resolution() {
        return this.colorTexture.source._resolution;
      }
      get colorTexture() {
        return this.colorTextures[0];
      }
      onSourceResize(source) {
        this.resize(source.width, source.height, source._resolution, true);
      }
      /**
       * This will ensure a depthStencil texture is created for this render target.
       * Most likely called by the mask system to make sure we have stencil buffer added.
       * @internal
       */
      ensureDepthStencilTexture() {
        if (!this.depthStencilTexture) {
          this.depthStencilTexture = new TextureSource({
            width: this.width,
            height: this.height,
            resolution: this.resolution,
            format: "depth24plus-stencil8",
            autoGenerateMipmaps: false,
            antialias: false,
            mipLevelCount: 1
            // sampleCount: handled by the render target system..
          });
        }
      }
      resize(width, height, resolution = this.resolution, skipColorTexture = false) {
        this.dirtyId++;
        this.colorTextures.forEach((colorTexture, i) => {
          if (skipColorTexture && i === 0)
            return;
          colorTexture.source.resize(width, height, resolution);
        });
        if (this.depthStencilTexture) {
          this.depthStencilTexture.source.resize(width, height, resolution);
        }
      }
      destroy() {
        this.colorTexture.source.off("resize", this.onSourceResize, this);
        if (this._managedColorTextures) {
          this.colorTextures.forEach((texture) => {
            texture.destroy();
          });
        }
        if (this.depthStencilTexture) {
          this.depthStencilTexture.destroy();
          delete this.depthStencilTexture;
        }
      }
    };
    /** The default options for a render target */
    _RenderTarget.defaultOptions = {
      /** the width of the RenderTarget */
      width: 0,
      /** the height of the RenderTarget */
      height: 0,
      /** the resolution of the RenderTarget */
      resolution: 1,
      /** an array of textures, or a number indicating how many color textures there should be */
      colorTextures: 1,
      /** should this render target have a stencil buffer? */
      stencil: false,
      /** should this render target have a depth buffer? */
      depth: false,
      /** should this render target be antialiased? */
      antialias: false,
      // save on perf by default!
      /** is this a root element, true if this is gl context owners render target */
      isRoot: false
    };
    let RenderTarget = _RenderTarget;

    "use strict";
    class RenderTargetSystem {
      constructor(renderer) {
        /** This is the root viewport for the render pass*/
        this.rootViewPort = new Rectangle();
        /** the current viewport that the gpu is using */
        this.viewport = new Rectangle();
        /**
         * a runner that lets systems know if the active render target has changed.
         * Eg the Stencil System needs to know so it can manage the stencil buffer
         */
        this.onRenderTargetChange = new SystemRunner("onRenderTargetChange");
        /** the projection matrix that is used by the shaders based on the active render target and the viewport */
        this.projectionMatrix = new Matrix();
        /** the default clear color for render targets */
        this.defaultClearColor = [0, 0, 0, 0];
        /**
         * a hash that stores the render target for a given render surface. When you pass in a texture source,
         * a render target is created for it. This map stores and makes it easy to retrieve the render target
         */
        this._renderSurfaceToRenderTargetHash = /* @__PURE__ */ new Map();
        /** A hash that stores a gpu render target for a given render target. */
        this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
        /**
         * A stack that stores the render target and frame that is currently being rendered to.
         * When push is called, the current render target is stored in this stack.
         * When pop is called, the previous render target is restored.
         */
        this._renderTargetStack = [];
        this._renderer = renderer;
        renderer.renderableGC.addManagedHash(this, "_gpuRenderTargetHash");
      }
      /** called when dev wants to finish a render pass */
      finishRenderPass() {
        this.adaptor.finishRenderPass(this.renderTarget);
      }
      /**
       * called when the renderer starts to render a scene.
       * @param options
       * @param options.target - the render target to render to
       * @param options.clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
       * @param options.clearColor - the color to clear to
       * @param options.frame - the frame to render to
       */
      renderStart({
        target,
        clear,
        clearColor,
        frame
      }) {
        var _a, _b;
        this._renderTargetStack.length = 0;
        this.push(
          target,
          clear,
          clearColor,
          frame
        );
        this.rootViewPort.copyFrom(this.viewport);
        this.rootRenderTarget = this.renderTarget;
        this.renderingToScreen = isRenderingToScreen(this.rootRenderTarget);
        (_b = (_a = this.adaptor).prerender) == null ? void 0 : _b.call(_a, this.rootRenderTarget);
      }
      postrender() {
        var _a, _b;
        (_b = (_a = this.adaptor).postrender) == null ? void 0 : _b.call(_a, this.rootRenderTarget);
      }
      /**
       * Binding a render surface! This is the main function of the render target system.
       * It will take the RenderSurface (which can be a texture, canvas, or render target) and bind it to the renderer.
       * Once bound all draw calls will be rendered to the render surface.
       *
       * If a frame is not provide and the render surface is a texture, the frame of the texture will be used.
       * @param renderSurface - the render surface to bind
       * @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
       * @param clearColor - the color to clear to
       * @param frame - the frame to render to
       * @returns the render target that was bound
       */
      bind(renderSurface, clear = true, clearColor, frame) {
        const renderTarget = this.getRenderTarget(renderSurface);
        const didChange = this.renderTarget !== renderTarget;
        this.renderTarget = renderTarget;
        this.renderSurface = renderSurface;
        const gpuRenderTarget = this.getGpuRenderTarget(renderTarget);
        if (renderTarget.pixelWidth !== gpuRenderTarget.width || renderTarget.pixelHeight !== gpuRenderTarget.height) {
          this.adaptor.resizeGpuRenderTarget(renderTarget);
          gpuRenderTarget.width = renderTarget.pixelWidth;
          gpuRenderTarget.height = renderTarget.pixelHeight;
        }
        const source = renderTarget.colorTexture;
        const viewport = this.viewport;
        const pixelWidth = source.pixelWidth;
        const pixelHeight = source.pixelHeight;
        if (!frame && renderSurface instanceof Texture) {
          frame = renderSurface.frame;
        }
        if (frame) {
          const resolution = source._resolution;
          viewport.x = frame.x * resolution + 0.5 | 0;
          viewport.y = frame.y * resolution + 0.5 | 0;
          viewport.width = frame.width * resolution + 0.5 | 0;
          viewport.height = frame.height * resolution + 0.5 | 0;
        } else {
          viewport.x = 0;
          viewport.y = 0;
          viewport.width = pixelWidth;
          viewport.height = pixelHeight;
        }
        calculateProjection(
          this.projectionMatrix,
          0,
          0,
          viewport.width / source.resolution,
          viewport.height / source.resolution,
          !renderTarget.isRoot
        );
        this.adaptor.startRenderPass(renderTarget, clear, clearColor, viewport);
        if (didChange) {
          this.onRenderTargetChange.emit(renderTarget);
        }
        return renderTarget;
      }
      clear(target, clear = CLEAR.ALL, clearColor) {
        if (!clear)
          return;
        if (target) {
          target = this.getRenderTarget(target);
        }
        this.adaptor.clear(
          target || this.renderTarget,
          clear,
          clearColor,
          this.viewport
        );
      }
      contextChange() {
        this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
      }
      /**
       * Push a render surface to the renderer. This will bind the render surface to the renderer,
       * @param renderSurface - the render surface to push
       * @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
       * @param clearColor - the color to clear to
       * @param frame - the frame to use when rendering to the render surface
       */
      push(renderSurface, clear = CLEAR.ALL, clearColor, frame) {
        const renderTarget = this.bind(renderSurface, clear, clearColor, frame);
        this._renderTargetStack.push({
          renderTarget,
          frame
        });
        return renderTarget;
      }
      /** Pops the current render target from the renderer and restores the previous render target. */
      pop() {
        this._renderTargetStack.pop();
        const currentRenderTargetData = this._renderTargetStack[this._renderTargetStack.length - 1];
        this.bind(currentRenderTargetData.renderTarget, false, null, currentRenderTargetData.frame);
      }
      /**
       * Gets the render target from the provide render surface. Eg if its a texture,
       * it will return the render target for the texture.
       * If its a render target, it will return the same render target.
       * @param renderSurface - the render surface to get the render target for
       * @returns the render target for the render surface
       */
      getRenderTarget(renderSurface) {
        var _a;
        if (renderSurface.isTexture) {
          renderSurface = renderSurface.source;
        }
        return (_a = this._renderSurfaceToRenderTargetHash.get(renderSurface)) != null ? _a : this._initRenderTarget(renderSurface);
      }
      /**
       * Copies a render surface to another texture.
       *
       * NOTE:
       * for sourceRenderSurfaceTexture, The render target must be something that is written too by the renderer
       *
       * The following is not valid:
       * @example
       * const canvas = document.createElement('canvas')
       * canvas.width = 200;
       * canvas.height = 200;
       *
       * const ctx = canvas2.getContext('2d')!
       * ctx.fillStyle = 'red'
       * ctx.fillRect(0, 0, 200, 200);
       *
       * const texture = RenderTexture.create({
       *   width: 200,
       *   height: 200,
       * })
       * const renderTarget = renderer.renderTarget.getRenderTarget(canvas2);
       *
       * renderer.renderTarget.copyToTexture(renderTarget,texture, {x:0,y:0},{width:200,height:200},{x:0,y:0});
       *
       * The best way to copy a canvas is to create a texture from it. Then render with that.
       *
       * Parsing in a RenderTarget canvas context (with a 2d context)
       * @param sourceRenderSurfaceTexture - the render surface to copy from
       * @param destinationTexture - the texture to copy to
       * @param originSrc - the origin of the copy
       * @param originSrc.x - the x origin of the copy
       * @param originSrc.y - the y origin of the copy
       * @param size - the size of the copy
       * @param size.width - the width of the copy
       * @param size.height - the height of the copy
       * @param originDest - the destination origin (top left to paste from!)
       * @param originDest.x - the x origin of the paste
       * @param originDest.y - the y origin of the paste
       */
      copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
        if (originSrc.x < 0) {
          size.width += originSrc.x;
          originDest.x -= originSrc.x;
          originSrc.x = 0;
        }
        if (originSrc.y < 0) {
          size.height += originSrc.y;
          originDest.y -= originSrc.y;
          originSrc.y = 0;
        }
        const { pixelWidth, pixelHeight } = sourceRenderSurfaceTexture;
        size.width = Math.min(size.width, pixelWidth - originSrc.x);
        size.height = Math.min(size.height, pixelHeight - originSrc.y);
        return this.adaptor.copyToTexture(
          sourceRenderSurfaceTexture,
          destinationTexture,
          originSrc,
          size,
          originDest
        );
      }
      /**
       * ensures that we have a depth stencil buffer available to render to
       * This is used by the mask system to make sure we have a stencil buffer.
       */
      ensureDepthStencil() {
        if (!this.renderTarget.stencil) {
          this.renderTarget.stencil = true;
          this.adaptor.startRenderPass(this.renderTarget, false, null, this.viewport);
        }
      }
      /** nukes the render target system */
      destroy() {
        this._renderer = null;
        this._renderSurfaceToRenderTargetHash.forEach((renderTarget, key) => {
          if (renderTarget !== key) {
            renderTarget.destroy();
          }
        });
        this._renderSurfaceToRenderTargetHash.clear();
        this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
      }
      _initRenderTarget(renderSurface) {
        let renderTarget = null;
        if (CanvasSource.test(renderSurface)) {
          renderSurface = getCanvasTexture(renderSurface).source;
        }
        if (renderSurface instanceof RenderTarget) {
          renderTarget = renderSurface;
        } else if (renderSurface instanceof TextureSource) {
          renderTarget = new RenderTarget({
            colorTextures: [renderSurface]
          });
          if (renderSurface.source instanceof CanvasSource) {
            renderTarget.isRoot = true;
          }
          renderSurface.once("destroy", () => {
            renderTarget.destroy();
            this._renderSurfaceToRenderTargetHash.delete(renderSurface);
            const gpuRenderTarget = this._gpuRenderTargetHash[renderTarget.uid];
            if (gpuRenderTarget) {
              this._gpuRenderTargetHash[renderTarget.uid] = null;
              this.adaptor.destroyGpuRenderTarget(gpuRenderTarget);
            }
          });
        }
        this._renderSurfaceToRenderTargetHash.set(renderSurface, renderTarget);
        return renderTarget;
      }
      getGpuRenderTarget(renderTarget) {
        return this._gpuRenderTargetHash[renderTarget.uid] || (this._gpuRenderTargetHash[renderTarget.uid] = this.adaptor.initGpuRenderTarget(renderTarget));
      }
      resetState() {
        this.renderTarget = null;
        this.renderSurface = null;
      }
    }

    "use strict";
    class GlRenderTargetSystem extends RenderTargetSystem {
      constructor(renderer) {
        super(renderer);
        this.adaptor = new GlRenderTargetAdaptor();
        this.adaptor.init(renderer, this);
      }
    }
    /** @ignore */
    GlRenderTargetSystem.extension = {
      type: [ExtensionType.WebGLSystem],
      name: "renderTarget"
    };

    "use strict";

    "use strict";
    class BufferResource extends EventEmitter {
      /**
       * Create a new Buffer Resource.
       * @param options - The options for the buffer resource
       * @param options.buffer - The underlying buffer that this resource is using
       * @param options.offset - The offset of the buffer this resource is using.
       * If not provided, then it will use the offset of the buffer.
       * @param options.size - The size of the buffer this resource is using.
       * If not provided, then it will use the size of the buffer.
       */
      constructor({ buffer, offset, size }) {
        super();
        /**
         * emits when the underlying buffer has changed shape (i.e. resized)
         * letting the renderer know that it needs to discard the old buffer on the GPU and create a new one
         * @event change
         */
        /** a unique id for this uniform group used through the renderer */
        this.uid = uid$1("buffer");
        /**
         * a resource type, used to identify how to handle it when its in a bind group / shader resource
         * @internal
         */
        this._resourceType = "bufferResource";
        /**
         * used internally to know if a uniform group was used in the last render pass
         * @internal
         */
        this._touched = 0;
        /**
         * the resource id used internally by the renderer to build bind group keys
         * @internal
         */
        this._resourceId = uid$1("resource");
        /**
         * A cheeky hint to the GL renderer to let it know this is a BufferResource
         * @internal
         */
        this._bufferResource = true;
        /**
         * Has the Buffer resource been destroyed?
         * @readonly
         */
        this.destroyed = false;
        this.buffer = buffer;
        this.offset = offset | 0;
        this.size = size;
        this.buffer.on("change", this.onBufferChange, this);
      }
      onBufferChange() {
        this._resourceId = uid$1("resource");
        this.emit("change", this);
      }
      /**
       * Destroys this resource. Make sure the underlying buffer is not used anywhere else
       * if you want to destroy it as well, or code will explode
       * @param destroyBuffer - Should the underlying buffer be destroyed as well?
       */
      destroy(destroyBuffer = false) {
        this.destroyed = true;
        if (destroyBuffer) {
          this.buffer.destroy();
        }
        this.emit("change", this);
        this.buffer = null;
        this.removeAllListeners();
      }
    }

    "use strict";
    function generateShaderSyncCode(shader, shaderSystem) {
      const funcFragments = [];
      const headerFragments = [`
        var g = s.groups;
        var sS = r.shader;
        var p = s.glProgram;
        var ugS = r.uniformGroup;
        var resources;
    `];
      let addedTextreSystem = false;
      let textureCount = 0;
      const programData = shaderSystem._getProgramData(shader.glProgram);
      for (const i in shader.groups) {
        const group = shader.groups[i];
        funcFragments.push(`
            resources = g[${i}].resources;
        `);
        for (const j in group.resources) {
          const resource = group.resources[j];
          if (resource instanceof UniformGroup) {
            if (resource.ubo) {
              const resName = shader._uniformBindMap[i][Number(j)];
              funcFragments.push(`
                        sS.bindUniformBlock(
                            resources[${j}],
                            '${resName}',
                            ${shader.glProgram._uniformBlockData[resName].index}
                        );
                    `);
            } else {
              funcFragments.push(`
                        ugS.updateUniformGroup(resources[${j}], p, sD);
                    `);
            }
          } else if (resource instanceof BufferResource) {
            const resName = shader._uniformBindMap[i][Number(j)];
            funcFragments.push(`
                    sS.bindUniformBlock(
                        resources[${j}],
                        '${resName}',
                        ${shader.glProgram._uniformBlockData[resName].index}
                    );
                `);
          } else if (resource instanceof TextureSource) {
            const uniformName = shader._uniformBindMap[i][j];
            const uniformData = programData.uniformData[uniformName];
            if (uniformData) {
              if (!addedTextreSystem) {
                addedTextreSystem = true;
                headerFragments.push(`
                        var tS = r.texture;
                        `);
              }
              shaderSystem._gl.uniform1i(uniformData.location, textureCount);
              funcFragments.push(`
                        tS.bind(resources[${j}], ${textureCount});
                    `);
              textureCount++;
            }
          }
        }
      }
      const functionSource = [...headerFragments, ...funcFragments].join("\n");
      return new Function("r", "s", "sD", functionSource);
    }

    "use strict";
    class IGLUniformData {
    }
    class GlProgramData {
      /**
       * Makes a new Pixi program.
       * @param program - webgl program
       * @param uniformData - uniforms
       */
      constructor(program, uniformData) {
        this.program = program;
        this.uniformData = uniformData;
        this.uniformGroups = {};
        this.uniformDirtyGroups = {};
        this.uniformBlockBindings = {};
      }
      /** Destroys this program. */
      destroy() {
        this.uniformData = null;
        this.uniformGroups = null;
        this.uniformDirtyGroups = null;
        this.uniformBlockBindings = null;
        this.program = null;
      }
    }

    "use strict";
    function compileShader(gl, type, src) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, src);
      gl.compileShader(shader);
      return shader;
    }

    "use strict";
    function booleanArray(size) {
      const array = new Array(size);
      for (let i = 0; i < array.length; i++) {
        array[i] = false;
      }
      return array;
    }
    function defaultValue(type, size) {
      switch (type) {
        case "float":
          return 0;
        case "vec2":
          return new Float32Array(2 * size);
        case "vec3":
          return new Float32Array(3 * size);
        case "vec4":
          return new Float32Array(4 * size);
        case "int":
        case "uint":
        case "sampler2D":
        case "sampler2DArray":
          return 0;
        case "ivec2":
          return new Int32Array(2 * size);
        case "ivec3":
          return new Int32Array(3 * size);
        case "ivec4":
          return new Int32Array(4 * size);
        case "uvec2":
          return new Uint32Array(2 * size);
        case "uvec3":
          return new Uint32Array(3 * size);
        case "uvec4":
          return new Uint32Array(4 * size);
        case "bool":
          return false;
        case "bvec2":
          return booleanArray(2 * size);
        case "bvec3":
          return booleanArray(3 * size);
        case "bvec4":
          return booleanArray(4 * size);
        case "mat2":
          return new Float32Array([
            1,
            0,
            0,
            1
          ]);
        case "mat3":
          return new Float32Array([
            1,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            1
          ]);
        case "mat4":
          return new Float32Array([
            1,
            0,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            0,
            1
          ]);
      }
      return null;
    }

    "use strict";
    let GL_TABLE = null;
    const GL_TO_GLSL_TYPES = {
      FLOAT: "float",
      FLOAT_VEC2: "vec2",
      FLOAT_VEC3: "vec3",
      FLOAT_VEC4: "vec4",
      INT: "int",
      INT_VEC2: "ivec2",
      INT_VEC3: "ivec3",
      INT_VEC4: "ivec4",
      UNSIGNED_INT: "uint",
      UNSIGNED_INT_VEC2: "uvec2",
      UNSIGNED_INT_VEC3: "uvec3",
      UNSIGNED_INT_VEC4: "uvec4",
      BOOL: "bool",
      BOOL_VEC2: "bvec2",
      BOOL_VEC3: "bvec3",
      BOOL_VEC4: "bvec4",
      FLOAT_MAT2: "mat2",
      FLOAT_MAT3: "mat3",
      FLOAT_MAT4: "mat4",
      SAMPLER_2D: "sampler2D",
      INT_SAMPLER_2D: "sampler2D",
      UNSIGNED_INT_SAMPLER_2D: "sampler2D",
      SAMPLER_CUBE: "samplerCube",
      INT_SAMPLER_CUBE: "samplerCube",
      UNSIGNED_INT_SAMPLER_CUBE: "samplerCube",
      SAMPLER_2D_ARRAY: "sampler2DArray",
      INT_SAMPLER_2D_ARRAY: "sampler2DArray",
      UNSIGNED_INT_SAMPLER_2D_ARRAY: "sampler2DArray"
    };
    const GLSL_TO_VERTEX_TYPES = {
      float: "float32",
      vec2: "float32x2",
      vec3: "float32x3",
      vec4: "float32x4",
      int: "sint32",
      ivec2: "sint32x2",
      ivec3: "sint32x3",
      ivec4: "sint32x4",
      uint: "uint32",
      uvec2: "uint32x2",
      uvec3: "uint32x3",
      uvec4: "uint32x4",
      bool: "uint32",
      bvec2: "uint32x2",
      bvec3: "uint32x3",
      bvec4: "uint32x4"
    };
    function mapType(gl, type) {
      if (!GL_TABLE) {
        const typeNames = Object.keys(GL_TO_GLSL_TYPES);
        GL_TABLE = {};
        for (let i = 0; i < typeNames.length; ++i) {
          const tn = typeNames[i];
          GL_TABLE[gl[tn]] = GL_TO_GLSL_TYPES[tn];
        }
      }
      return GL_TABLE[type];
    }
    function mapGlToVertexFormat(gl, type) {
      const typeValue = mapType(gl, type);
      return GLSL_TO_VERTEX_TYPES[typeValue] || "float32";
    }

    "use strict";
    function extractAttributesFromGlProgram(program, gl, sortAttributes = false) {
      const attributes = {};
      const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
      for (let i = 0; i < totalAttributes; i++) {
        const attribData = gl.getActiveAttrib(program, i);
        if (attribData.name.startsWith("gl_")) {
          continue;
        }
        const format = mapGlToVertexFormat(gl, attribData.type);
        attributes[attribData.name] = {
          location: 0,
          // set further down..
          format,
          stride: getAttributeInfoFromFormat(format).stride,
          offset: 0,
          instance: false,
          start: 0
        };
      }
      const keys = Object.keys(attributes);
      if (sortAttributes) {
        keys.sort((a, b) => a > b ? 1 : -1);
        for (let i = 0; i < keys.length; i++) {
          attributes[keys[i]].location = i;
          gl.bindAttribLocation(program, i, keys[i]);
        }
        gl.linkProgram(program);
      } else {
        for (let i = 0; i < keys.length; i++) {
          attributes[keys[i]].location = gl.getAttribLocation(program, keys[i]);
        }
      }
      return attributes;
    }

    "use strict";
    function getUboData(program, gl) {
      if (!gl.ACTIVE_UNIFORM_BLOCKS)
        return {};
      const uniformBlocks = {};
      const totalUniformsBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
      for (let i = 0; i < totalUniformsBlocks; i++) {
        const name = gl.getActiveUniformBlockName(program, i);
        const uniformBlockIndex = gl.getUniformBlockIndex(program, name);
        const size = gl.getActiveUniformBlockParameter(program, i, gl.UNIFORM_BLOCK_DATA_SIZE);
        uniformBlocks[name] = {
          name,
          index: uniformBlockIndex,
          size
        };
      }
      return uniformBlocks;
    }

    "use strict";
    function getUniformData(program, gl) {
      const uniforms = {};
      const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
      for (let i = 0; i < totalUniforms; i++) {
        const uniformData = gl.getActiveUniform(program, i);
        const name = uniformData.name.replace(/\[.*?\]$/, "");
        const isArray = !!uniformData.name.match(/\[.*?\]$/);
        const type = mapType(gl, uniformData.type);
        uniforms[name] = {
          name,
          index: i,
          type,
          size: uniformData.size,
          isArray,
          value: defaultValue(type, uniformData.size)
        };
      }
      return uniforms;
    }

    "use strict";
    function logPrettyShaderError(gl, shader) {
      const shaderSrc = gl.getShaderSource(shader).split("\n").map((line, index) => `${index}: ${line}`);
      const shaderLog = gl.getShaderInfoLog(shader);
      const splitShader = shaderLog.split("\n");
      const dedupe = {};
      const lineNumbers = splitShader.map((line) => parseFloat(line.replace(/^ERROR\: 0\:([\d]+)\:.*$/, "$1"))).filter((n) => {
        if (n && !dedupe[n]) {
          dedupe[n] = true;
          return true;
        }
        return false;
      });
      const logArgs = [""];
      lineNumbers.forEach((number) => {
        shaderSrc[number - 1] = `%c${shaderSrc[number - 1]}%c`;
        logArgs.push("background: #FF0000; color:#FFFFFF; font-size: 10px", "font-size: 10px");
      });
      const fragmentSourceToLog = shaderSrc.join("\n");
      logArgs[0] = fragmentSourceToLog;
      console.error(shaderLog);
      console.groupCollapsed("click to view full shader code");
      console.warn(...logArgs);
      console.groupEnd();
    }
    function logProgramError(gl, program, vertexShader, fragmentShader) {
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
          logPrettyShaderError(gl, vertexShader);
        }
        if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
          logPrettyShaderError(gl, fragmentShader);
        }
        console.error("PixiJS Error: Could not initialize shader.");
        if (gl.getProgramInfoLog(program) !== "") {
          console.warn("PixiJS Warning: gl.getProgramInfoLog()", gl.getProgramInfoLog(program));
        }
      }
    }

    "use strict";
    function generateProgram(gl, program) {
      const glVertShader = compileShader(gl, gl.VERTEX_SHADER, program.vertex);
      const glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, program.fragment);
      const webGLProgram = gl.createProgram();
      gl.attachShader(webGLProgram, glVertShader);
      gl.attachShader(webGLProgram, glFragShader);
      const transformFeedbackVaryings = program.transformFeedbackVaryings;
      if (transformFeedbackVaryings) {
        if (typeof gl.transformFeedbackVaryings !== "function") {
          warn(`TransformFeedback is not supported but TransformFeedbackVaryings are given.`);
        } else {
          gl.transformFeedbackVaryings(
            webGLProgram,
            transformFeedbackVaryings.names,
            transformFeedbackVaryings.bufferMode === "separate" ? gl.SEPARATE_ATTRIBS : gl.INTERLEAVED_ATTRIBS
          );
        }
      }
      gl.linkProgram(webGLProgram);
      if (!gl.getProgramParameter(webGLProgram, gl.LINK_STATUS)) {
        logProgramError(gl, webGLProgram, glVertShader, glFragShader);
      }
      program._attributeData = extractAttributesFromGlProgram(
        webGLProgram,
        gl,
        !/^[ \t]*#[ \t]*version[ \t]+300[ \t]+es[ \t]*$/m.test(program.vertex)
      );
      program._uniformData = getUniformData(webGLProgram, gl);
      program._uniformBlockData = getUboData(webGLProgram, gl);
      gl.deleteShader(glVertShader);
      gl.deleteShader(glFragShader);
      const uniformData = {};
      for (const i in program._uniformData) {
        const data = program._uniformData[i];
        uniformData[i] = {
          location: gl.getUniformLocation(webGLProgram, i),
          value: defaultValue(data.type, data.size)
        };
      }
      const glProgram = new GlProgramData(webGLProgram, uniformData);
      return glProgram;
    }

    "use strict";
    const defaultSyncData = {
      textureCount: 0,
      blockIndex: 0
    };
    class GlShaderSystem {
      constructor(renderer) {
        /** @internal */
        this._activeProgram = null;
        this._programDataHash = /* @__PURE__ */ Object.create(null);
        this._shaderSyncFunctions = /* @__PURE__ */ Object.create(null);
        this._renderer = renderer;
      }
      contextChange(gl) {
        this._gl = gl;
        this._programDataHash = /* @__PURE__ */ Object.create(null);
        this._shaderSyncFunctions = /* @__PURE__ */ Object.create(null);
        this._activeProgram = null;
      }
      /**
       * Changes the current shader to the one given in parameter.
       * @param shader - the new shader
       * @param skipSync - false if the shader should automatically sync its uniforms.
       * @returns the glProgram that belongs to the shader.
       */
      bind(shader, skipSync) {
        this._setProgram(shader.glProgram);
        if (skipSync)
          return;
        defaultSyncData.textureCount = 0;
        defaultSyncData.blockIndex = 0;
        let syncFunction = this._shaderSyncFunctions[shader.glProgram._key];
        if (!syncFunction) {
          syncFunction = this._shaderSyncFunctions[shader.glProgram._key] = this._generateShaderSync(shader, this);
        }
        this._renderer.buffer.nextBindBase(!!shader.glProgram.transformFeedbackVaryings);
        syncFunction(this._renderer, shader, defaultSyncData);
      }
      /**
       * Updates the uniform group.
       * @param uniformGroup - the uniform group to update
       */
      updateUniformGroup(uniformGroup) {
        this._renderer.uniformGroup.updateUniformGroup(uniformGroup, this._activeProgram, defaultSyncData);
      }
      /**
       * Binds a uniform block to the shader.
       * @param uniformGroup - the uniform group to bind
       * @param name - the name of the uniform block
       * @param index - the index of the uniform block
       */
      bindUniformBlock(uniformGroup, name, index = 0) {
        const bufferSystem = this._renderer.buffer;
        const programData = this._getProgramData(this._activeProgram);
        const isBufferResource = uniformGroup._bufferResource;
        if (!isBufferResource) {
          this._renderer.ubo.updateUniformGroup(uniformGroup);
        }
        const buffer = uniformGroup.buffer;
        const glBuffer = bufferSystem.updateBuffer(buffer);
        const boundLocation = bufferSystem.freeLocationForBufferBase(glBuffer);
        if (isBufferResource) {
          const { offset, size } = uniformGroup;
          if (offset === 0 && size === buffer.data.byteLength) {
            bufferSystem.bindBufferBase(glBuffer, boundLocation);
          } else {
            bufferSystem.bindBufferRange(glBuffer, boundLocation, offset);
          }
        } else if (bufferSystem.getLastBindBaseLocation(glBuffer) !== boundLocation) {
          bufferSystem.bindBufferBase(glBuffer, boundLocation);
        }
        const uniformBlockIndex = this._activeProgram._uniformBlockData[name].index;
        if (programData.uniformBlockBindings[index] === boundLocation)
          return;
        programData.uniformBlockBindings[index] = boundLocation;
        this._renderer.gl.uniformBlockBinding(programData.program, uniformBlockIndex, boundLocation);
      }
      _setProgram(program) {
        if (this._activeProgram === program)
          return;
        this._activeProgram = program;
        const programData = this._getProgramData(program);
        this._gl.useProgram(programData.program);
      }
      /**
       * @param program - the program to get the data for
       * @internal
       */
      _getProgramData(program) {
        return this._programDataHash[program._key] || this._createProgramData(program);
      }
      _createProgramData(program) {
        const key = program._key;
        this._programDataHash[key] = generateProgram(this._gl, program);
        return this._programDataHash[key];
      }
      destroy() {
        for (const key of Object.keys(this._programDataHash)) {
          this._programDataHash[key].destroy();
        }
        this._programDataHash = null;
        this._shaderSyncFunctions = null;
        this._activeProgram = null;
        this._renderer = null;
        this._gl = null;
      }
      /**
       * Creates a function that can be executed that will sync the shader as efficiently as possible.
       * Overridden by the unsafe eval package if you don't want eval used in your project.
       * @param shader - the shader to generate the sync function for
       * @param shaderSystem - the shader system to use
       * @returns - the generated sync function
       * @ignore
       */
      _generateShaderSync(shader, shaderSystem) {
        return generateShaderSyncCode(shader, shaderSystem);
      }
      resetState() {
        this._activeProgram = null;
      }
    }
    /** @ignore */
    GlShaderSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "shader"
    };

    "use strict";
    const UNIFORM_TO_SINGLE_SETTERS = {
      f32: `if (cv !== v) {
            cu.value = v;
            gl.uniform1f(location, v);
        }`,
      "vec2<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
            cv[0] = v[0];
            cv[1] = v[1];
            gl.uniform2f(location, v[0], v[1]);
        }`,
      "vec3<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            gl.uniform3f(location, v[0], v[1], v[2]);
        }`,
      "vec4<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            cv[3] = v[3];
            gl.uniform4f(location, v[0], v[1], v[2], v[3]);
        }`,
      i32: `if (cv !== v) {
            cu.value = v;
            gl.uniform1i(location, v);
        }`,
      "vec2<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
            cv[0] = v[0];
            cv[1] = v[1];
            gl.uniform2i(location, v[0], v[1]);
        }`,
      "vec3<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            gl.uniform3i(location, v[0], v[1], v[2]);
        }`,
      "vec4<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            cv[3] = v[3];
            gl.uniform4i(location, v[0], v[1], v[2], v[3]);
        }`,
      u32: `if (cv !== v) {
            cu.value = v;
            gl.uniform1ui(location, v);
        }`,
      "vec2<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
            cv[0] = v[0];
            cv[1] = v[1];
            gl.uniform2ui(location, v[0], v[1]);
        }`,
      "vec3<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            gl.uniform3ui(location, v[0], v[1], v[2]);
        }`,
      "vec4<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            cv[3] = v[3];
            gl.uniform4ui(location, v[0], v[1], v[2], v[3]);
        }`,
      bool: `if (cv !== v) {
            cu.value = v;
            gl.uniform1i(location, v);
        }`,
      "vec2<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
            cv[0] = v[0];
            cv[1] = v[1];
            gl.uniform2i(location, v[0], v[1]);
        }`,
      "vec3<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            gl.uniform3i(location, v[0], v[1], v[2]);
        }`,
      "vec4<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
            cv[0] = v[0];
            cv[1] = v[1];
            cv[2] = v[2];
            cv[3] = v[3];
            gl.uniform4i(location, v[0], v[1], v[2], v[3]);
        }`,
      "mat2x2<f32>": `gl.uniformMatrix2fv(location, false, v);`,
      "mat3x3<f32>": `gl.uniformMatrix3fv(location, false, v);`,
      "mat4x4<f32>": `gl.uniformMatrix4fv(location, false, v);`
    };
    const UNIFORM_TO_ARRAY_SETTERS = {
      f32: `gl.uniform1fv(location, v);`,
      "vec2<f32>": `gl.uniform2fv(location, v);`,
      "vec3<f32>": `gl.uniform3fv(location, v);`,
      "vec4<f32>": `gl.uniform4fv(location, v);`,
      "mat2x2<f32>": `gl.uniformMatrix2fv(location, false, v);`,
      "mat3x3<f32>": `gl.uniformMatrix3fv(location, false, v);`,
      "mat4x4<f32>": `gl.uniformMatrix4fv(location, false, v);`,
      i32: `gl.uniform1iv(location, v);`,
      "vec2<i32>": `gl.uniform2iv(location, v);`,
      "vec3<i32>": `gl.uniform3iv(location, v);`,
      "vec4<i32>": `gl.uniform4iv(location, v);`,
      u32: `gl.uniform1iv(location, v);`,
      "vec2<u32>": `gl.uniform2iv(location, v);`,
      "vec3<u32>": `gl.uniform3iv(location, v);`,
      "vec4<u32>": `gl.uniform4iv(location, v);`,
      bool: `gl.uniform1iv(location, v);`,
      "vec2<bool>": `gl.uniform2iv(location, v);`,
      "vec3<bool>": `gl.uniform3iv(location, v);`,
      "vec4<bool>": `gl.uniform4iv(location, v);`
    };

    "use strict";
    function generateUniformsSync(group, uniformData) {
      const funcFragments = [`
        var v = null;
        var cv = null;
        var cu = null;
        var t = 0;
        var gl = renderer.gl;
        var name = null;
    `];
      for (const i in group.uniforms) {
        if (!uniformData[i]) {
          if (group.uniforms[i] instanceof UniformGroup) {
            if (group.uniforms[i].ubo) {
              funcFragments.push(`
                        renderer.shader.bindUniformBlock(uv.${i}, "${i}");
                    `);
            } else {
              funcFragments.push(`
                        renderer.shader.updateUniformGroup(uv.${i});
                    `);
            }
          } else if (group.uniforms[i] instanceof BufferResource) {
            funcFragments.push(`
                        renderer.shader.bindBufferResource(uv.${i}, "${i}");
                    `);
          }
          continue;
        }
        const uniform = group.uniformStructures[i];
        let parsed = false;
        for (let j = 0; j < uniformParsers.length; j++) {
          const parser = uniformParsers[j];
          if (uniform.type === parser.type && parser.test(uniform)) {
            funcFragments.push(`name = "${i}";`, uniformParsers[j].uniform);
            parsed = true;
            break;
          }
        }
        if (!parsed) {
          const templateType = uniform.size === 1 ? UNIFORM_TO_SINGLE_SETTERS : UNIFORM_TO_ARRAY_SETTERS;
          const template = templateType[uniform.type].replace("location", `ud["${i}"].location`);
          funcFragments.push(`
            cu = ud["${i}"];
            cv = cu.value;
            v = uv["${i}"];
            ${template};`);
        }
      }
      return new Function("ud", "uv", "renderer", "syncData", funcFragments.join("\n"));
    }

    "use strict";
    class GlUniformGroupSystem {
      /** @param renderer - The renderer this System works for. */
      constructor(renderer) {
        /** Cache to holds the generated functions. Stored against UniformObjects unique signature. */
        this._cache = {};
        this._uniformGroupSyncHash = {};
        this._renderer = renderer;
        this.gl = null;
        this._cache = {};
      }
      contextChange(gl) {
        this.gl = gl;
      }
      /**
       * Uploads the uniforms values to the currently bound shader.
       * @param group - the uniforms values that be applied to the current shader
       * @param program
       * @param syncData
       * @param syncData.textureCount
       */
      updateUniformGroup(group, program, syncData) {
        const programData = this._renderer.shader._getProgramData(program);
        if (!group.isStatic || group._dirtyId !== programData.uniformDirtyGroups[group.uid]) {
          programData.uniformDirtyGroups[group.uid] = group._dirtyId;
          const syncFunc = this._getUniformSyncFunction(group, program);
          syncFunc(programData.uniformData, group.uniforms, this._renderer, syncData);
        }
      }
      /**
       * Overridable by the pixi.js/unsafe-eval package to use static syncUniforms instead.
       * @param group
       * @param program
       */
      _getUniformSyncFunction(group, program) {
        var _a;
        return ((_a = this._uniformGroupSyncHash[group._signature]) == null ? void 0 : _a[program._key]) || this._createUniformSyncFunction(group, program);
      }
      _createUniformSyncFunction(group, program) {
        const uniformGroupSyncHash = this._uniformGroupSyncHash[group._signature] || (this._uniformGroupSyncHash[group._signature] = {});
        const id = this._getSignature(group, program._uniformData, "u");
        if (!this._cache[id]) {
          this._cache[id] = this._generateUniformsSync(group, program._uniformData);
        }
        uniformGroupSyncHash[program._key] = this._cache[id];
        return uniformGroupSyncHash[program._key];
      }
      _generateUniformsSync(group, uniformData) {
        return generateUniformsSync(group, uniformData);
      }
      /**
       * Takes a uniform group and data and generates a unique signature for them.
       * @param group - The uniform group to get signature of
       * @param group.uniforms
       * @param uniformData - Uniform information generated by the shader
       * @param preFix
       * @returns Unique signature of the uniform group
       */
      _getSignature(group, uniformData, preFix) {
        const uniforms = group.uniforms;
        const strings = [`${preFix}-`];
        for (const i in uniforms) {
          strings.push(i);
          if (uniformData[i]) {
            strings.push(uniformData[i].type);
          }
        }
        return strings.join("-");
      }
      /** Destroys this System and removes all its textures. */
      destroy() {
        this._renderer = null;
        this._cache = null;
      }
    }
    /** @ignore */
    GlUniformGroupSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "uniformGroup"
    };

    "use strict";
    function migrateFragmentFromV7toV8(fragmentShader) {
      fragmentShader = fragmentShader.replaceAll("texture2D", "texture").replaceAll("gl_FragColor", "finalColor").replaceAll("varying", "in");
      fragmentShader = `
        out vec4 finalColor;
    ${fragmentShader}
    `;
      return fragmentShader;
    }

    "use strict";
    const GLSL_TO_SIZE = {
      float: 1,
      vec2: 2,
      vec3: 3,
      vec4: 4,
      int: 1,
      ivec2: 2,
      ivec3: 3,
      ivec4: 4,
      uint: 1,
      uvec2: 2,
      uvec3: 3,
      uvec4: 4,
      bool: 1,
      bvec2: 2,
      bvec3: 3,
      bvec4: 4,
      mat2: 4,
      mat3: 9,
      mat4: 16,
      sampler2D: 1
    };
    function mapSize(type) {
      return GLSL_TO_SIZE[type];
    }

    "use strict";
    function mapWebGLBlendModesToPixi(gl) {
      const blendMap = {};
      blendMap.normal = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
      blendMap.add = [gl.ONE, gl.ONE];
      blendMap.multiply = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
      blendMap.screen = [gl.ONE, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
      blendMap.none = [0, 0];
      blendMap["normal-npm"] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
      blendMap["add-npm"] = [gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE];
      blendMap["screen-npm"] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
      blendMap.erase = [gl.ZERO, gl.ONE_MINUS_SRC_ALPHA];
      const isWebGl2 = !(gl instanceof DOMAdapter.get().getWebGLRenderingContext());
      if (isWebGl2) {
        blendMap.min = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, gl.MIN, gl.MIN];
        blendMap.max = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, gl.MAX, gl.MAX];
      } else {
        const ext = gl.getExtension("EXT_blend_minmax");
        if (ext) {
          blendMap.min = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, ext.MIN_EXT, ext.MIN_EXT];
          blendMap.max = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, ext.MAX_EXT, ext.MAX_EXT];
        }
      }
      return blendMap;
    }

    "use strict";
    const BLEND = 0;
    const OFFSET = 1;
    const CULLING = 2;
    const DEPTH_TEST = 3;
    const WINDING = 4;
    const DEPTH_MASK = 5;
    const _GlStateSystem = class _GlStateSystem {
      constructor(renderer) {
        /**
         * Whether to invert the front face when rendering
         * This is used for render textures where the Y-coordinate is flipped
         * @default false
         */
        this._invertFrontFace = false;
        this.gl = null;
        this.stateId = 0;
        this.polygonOffset = 0;
        this.blendMode = "none";
        this._blendEq = false;
        this.map = [];
        this.map[BLEND] = this.setBlend;
        this.map[OFFSET] = this.setOffset;
        this.map[CULLING] = this.setCullFace;
        this.map[DEPTH_TEST] = this.setDepthTest;
        this.map[WINDING] = this.setFrontFace;
        this.map[DEPTH_MASK] = this.setDepthMask;
        this.checks = [];
        this.defaultState = State.for2d();
        renderer.renderTarget.onRenderTargetChange.add(this);
      }
      onRenderTargetChange(renderTarget) {
        this._invertFrontFace = !renderTarget.isRoot;
        if (this._cullFace) {
          this.setFrontFace(this._frontFace);
        } else {
          this._frontFaceDirty = true;
        }
      }
      contextChange(gl) {
        this.gl = gl;
        this.blendModesMap = mapWebGLBlendModesToPixi(gl);
        this.resetState();
      }
      /**
       * Sets the current state
       * @param {*} state - The state to set.
       */
      set(state) {
        state || (state = this.defaultState);
        if (this.stateId !== state.data) {
          let diff = this.stateId ^ state.data;
          let i = 0;
          while (diff) {
            if (diff & 1) {
              this.map[i].call(this, !!(state.data & 1 << i));
            }
            diff >>= 1;
            i++;
          }
          this.stateId = state.data;
        }
        for (let i = 0; i < this.checks.length; i++) {
          this.checks[i](this, state);
        }
      }
      /**
       * Sets the state, when previous state is unknown.
       * @param {*} state - The state to set
       */
      forceState(state) {
        state || (state = this.defaultState);
        for (let i = 0; i < this.map.length; i++) {
          this.map[i].call(this, !!(state.data & 1 << i));
        }
        for (let i = 0; i < this.checks.length; i++) {
          this.checks[i](this, state);
        }
        this.stateId = state.data;
      }
      /**
       * Sets whether to enable or disable blending.
       * @param value - Turn on or off WebGl blending.
       */
      setBlend(value) {
        this._updateCheck(_GlStateSystem._checkBlendMode, value);
        this.gl[value ? "enable" : "disable"](this.gl.BLEND);
      }
      /**
       * Sets whether to enable or disable polygon offset fill.
       * @param value - Turn on or off webgl polygon offset testing.
       */
      setOffset(value) {
        this._updateCheck(_GlStateSystem._checkPolygonOffset, value);
        this.gl[value ? "enable" : "disable"](this.gl.POLYGON_OFFSET_FILL);
      }
      /**
       * Sets whether to enable or disable depth test.
       * @param value - Turn on or off webgl depth testing.
       */
      setDepthTest(value) {
        this.gl[value ? "enable" : "disable"](this.gl.DEPTH_TEST);
      }
      /**
       * Sets whether to enable or disable depth mask.
       * @param value - Turn on or off webgl depth mask.
       */
      setDepthMask(value) {
        this.gl.depthMask(value);
      }
      /**
       * Sets whether to enable or disable cull face.
       * @param {boolean} value - Turn on or off webgl cull face.
       */
      setCullFace(value) {
        this._cullFace = value;
        this.gl[value ? "enable" : "disable"](this.gl.CULL_FACE);
        if (this._cullFace && this._frontFaceDirty) {
          this.setFrontFace(this._frontFace);
        }
      }
      /**
       * Sets the gl front face.
       * @param {boolean} value - true is clockwise and false is counter-clockwise
       */
      setFrontFace(value) {
        this._frontFace = value;
        this._frontFaceDirty = false;
        const faceMode = this._invertFrontFace ? !value : value;
        if (this._glFrontFace !== faceMode) {
          this._glFrontFace = faceMode;
          this.gl.frontFace(this.gl[faceMode ? "CW" : "CCW"]);
        }
      }
      /**
       * Sets the blend mode.
       * @param {number} value - The blend mode to set to.
       */
      setBlendMode(value) {
        if (!this.blendModesMap[value]) {
          value = "normal";
        }
        if (value === this.blendMode) {
          return;
        }
        this.blendMode = value;
        const mode = this.blendModesMap[value];
        const gl = this.gl;
        if (mode.length === 2) {
          gl.blendFunc(mode[0], mode[1]);
        } else {
          gl.blendFuncSeparate(mode[0], mode[1], mode[2], mode[3]);
        }
        if (mode.length === 6) {
          this._blendEq = true;
          gl.blendEquationSeparate(mode[4], mode[5]);
        } else if (this._blendEq) {
          this._blendEq = false;
          gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
        }
      }
      /**
       * Sets the polygon offset.
       * @param {number} value - the polygon offset
       * @param {number} scale - the polygon offset scale
       */
      setPolygonOffset(value, scale) {
        this.gl.polygonOffset(value, scale);
      }
      /** Resets all the logic and disables the VAOs. */
      resetState() {
        this._glFrontFace = false;
        this._frontFace = false;
        this._cullFace = false;
        this._frontFaceDirty = false;
        this._invertFrontFace = false;
        this.gl.frontFace(this.gl.CCW);
        this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
        this.forceState(this.defaultState);
        this._blendEq = true;
        this.blendMode = "";
        this.setBlendMode("normal");
      }
      /**
       * Checks to see which updates should be checked based on which settings have been activated.
       *
       * For example, if blend is enabled then we should check the blend modes each time the state is changed
       * or if polygon fill is activated then we need to check if the polygon offset changes.
       * The idea is that we only check what we have too.
       * @param func - the checking function to add or remove
       * @param value - should the check function be added or removed.
       */
      _updateCheck(func, value) {
        const index = this.checks.indexOf(func);
        if (value && index === -1) {
          this.checks.push(func);
        } else if (!value && index !== -1) {
          this.checks.splice(index, 1);
        }
      }
      /**
       * A private little wrapper function that we call to check the blend mode.
       * @param system - the System to perform the state check on
       * @param state - the state that the blendMode will pulled from
       */
      static _checkBlendMode(system, state) {
        system.setBlendMode(state.blendMode);
      }
      /**
       * A private little wrapper function that we call to check the polygon offset.
       * @param system - the System to perform the state check on
       * @param state - the state that the blendMode will pulled from
       */
      static _checkPolygonOffset(system, state) {
        system.setPolygonOffset(1, state.polygonOffset);
      }
      /** @ignore */
      destroy() {
        this.gl = null;
        this.checks.length = 0;
      }
    };
    /** @ignore */
    _GlStateSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "state"
    };
    let GlStateSystem = _GlStateSystem;

    "use strict";
    class GlTexture {
      constructor(texture) {
        this.target = GL_TARGETS.TEXTURE_2D;
        this.texture = texture;
        this.width = -1;
        this.height = -1;
        this.type = GL_TYPES.UNSIGNED_BYTE;
        this.internalFormat = GL_FORMATS.RGBA;
        this.format = GL_FORMATS.RGBA;
        this.samplerType = 0;
      }
      destroy() {
      }
    }

    "use strict";
    const glUploadBufferImageResource = {
      id: "buffer",
      upload(source, glTexture, gl) {
        if (glTexture.width === source.width || glTexture.height === source.height) {
          gl.texSubImage2D(
            gl.TEXTURE_2D,
            0,
            0,
            0,
            source.width,
            source.height,
            glTexture.format,
            glTexture.type,
            source.resource
          );
        } else {
          gl.texImage2D(
            glTexture.target,
            0,
            glTexture.internalFormat,
            source.width,
            source.height,
            0,
            glTexture.format,
            glTexture.type,
            source.resource
          );
        }
        glTexture.width = source.width;
        glTexture.height = source.height;
      }
    };

    "use strict";
    const compressedFormatMap = {
      "bc1-rgba-unorm": true,
      "bc1-rgba-unorm-srgb": true,
      "bc2-rgba-unorm": true,
      "bc2-rgba-unorm-srgb": true,
      "bc3-rgba-unorm": true,
      "bc3-rgba-unorm-srgb": true,
      "bc4-r-unorm": true,
      "bc4-r-snorm": true,
      "bc5-rg-unorm": true,
      "bc5-rg-snorm": true,
      "bc6h-rgb-ufloat": true,
      "bc6h-rgb-float": true,
      "bc7-rgba-unorm": true,
      "bc7-rgba-unorm-srgb": true,
      // ETC2 compressed formats usable if "texture-compression-etc2" is both
      // supported by the device/user agent and enabled in requestDevice.
      "etc2-rgb8unorm": true,
      "etc2-rgb8unorm-srgb": true,
      "etc2-rgb8a1unorm": true,
      "etc2-rgb8a1unorm-srgb": true,
      "etc2-rgba8unorm": true,
      "etc2-rgba8unorm-srgb": true,
      "eac-r11unorm": true,
      "eac-r11snorm": true,
      "eac-rg11unorm": true,
      "eac-rg11snorm": true,
      // ASTC compressed formats usable if "texture-compression-astc" is both
      // supported by the device/user agent and enabled in requestDevice.
      "astc-4x4-unorm": true,
      "astc-4x4-unorm-srgb": true,
      "astc-5x4-unorm": true,
      "astc-5x4-unorm-srgb": true,
      "astc-5x5-unorm": true,
      "astc-5x5-unorm-srgb": true,
      "astc-6x5-unorm": true,
      "astc-6x5-unorm-srgb": true,
      "astc-6x6-unorm": true,
      "astc-6x6-unorm-srgb": true,
      "astc-8x5-unorm": true,
      "astc-8x5-unorm-srgb": true,
      "astc-8x6-unorm": true,
      "astc-8x6-unorm-srgb": true,
      "astc-8x8-unorm": true,
      "astc-8x8-unorm-srgb": true,
      "astc-10x5-unorm": true,
      "astc-10x5-unorm-srgb": true,
      "astc-10x6-unorm": true,
      "astc-10x6-unorm-srgb": true,
      "astc-10x8-unorm": true,
      "astc-10x8-unorm-srgb": true,
      "astc-10x10-unorm": true,
      "astc-10x10-unorm-srgb": true,
      "astc-12x10-unorm": true,
      "astc-12x10-unorm-srgb": true,
      "astc-12x12-unorm": true,
      "astc-12x12-unorm-srgb": true
    };
    const glUploadCompressedTextureResource = {
      id: "compressed",
      upload(source, glTexture, gl) {
        gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
        let mipWidth = source.pixelWidth;
        let mipHeight = source.pixelHeight;
        const compressed = !!compressedFormatMap[source.format];
        for (let i = 0; i < source.resource.length; i++) {
          const levelBuffer = source.resource[i];
          if (compressed) {
            gl.compressedTexImage2D(
              gl.TEXTURE_2D,
              i,
              glTexture.internalFormat,
              mipWidth,
              mipHeight,
              0,
              levelBuffer
            );
          } else {
            gl.texImage2D(
              gl.TEXTURE_2D,
              i,
              glTexture.internalFormat,
              mipWidth,
              mipHeight,
              0,
              glTexture.format,
              glTexture.type,
              levelBuffer
            );
          }
          mipWidth = Math.max(mipWidth >> 1, 1);
          mipHeight = Math.max(mipHeight >> 1, 1);
        }
      }
    };

    "use strict";
    const glUploadImageResource = {
      id: "image",
      upload(source, glTexture, gl, webGLVersion) {
        const glWidth = glTexture.width;
        const glHeight = glTexture.height;
        const textureWidth = source.pixelWidth;
        const textureHeight = source.pixelHeight;
        const resourceWidth = source.resourceWidth;
        const resourceHeight = source.resourceHeight;
        if (resourceWidth < textureWidth || resourceHeight < textureHeight) {
          if (glWidth !== textureWidth || glHeight !== textureHeight) {
            gl.texImage2D(
              glTexture.target,
              0,
              glTexture.internalFormat,
              textureWidth,
              textureHeight,
              0,
              glTexture.format,
              glTexture.type,
              null
            );
          }
          if (webGLVersion === 2) {
            gl.texSubImage2D(
              gl.TEXTURE_2D,
              0,
              0,
              0,
              resourceWidth,
              resourceHeight,
              glTexture.format,
              glTexture.type,
              source.resource
            );
          } else {
            gl.texSubImage2D(
              gl.TEXTURE_2D,
              0,
              0,
              0,
              glTexture.format,
              glTexture.type,
              source.resource
            );
          }
        } else if (glWidth === textureWidth && glHeight === textureHeight) {
          gl.texSubImage2D(
            gl.TEXTURE_2D,
            0,
            0,
            0,
            glTexture.format,
            glTexture.type,
            source.resource
          );
        } else if (webGLVersion === 2) {
          gl.texImage2D(
            glTexture.target,
            0,
            glTexture.internalFormat,
            textureWidth,
            textureHeight,
            0,
            glTexture.format,
            glTexture.type,
            source.resource
          );
        } else {
          gl.texImage2D(
            glTexture.target,
            0,
            glTexture.internalFormat,
            glTexture.format,
            glTexture.type,
            source.resource
          );
        }
        glTexture.width = textureWidth;
        glTexture.height = textureHeight;
      }
    };

    "use strict";
    const glUploadVideoResource = {
      id: "video",
      upload(source, glTexture, gl, webGLVersion) {
        if (!source.isValid) {
          gl.texImage2D(
            glTexture.target,
            0,
            glTexture.internalFormat,
            1,
            1,
            0,
            glTexture.format,
            glTexture.type,
            null
          );
          return;
        }
        glUploadImageResource.upload(source, glTexture, gl, webGLVersion);
      }
    };

    "use strict";
    const scaleModeToGlFilter = {
      linear: 9729,
      nearest: 9728
    };
    const mipmapScaleModeToGlFilter = {
      linear: {
        linear: 9987,
        nearest: 9985
      },
      nearest: {
        linear: 9986,
        nearest: 9984
      }
    };
    const wrapModeToGlAddress = {
      "clamp-to-edge": 33071,
      repeat: 10497,
      "mirror-repeat": 33648
    };
    const compareModeToGlCompare = {
      never: 512,
      less: 513,
      equal: 514,
      "less-equal": 515,
      greater: 516,
      "not-equal": 517,
      "greater-equal": 518,
      always: 519
    };

    "use strict";
    function applyStyleParams(style, gl, mipmaps, anisotropicExt, glFunctionName, firstParam, forceClamp, firstCreation) {
      const castParam = firstParam;
      if (!firstCreation || style.addressModeU !== "repeat" || style.addressModeV !== "repeat" || style.addressModeW !== "repeat") {
        const wrapModeS = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeU];
        const wrapModeT = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeV];
        const wrapModeR = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeW];
        gl[glFunctionName](castParam, gl.TEXTURE_WRAP_S, wrapModeS);
        gl[glFunctionName](castParam, gl.TEXTURE_WRAP_T, wrapModeT);
        if (gl.TEXTURE_WRAP_R)
          gl[glFunctionName](castParam, gl.TEXTURE_WRAP_R, wrapModeR);
      }
      if (!firstCreation || style.magFilter !== "linear") {
        gl[glFunctionName](castParam, gl.TEXTURE_MAG_FILTER, scaleModeToGlFilter[style.magFilter]);
      }
      if (mipmaps) {
        if (!firstCreation || style.mipmapFilter !== "linear") {
          const glFilterMode = mipmapScaleModeToGlFilter[style.minFilter][style.mipmapFilter];
          gl[glFunctionName](castParam, gl.TEXTURE_MIN_FILTER, glFilterMode);
        }
      } else {
        gl[glFunctionName](castParam, gl.TEXTURE_MIN_FILTER, scaleModeToGlFilter[style.minFilter]);
      }
      if (anisotropicExt && style.maxAnisotropy > 1) {
        const level = Math.min(style.maxAnisotropy, gl.getParameter(anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT));
        gl[glFunctionName](castParam, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, level);
      }
      if (style.compare) {
        gl[glFunctionName](castParam, gl.TEXTURE_COMPARE_FUNC, compareModeToGlCompare[style.compare]);
      }
    }

    "use strict";
    function mapFormatToGlFormat(gl) {
      return {
        // 8-bit formats
        r8unorm: gl.RED,
        r8snorm: gl.RED,
        r8uint: gl.RED,
        r8sint: gl.RED,
        // 16-bit formats
        r16uint: gl.RED,
        r16sint: gl.RED,
        r16float: gl.RED,
        rg8unorm: gl.RG,
        rg8snorm: gl.RG,
        rg8uint: gl.RG,
        rg8sint: gl.RG,
        // 32-bit formats
        r32uint: gl.RED,
        r32sint: gl.RED,
        r32float: gl.RED,
        rg16uint: gl.RG,
        rg16sint: gl.RG,
        rg16float: gl.RG,
        rgba8unorm: gl.RGBA,
        "rgba8unorm-srgb": gl.RGBA,
        // Packed 32-bit formats
        rgba8snorm: gl.RGBA,
        rgba8uint: gl.RGBA,
        rgba8sint: gl.RGBA,
        bgra8unorm: gl.RGBA,
        "bgra8unorm-srgb": gl.RGBA,
        rgb9e5ufloat: gl.RGB,
        rgb10a2unorm: gl.RGBA,
        rg11b10ufloat: gl.RGB,
        // 64-bit formats
        rg32uint: gl.RG,
        rg32sint: gl.RG,
        rg32float: gl.RG,
        rgba16uint: gl.RGBA,
        rgba16sint: gl.RGBA,
        rgba16float: gl.RGBA,
        // 128-bit formats
        rgba32uint: gl.RGBA,
        rgba32sint: gl.RGBA,
        rgba32float: gl.RGBA,
        // Depth/stencil formats
        stencil8: gl.STENCIL_INDEX8,
        depth16unorm: gl.DEPTH_COMPONENT,
        depth24plus: gl.DEPTH_COMPONENT,
        "depth24plus-stencil8": gl.DEPTH_STENCIL,
        depth32float: gl.DEPTH_COMPONENT,
        "depth32float-stencil8": gl.DEPTH_STENCIL
      };
    }

    "use strict";
    var __defProp$l = Object.defineProperty;
    var __defProps$a = Object.defineProperties;
    var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$n = Object.getOwnPropertySymbols;
    var __hasOwnProp$n = Object.prototype.hasOwnProperty;
    var __propIsEnum$n = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$l = (obj, key, value) => key in obj ? __defProp$l(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$l = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$n.call(b, prop))
          __defNormalProp$l(a, prop, b[prop]);
      if (__getOwnPropSymbols$n)
        for (var prop of __getOwnPropSymbols$n(b)) {
          if (__propIsEnum$n.call(b, prop))
            __defNormalProp$l(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$a = (a, b) => __defProps$a(a, __getOwnPropDescs$a(b));
    function mapFormatToGlInternalFormat(gl, extensions) {
      let srgb = {};
      let bgra8unorm = gl.RGBA;
      if (!(gl instanceof DOMAdapter.get().getWebGLRenderingContext())) {
        srgb = {
          "rgba8unorm-srgb": gl.SRGB8_ALPHA8,
          "bgra8unorm-srgb": gl.SRGB8_ALPHA8
        };
        bgra8unorm = gl.RGBA8;
      } else if (extensions.srgb) {
        srgb = {
          "rgba8unorm-srgb": extensions.srgb.SRGB8_ALPHA8_EXT,
          "bgra8unorm-srgb": extensions.srgb.SRGB8_ALPHA8_EXT
        };
      }
      return __spreadValues$l(__spreadValues$l(__spreadValues$l(__spreadValues$l(__spreadValues$l(__spreadValues$l(__spreadProps$a(__spreadValues$l({
        // 8-bit formats
        r8unorm: gl.R8,
        r8snorm: gl.R8_SNORM,
        r8uint: gl.R8UI,
        r8sint: gl.R8I,
        // 16-bit formats
        r16uint: gl.R16UI,
        r16sint: gl.R16I,
        r16float: gl.R16F,
        rg8unorm: gl.RG8,
        rg8snorm: gl.RG8_SNORM,
        rg8uint: gl.RG8UI,
        rg8sint: gl.RG8I,
        // 32-bit formats
        r32uint: gl.R32UI,
        r32sint: gl.R32I,
        r32float: gl.R32F,
        rg16uint: gl.RG16UI,
        rg16sint: gl.RG16I,
        rg16float: gl.RG16F,
        rgba8unorm: gl.RGBA
      }, srgb), {
        // Packed 32-bit formats
        rgba8snorm: gl.RGBA8_SNORM,
        rgba8uint: gl.RGBA8UI,
        rgba8sint: gl.RGBA8I,
        bgra8unorm,
        rgb9e5ufloat: gl.RGB9_E5,
        rgb10a2unorm: gl.RGB10_A2,
        rg11b10ufloat: gl.R11F_G11F_B10F,
        // 64-bit formats
        rg32uint: gl.RG32UI,
        rg32sint: gl.RG32I,
        rg32float: gl.RG32F,
        rgba16uint: gl.RGBA16UI,
        rgba16sint: gl.RGBA16I,
        rgba16float: gl.RGBA16F,
        // 128-bit formats
        rgba32uint: gl.RGBA32UI,
        rgba32sint: gl.RGBA32I,
        rgba32float: gl.RGBA32F,
        // Depth/stencil formats
        stencil8: gl.STENCIL_INDEX8,
        depth16unorm: gl.DEPTH_COMPONENT16,
        depth24plus: gl.DEPTH_COMPONENT24,
        "depth24plus-stencil8": gl.DEPTH24_STENCIL8,
        depth32float: gl.DEPTH_COMPONENT32F,
        "depth32float-stencil8": gl.DEPTH32F_STENCIL8
      }), extensions.s3tc ? {
        "bc1-rgba-unorm": extensions.s3tc.COMPRESSED_RGBA_S3TC_DXT1_EXT,
        "bc2-rgba-unorm": extensions.s3tc.COMPRESSED_RGBA_S3TC_DXT3_EXT,
        "bc3-rgba-unorm": extensions.s3tc.COMPRESSED_RGBA_S3TC_DXT5_EXT
      } : {}), extensions.s3tc_sRGB ? {
        "bc1-rgba-unorm-srgb": extensions.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
        "bc2-rgba-unorm-srgb": extensions.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
        "bc3-rgba-unorm-srgb": extensions.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
      } : {}), extensions.rgtc ? {
        "bc4-r-unorm": extensions.rgtc.COMPRESSED_RED_RGTC1_EXT,
        "bc4-r-snorm": extensions.rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT,
        "bc5-rg-unorm": extensions.rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
        "bc5-rg-snorm": extensions.rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT
      } : {}), extensions.bptc ? {
        "bc6h-rgb-float": extensions.bptc.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT,
        "bc6h-rgb-ufloat": extensions.bptc.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT,
        "bc7-rgba-unorm": extensions.bptc.COMPRESSED_RGBA_BPTC_UNORM_EXT,
        "bc7-rgba-unorm-srgb": extensions.bptc.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT
      } : {}), extensions.etc ? {
        "etc2-rgb8unorm": extensions.etc.COMPRESSED_RGB8_ETC2,
        "etc2-rgb8unorm-srgb": extensions.etc.COMPRESSED_SRGB8_ETC2,
        "etc2-rgb8a1unorm": extensions.etc.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
        "etc2-rgb8a1unorm-srgb": extensions.etc.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
        "etc2-rgba8unorm": extensions.etc.COMPRESSED_RGBA8_ETC2_EAC,
        "etc2-rgba8unorm-srgb": extensions.etc.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
        "eac-r11unorm": extensions.etc.COMPRESSED_R11_EAC,
        // 'eac-r11snorm'
        "eac-rg11unorm": extensions.etc.COMPRESSED_SIGNED_RG11_EAC
        // 'eac-rg11snorm'
      } : {}), extensions.astc ? {
        "astc-4x4-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_4x4_KHR,
        "astc-4x4-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
        "astc-5x4-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_5x4_KHR,
        "astc-5x4-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
        "astc-5x5-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_5x5_KHR,
        "astc-5x5-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
        "astc-6x5-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_6x5_KHR,
        "astc-6x5-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
        "astc-6x6-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_6x6_KHR,
        "astc-6x6-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
        "astc-8x5-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_8x5_KHR,
        "astc-8x5-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
        "astc-8x6-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_8x6_KHR,
        "astc-8x6-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
        "astc-8x8-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_8x8_KHR,
        "astc-8x8-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
        "astc-10x5-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_10x5_KHR,
        "astc-10x5-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
        "astc-10x6-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_10x6_KHR,
        "astc-10x6-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
        "astc-10x8-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_10x8_KHR,
        "astc-10x8-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
        "astc-10x10-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_10x10_KHR,
        "astc-10x10-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
        "astc-12x10-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_12x10_KHR,
        "astc-12x10-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
        "astc-12x12-unorm": extensions.astc.COMPRESSED_RGBA_ASTC_12x12_KHR,
        "astc-12x12-unorm-srgb": extensions.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
      } : {});
    }

    "use strict";
    function mapFormatToGlType(gl) {
      return {
        // 8-bit formats
        r8unorm: gl.UNSIGNED_BYTE,
        r8snorm: gl.BYTE,
        r8uint: gl.UNSIGNED_BYTE,
        r8sint: gl.BYTE,
        // 16-bit formats
        r16uint: gl.UNSIGNED_SHORT,
        r16sint: gl.SHORT,
        r16float: gl.HALF_FLOAT,
        rg8unorm: gl.UNSIGNED_BYTE,
        rg8snorm: gl.BYTE,
        rg8uint: gl.UNSIGNED_BYTE,
        rg8sint: gl.BYTE,
        // 32-bit formats
        r32uint: gl.UNSIGNED_INT,
        r32sint: gl.INT,
        r32float: gl.FLOAT,
        rg16uint: gl.UNSIGNED_SHORT,
        rg16sint: gl.SHORT,
        rg16float: gl.HALF_FLOAT,
        rgba8unorm: gl.UNSIGNED_BYTE,
        "rgba8unorm-srgb": gl.UNSIGNED_BYTE,
        // Packed 32-bit formats
        rgba8snorm: gl.BYTE,
        rgba8uint: gl.UNSIGNED_BYTE,
        rgba8sint: gl.BYTE,
        bgra8unorm: gl.UNSIGNED_BYTE,
        "bgra8unorm-srgb": gl.UNSIGNED_BYTE,
        rgb9e5ufloat: gl.UNSIGNED_INT_5_9_9_9_REV,
        rgb10a2unorm: gl.UNSIGNED_INT_2_10_10_10_REV,
        rg11b10ufloat: gl.UNSIGNED_INT_10F_11F_11F_REV,
        // 64-bit formats
        rg32uint: gl.UNSIGNED_INT,
        rg32sint: gl.INT,
        rg32float: gl.FLOAT,
        rgba16uint: gl.UNSIGNED_SHORT,
        rgba16sint: gl.SHORT,
        rgba16float: gl.HALF_FLOAT,
        // 128-bit formats
        rgba32uint: gl.UNSIGNED_INT,
        rgba32sint: gl.INT,
        rgba32float: gl.FLOAT,
        // Depth/stencil formats
        stencil8: gl.UNSIGNED_BYTE,
        depth16unorm: gl.UNSIGNED_SHORT,
        depth24plus: gl.UNSIGNED_INT,
        "depth24plus-stencil8": gl.UNSIGNED_INT_24_8,
        depth32float: gl.FLOAT,
        "depth32float-stencil8": gl.FLOAT_32_UNSIGNED_INT_24_8_REV
      };
    }

    "use strict";
    function unpremultiplyAlpha$1(pixels) {
      if (pixels instanceof Uint8ClampedArray) {
        pixels = new Uint8Array(pixels.buffer);
      }
      const n = pixels.length;
      for (let i = 0; i < n; i += 4) {
        const alpha = pixels[i + 3];
        if (alpha !== 0) {
          const a = 255.001 / alpha;
          pixels[i] = pixels[i] * a + 0.5;
          pixels[i + 1] = pixels[i + 1] * a + 0.5;
          pixels[i + 2] = pixels[i + 2] * a + 0.5;
        }
      }
    }

    "use strict";
    const BYTES_PER_PIXEL = 4;
    class GlTextureSystem {
      constructor(renderer) {
        this._glSamplers = /* @__PURE__ */ Object.create(null);
        this._boundTextures = [];
        this._activeTextureLocation = -1;
        this._boundSamplers = /* @__PURE__ */ Object.create(null);
        this._uploads = {
          image: glUploadImageResource,
          buffer: glUploadBufferImageResource,
          video: glUploadVideoResource,
          compressed: glUploadCompressedTextureResource
        };
        this._premultiplyAlpha = false;
        // TODO - separate samplers will be a cool thing to add, but not right now!
        this._useSeparateSamplers = false;
        this._renderer = renderer;
        this._managedTextures = new GCManagedHash({
          renderer,
          type: "resource",
          onUnload: this.onSourceUnload.bind(this),
          name: "glTexture"
        });
      }
      /**
       * @deprecated since 8.15.0
       */
      get managedTextures() {
        return Object.values(this._managedTextures.items);
      }
      contextChange(gl) {
        this._gl = gl;
        if (!this._mapFormatToInternalFormat) {
          this._mapFormatToInternalFormat = mapFormatToGlInternalFormat(gl, this._renderer.context.extensions);
          this._mapFormatToType = mapFormatToGlType(gl);
          this._mapFormatToFormat = mapFormatToGlFormat(gl);
        }
        this._managedTextures.removeAll(true);
        this._glSamplers = /* @__PURE__ */ Object.create(null);
        this._boundSamplers = /* @__PURE__ */ Object.create(null);
        this._premultiplyAlpha = false;
        for (let i = 0; i < 16; i++) {
          this.bind(Texture.EMPTY, i);
        }
      }
      /**
       * Initializes a texture source, if it has already been initialized nothing will happen.
       * @param source - The texture source to initialize.
       * @returns The initialized texture source.
       */
      initSource(source) {
        this.bind(source);
      }
      bind(texture, location = 0) {
        const source = texture.source;
        if (texture) {
          this.bindSource(source, location);
          if (this._useSeparateSamplers) {
            this._bindSampler(source.style, location);
          }
        } else {
          this.bindSource(null, location);
          if (this._useSeparateSamplers) {
            this._bindSampler(null, location);
          }
        }
      }
      bindSource(source, location = 0) {
        const gl = this._gl;
        source._gcLastUsed = this._renderer.gc.now;
        if (this._boundTextures[location] !== source) {
          this._boundTextures[location] = source;
          this._activateLocation(location);
          source || (source = Texture.EMPTY.source);
          const glTexture = this.getGlSource(source);
          gl.bindTexture(glTexture.target, glTexture.texture);
        }
      }
      _bindSampler(style, location = 0) {
        const gl = this._gl;
        if (!style) {
          this._boundSamplers[location] = null;
          gl.bindSampler(location, null);
          return;
        }
        const sampler = this._getGlSampler(style);
        if (this._boundSamplers[location] !== sampler) {
          this._boundSamplers[location] = sampler;
          gl.bindSampler(location, sampler);
        }
      }
      unbind(texture) {
        const source = texture.source;
        const boundTextures = this._boundTextures;
        const gl = this._gl;
        for (let i = 0; i < boundTextures.length; i++) {
          if (boundTextures[i] === source) {
            this._activateLocation(i);
            const glTexture = this.getGlSource(source);
            gl.bindTexture(glTexture.target, null);
            boundTextures[i] = null;
          }
        }
      }
      _activateLocation(location) {
        if (this._activeTextureLocation !== location) {
          this._activeTextureLocation = location;
          this._gl.activeTexture(this._gl.TEXTURE0 + location);
        }
      }
      _initSource(source) {
        const gl = this._gl;
        const glTexture = new GlTexture(gl.createTexture());
        glTexture.type = this._mapFormatToType[source.format];
        glTexture.internalFormat = this._mapFormatToInternalFormat[source.format];
        glTexture.format = this._mapFormatToFormat[source.format];
        if (source.autoGenerateMipmaps && (this._renderer.context.supports.nonPowOf2mipmaps || source.isPowerOfTwo)) {
          const biggestDimension = Math.max(source.width, source.height);
          source.mipLevelCount = Math.floor(Math.log2(biggestDimension)) + 1;
        }
        source._gpuData[this._renderer.uid] = glTexture;
        const added = this._managedTextures.add(source);
        if (added) {
          source.on("update", this.onSourceUpdate, this);
          source.on("resize", this.onSourceUpdate, this);
          source.on("styleChange", this.onStyleChange, this);
          source.on("updateMipmaps", this.onUpdateMipmaps, this);
        }
        this.onSourceUpdate(source);
        this.updateStyle(source, false);
        return glTexture;
      }
      onStyleChange(source) {
        this.updateStyle(source, false);
      }
      updateStyle(source, firstCreation) {
        const gl = this._gl;
        const glTexture = this.getGlSource(source);
        gl.bindTexture(gl.TEXTURE_2D, glTexture.texture);
        this._boundTextures[this._activeTextureLocation] = source;
        applyStyleParams(
          source.style,
          gl,
          source.mipLevelCount > 1,
          this._renderer.context.extensions.anisotropicFiltering,
          "texParameteri",
          gl.TEXTURE_2D,
          // will force a clamp to edge if the texture is not a power of two
          !this._renderer.context.supports.nonPowOf2wrapping && !source.isPowerOfTwo,
          firstCreation
        );
      }
      onSourceUnload(source, contextLost = false) {
        const glTexture = source._gpuData[this._renderer.uid];
        if (!glTexture)
          return;
        if (!contextLost) {
          this.unbind(source);
          this._gl.deleteTexture(glTexture.texture);
        }
        source.off("update", this.onSourceUpdate, this);
        source.off("resize", this.onSourceUpdate, this);
        source.off("styleChange", this.onStyleChange, this);
        source.off("updateMipmaps", this.onUpdateMipmaps, this);
      }
      onSourceUpdate(source) {
        const gl = this._gl;
        const glTexture = this.getGlSource(source);
        gl.bindTexture(gl.TEXTURE_2D, glTexture.texture);
        this._boundTextures[this._activeTextureLocation] = source;
        const premultipliedAlpha = source.alphaMode === "premultiply-alpha-on-upload";
        if (this._premultiplyAlpha !== premultipliedAlpha) {
          this._premultiplyAlpha = premultipliedAlpha;
          gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultipliedAlpha);
        }
        if (this._uploads[source.uploadMethodId]) {
          this._uploads[source.uploadMethodId].upload(source, glTexture, gl, this._renderer.context.webGLVersion);
        } else {
          gl.texImage2D(
            gl.TEXTURE_2D,
            0,
            glTexture.internalFormat,
            source.pixelWidth,
            source.pixelHeight,
            0,
            glTexture.format,
            glTexture.type,
            null
          );
        }
        if (source.autoGenerateMipmaps && source.mipLevelCount > 1) {
          this.onUpdateMipmaps(source, false);
        }
      }
      onUpdateMipmaps(source, bind = true) {
        if (bind)
          this.bindSource(source, 0);
        const glTexture = this.getGlSource(source);
        this._gl.generateMipmap(glTexture.target);
      }
      _initSampler(style) {
        const gl = this._gl;
        const glSampler = this._gl.createSampler();
        this._glSamplers[style._resourceId] = glSampler;
        applyStyleParams(
          style,
          gl,
          this._boundTextures[this._activeTextureLocation].mipLevelCount > 1,
          this._renderer.context.extensions.anisotropicFiltering,
          "samplerParameteri",
          glSampler,
          false,
          true
        );
        return this._glSamplers[style._resourceId];
      }
      _getGlSampler(sampler) {
        return this._glSamplers[sampler._resourceId] || this._initSampler(sampler);
      }
      getGlSource(source) {
        source._gcLastUsed = this._renderer.gc.now;
        return source._gpuData[this._renderer.uid] || this._initSource(source);
      }
      generateCanvas(texture) {
        const { pixels, width, height } = this.getPixels(texture);
        const canvas = DOMAdapter.get().createCanvas();
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext("2d");
        if (ctx) {
          const imageData = ctx.createImageData(width, height);
          imageData.data.set(pixels);
          ctx.putImageData(imageData, 0, 0);
        }
        return canvas;
      }
      getPixels(texture) {
        const resolution = texture.source.resolution;
        const frame = texture.frame;
        const width = Math.max(Math.round(frame.width * resolution), 1);
        const height = Math.max(Math.round(frame.height * resolution), 1);
        const pixels = new Uint8Array(BYTES_PER_PIXEL * width * height);
        const renderer = this._renderer;
        const renderTarget = renderer.renderTarget.getRenderTarget(texture);
        const glRenterTarget = renderer.renderTarget.getGpuRenderTarget(renderTarget);
        const gl = renderer.gl;
        gl.bindFramebuffer(gl.FRAMEBUFFER, glRenterTarget.resolveTargetFramebuffer);
        gl.readPixels(
          Math.round(frame.x * resolution),
          Math.round(frame.y * resolution),
          width,
          height,
          gl.RGBA,
          gl.UNSIGNED_BYTE,
          pixels
        );
        if (false) {
          unpremultiplyAlpha(pixels);
        }
        return { pixels: new Uint8ClampedArray(pixels.buffer), width, height };
      }
      destroy() {
        this._managedTextures.destroy();
        this._glSamplers = null;
        this._boundTextures = null;
        this._boundSamplers = null;
        this._mapFormatToInternalFormat = null;
        this._mapFormatToType = null;
        this._mapFormatToFormat = null;
        this._uploads = null;
        this._renderer = null;
      }
      resetState() {
        this._activeTextureLocation = -1;
        this._boundTextures.fill(Texture.EMPTY.source);
        this._boundSamplers = /* @__PURE__ */ Object.create(null);
        const gl = this._gl;
        this._premultiplyAlpha = false;
        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._premultiplyAlpha);
      }
    }
    /** @ignore */
    GlTextureSystem.extension = {
      type: [
        ExtensionType.WebGLSystem
      ],
      name: "texture"
    };

    "use strict";

    "use strict";
    class GlGraphicsAdaptor {
      contextChange(renderer) {
        const uniforms = new UniformGroup({
          uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
          uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uRound: { value: 0, type: "f32" }
        });
        const maxTextures = renderer.limits.maxBatchableTextures;
        const glProgram = compileHighShaderGlProgram({
          name: "graphics",
          bits: [
            colorBitGl,
            generateTextureBatchBitGl(maxTextures),
            localUniformBitGl,
            roundPixelsBitGl
          ]
        });
        this.shader = new Shader({
          glProgram,
          resources: {
            localUniforms: uniforms,
            batchSamplers: getBatchSamplersUniformGroup(maxTextures)
          }
        });
      }
      execute(graphicsPipe, renderable) {
        const context = renderable.context;
        const shader = context.customShader || this.shader;
        const renderer = graphicsPipe.renderer;
        const contextSystem = renderer.graphicsContext;
        const {
          batcher,
          instructions
        } = contextSystem.getContextRenderData(context);
        shader.groups[0] = renderer.globalUniforms.bindGroup;
        renderer.state.set(graphicsPipe.state);
        renderer.shader.bind(shader);
        renderer.geometry.bind(batcher.geometry, shader.glProgram);
        const batches = instructions.instructions;
        for (let i = 0; i < instructions.instructionSize; i++) {
          const batch = batches[i];
          if (batch.size) {
            for (let j = 0; j < batch.textures.count; j++) {
              renderer.texture.bind(batch.textures.textures[j], j);
            }
            renderer.geometry.draw(batch.topology, batch.size, batch.start);
          }
        }
      }
      destroy() {
        this.shader.destroy(true);
        this.shader = null;
      }
    }
    /** @ignore */
    GlGraphicsAdaptor.extension = {
      type: [
        ExtensionType.WebGLPipesAdaptor
      ],
      name: "graphics"
    };

    "use strict";
    class GlMeshAdaptor {
      init() {
        const glProgram = compileHighShaderGlProgram({
          name: "mesh",
          bits: [
            localUniformBitGl,
            textureBitGl,
            roundPixelsBitGl
          ]
        });
        this._shader = new Shader({
          glProgram,
          resources: {
            uTexture: Texture.EMPTY.source,
            textureUniforms: {
              uTextureMatrix: { type: "mat3x3<f32>", value: new Matrix() }
            }
          }
        });
      }
      execute(meshPipe, mesh) {
        const renderer = meshPipe.renderer;
        let shader = mesh._shader;
        if (!shader) {
          shader = this._shader;
          const texture = mesh.texture;
          const source = texture.source;
          shader.resources.uTexture = source;
          shader.resources.uSampler = source.style;
          shader.resources.textureUniforms.uniforms.uTextureMatrix = texture.textureMatrix.mapCoord;
        } else if (!shader.glProgram) {
          warn("Mesh shader has no glProgram", mesh.shader);
          return;
        }
        shader.groups[100] = renderer.globalUniforms.bindGroup;
        shader.groups[101] = meshPipe.localUniformsBindGroup;
        renderer.encoder.draw({
          geometry: mesh._geometry,
          shader,
          state: mesh.state
        });
      }
      destroy() {
        this._shader.destroy(true);
        this._shader = null;
      }
    }
    GlMeshAdaptor.extension = {
      type: [
        ExtensionType.WebGLPipesAdaptor
      ],
      name: "mesh"
    };

    "use strict";
    class CustomRenderPipe {
      constructor(renderer) {
        this._renderer = renderer;
      }
      updateRenderable() {
      }
      destroyRenderable() {
      }
      validateRenderable() {
        return false;
      }
      addRenderable(container, instructionSet) {
        this._renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add(container);
      }
      execute(container) {
        if (!container.isRenderable)
          return;
        container.render(this._renderer);
      }
      destroy() {
        this._renderer = null;
      }
    }
    CustomRenderPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "customRender"
    };

    "use strict";
    function executeInstructions(renderGroup, renderer) {
      const instructionSet = renderGroup.instructionSet;
      const instructions = instructionSet.instructions;
      for (let i = 0; i < instructionSet.instructionSize; i++) {
        const instruction = instructions[i];
        renderer[instruction.renderPipeId].execute(instruction);
      }
    }

    "use strict";
    const tempMatrix$2 = new Matrix();
    class RenderGroupPipe {
      constructor(renderer) {
        this._renderer = renderer;
      }
      addRenderGroup(renderGroup, instructionSet) {
        if (renderGroup.isCachedAsTexture) {
          this._addRenderableCacheAsTexture(renderGroup, instructionSet);
        } else {
          this._addRenderableDirect(renderGroup, instructionSet);
        }
      }
      execute(renderGroup) {
        if (!renderGroup.isRenderable)
          return;
        if (renderGroup.isCachedAsTexture) {
          this._executeCacheAsTexture(renderGroup);
        } else {
          this._executeDirect(renderGroup);
        }
      }
      destroy() {
        this._renderer = null;
      }
      _addRenderableDirect(renderGroup, instructionSet) {
        this._renderer.renderPipes.batch.break(instructionSet);
        if (renderGroup._batchableRenderGroup) {
          BigPool.return(renderGroup._batchableRenderGroup);
          renderGroup._batchableRenderGroup = null;
        }
        instructionSet.add(renderGroup);
      }
      _addRenderableCacheAsTexture(renderGroup, instructionSet) {
        var _a;
        const batchableRenderGroup = (_a = renderGroup._batchableRenderGroup) != null ? _a : renderGroup._batchableRenderGroup = BigPool.get(BatchableSprite);
        batchableRenderGroup.renderable = renderGroup.root;
        batchableRenderGroup.transform = renderGroup.root.relativeGroupTransform;
        batchableRenderGroup.texture = renderGroup.texture;
        batchableRenderGroup.bounds = renderGroup._textureBounds;
        instructionSet.add(renderGroup);
        this._renderer.renderPipes.blendMode.pushBlendMode(renderGroup, renderGroup.root.groupBlendMode, instructionSet);
        this._renderer.renderPipes.batch.addToBatch(batchableRenderGroup, instructionSet);
        this._renderer.renderPipes.blendMode.popBlendMode(instructionSet);
      }
      _executeCacheAsTexture(renderGroup) {
        if (renderGroup.textureNeedsUpdate) {
          renderGroup.textureNeedsUpdate = false;
          const worldTransformMatrix = tempMatrix$2.identity().translate(
            -renderGroup._textureBounds.x,
            -renderGroup._textureBounds.y
          );
          this._renderer.renderTarget.push(renderGroup.texture, true, null, renderGroup.texture.frame);
          this._renderer.globalUniforms.push({
            worldTransformMatrix,
            worldColor: 4294967295,
            offset: { x: 0, y: 0 }
          });
          executeInstructions(renderGroup, this._renderer.renderPipes);
          this._renderer.renderTarget.finishRenderPass();
          this._renderer.renderTarget.pop();
          this._renderer.globalUniforms.pop();
        }
        renderGroup._batchableRenderGroup._batcher.updateElement(renderGroup._batchableRenderGroup);
        renderGroup._batchableRenderGroup._batcher.geometry.buffers[0].update();
      }
      _executeDirect(renderGroup) {
        this._renderer.globalUniforms.push({
          worldTransformMatrix: renderGroup.inverseParentTextureTransform,
          worldColor: renderGroup.worldColorAlpha
        });
        executeInstructions(renderGroup, this._renderer.renderPipes);
        this._renderer.globalUniforms.pop();
      }
    }
    RenderGroupPipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "renderGroup"
    };

    "use strict";
    function clearList(list, index) {
      index || (index = 0);
      for (let j = index; j < list.length; j++) {
        if (list[j]) {
          list[j] = null;
        } else {
          break;
        }
      }
    }

    "use strict";
    const tempContainer = new Container();
    const UPDATE_BLEND_COLOR_VISIBLE = UPDATE_VISIBLE | UPDATE_COLOR | UPDATE_BLEND;
    function updateRenderGroupTransforms(renderGroup, updateChildRenderGroups = false) {
      updateRenderGroupTransform(renderGroup);
      const childrenToUpdate = renderGroup.childrenToUpdate;
      const updateTick = renderGroup.updateTick++;
      for (const j in childrenToUpdate) {
        const renderGroupDepth = Number(j);
        const childrenAtDepth = childrenToUpdate[j];
        const list = childrenAtDepth.list;
        const index = childrenAtDepth.index;
        for (let i = 0; i < index; i++) {
          const child = list[i];
          if (child.parentRenderGroup === renderGroup && child.relativeRenderGroupDepth === renderGroupDepth) {
            updateTransformAndChildren(child, updateTick, 0);
          }
        }
        clearList(list, index);
        childrenAtDepth.index = 0;
      }
      if (updateChildRenderGroups) {
        for (let i = 0; i < renderGroup.renderGroupChildren.length; i++) {
          updateRenderGroupTransforms(renderGroup.renderGroupChildren[i], updateChildRenderGroups);
        }
      }
    }
    function updateRenderGroupTransform(renderGroup) {
      const root = renderGroup.root;
      let worldAlpha;
      if (renderGroup.renderGroupParent) {
        const renderGroupParent = renderGroup.renderGroupParent;
        renderGroup.worldTransform.appendFrom(
          root.relativeGroupTransform,
          renderGroupParent.worldTransform
        );
        renderGroup.worldColor = multiplyColors(
          root.groupColor,
          renderGroupParent.worldColor
        );
        worldAlpha = root.groupAlpha * renderGroupParent.worldAlpha;
      } else {
        renderGroup.worldTransform.copyFrom(root.localTransform);
        renderGroup.worldColor = root.localColor;
        worldAlpha = root.localAlpha;
      }
      worldAlpha = worldAlpha < 0 ? 0 : worldAlpha > 1 ? 1 : worldAlpha;
      renderGroup.worldAlpha = worldAlpha;
      renderGroup.worldColorAlpha = renderGroup.worldColor + ((worldAlpha * 255 | 0) << 24);
    }
    function updateTransformAndChildren(container, updateTick, updateFlags) {
      if (updateTick === container.updateTick)
        return;
      container.updateTick = updateTick;
      container.didChange = false;
      const localTransform = container.localTransform;
      container.updateLocalTransform();
      const parent = container.parent;
      if (parent && !parent.renderGroup) {
        updateFlags |= container._updateFlags;
        container.relativeGroupTransform.appendFrom(
          localTransform,
          parent.relativeGroupTransform
        );
        if (updateFlags & UPDATE_BLEND_COLOR_VISIBLE) {
          updateColorBlendVisibility(container, parent, updateFlags);
        }
      } else {
        updateFlags = container._updateFlags;
        container.relativeGroupTransform.copyFrom(localTransform);
        if (updateFlags & UPDATE_BLEND_COLOR_VISIBLE) {
          updateColorBlendVisibility(container, tempContainer, updateFlags);
        }
      }
      if (!container.renderGroup) {
        const children = container.children;
        const length = children.length;
        for (let i = 0; i < length; i++) {
          updateTransformAndChildren(children[i], updateTick, updateFlags);
        }
        const renderGroup = container.parentRenderGroup;
        const renderable = container;
        if (renderable.renderPipeId && !renderGroup.structureDidChange) {
          renderGroup.updateRenderable(renderable);
        }
      }
    }
    function updateColorBlendVisibility(container, parent, updateFlags) {
      if (updateFlags & UPDATE_COLOR) {
        container.groupColor = multiplyColors(
          container.localColor,
          parent.groupColor
        );
        let groupAlpha = container.localAlpha * parent.groupAlpha;
        groupAlpha = groupAlpha < 0 ? 0 : groupAlpha > 1 ? 1 : groupAlpha;
        container.groupAlpha = groupAlpha;
        container.groupColorAlpha = container.groupColor + ((groupAlpha * 255 | 0) << 24);
      }
      if (updateFlags & UPDATE_BLEND) {
        container.groupBlendMode = container.localBlendMode === "inherit" ? parent.groupBlendMode : container.localBlendMode;
      }
      if (updateFlags & UPDATE_VISIBLE) {
        container.globalDisplayStatus = container.localDisplayStatus & parent.globalDisplayStatus;
      }
      container._updateFlags = 0;
    }

    "use strict";
    function validateRenderables(renderGroup, renderPipes) {
      const { list } = renderGroup.childrenRenderablesToUpdate;
      let rebuildRequired = false;
      for (let i = 0; i < renderGroup.childrenRenderablesToUpdate.index; i++) {
        const container = list[i];
        const renderable = container;
        const pipe = renderPipes[renderable.renderPipeId];
        rebuildRequired = pipe.validateRenderable(container);
        if (rebuildRequired) {
          break;
        }
      }
      renderGroup.structureDidChange = rebuildRequired;
      return rebuildRequired;
    }

    "use strict";
    const tempMatrix$1 = new Matrix();
    class RenderGroupSystem {
      constructor(renderer) {
        this._renderer = renderer;
      }
      render({ container, transform }) {
        const parent = container.parent;
        const renderGroupParent = container.renderGroup.renderGroupParent;
        container.parent = null;
        container.renderGroup.renderGroupParent = null;
        const renderer = this._renderer;
        const originalLocalTransform = tempMatrix$1;
        if (transform) {
          originalLocalTransform.copyFrom(container.renderGroup.localTransform);
          container.renderGroup.localTransform.copyFrom(transform);
        }
        const renderPipes = renderer.renderPipes;
        this._updateCachedRenderGroups(container.renderGroup, null);
        this._updateRenderGroups(container.renderGroup);
        renderer.globalUniforms.start({
          worldTransformMatrix: transform ? container.renderGroup.localTransform : container.renderGroup.worldTransform,
          worldColor: container.renderGroup.worldColorAlpha
        });
        executeInstructions(container.renderGroup, renderPipes);
        if (renderPipes.uniformBatch) {
          renderPipes.uniformBatch.renderEnd();
        }
        if (transform) {
          container.renderGroup.localTransform.copyFrom(originalLocalTransform);
        }
        container.parent = parent;
        container.renderGroup.renderGroupParent = renderGroupParent;
      }
      destroy() {
        this._renderer = null;
      }
      _updateCachedRenderGroups(renderGroup, closestCacheAsTexture) {
        var _a, _b;
        renderGroup._parentCacheAsTextureRenderGroup = closestCacheAsTexture;
        if (renderGroup.isCachedAsTexture) {
          if (!renderGroup.textureNeedsUpdate)
            return;
          closestCacheAsTexture = renderGroup;
        }
        for (let i = renderGroup.renderGroupChildren.length - 1; i >= 0; i--) {
          this._updateCachedRenderGroups(renderGroup.renderGroupChildren[i], closestCacheAsTexture);
        }
        renderGroup.invalidateMatrices();
        if (renderGroup.isCachedAsTexture) {
          if (renderGroup.textureNeedsUpdate) {
            const bounds = renderGroup.root.getLocalBounds();
            bounds.ceil();
            const lastTexture = renderGroup.texture;
            if (renderGroup.texture) {
              TexturePool.returnTexture(renderGroup.texture, true);
            }
            const renderer = this._renderer;
            const resolution = renderGroup.textureOptions.resolution || renderer.view.resolution;
            const antialias = (_a = renderGroup.textureOptions.antialias) != null ? _a : renderer.view.antialias;
            const scaleMode = (_b = renderGroup.textureOptions.scaleMode) != null ? _b : "linear";
            const texture = TexturePool.getOptimalTexture(
              bounds.width,
              bounds.height,
              resolution,
              antialias
            );
            texture._source.style = new TextureStyle({ scaleMode });
            renderGroup.texture = texture;
            renderGroup._textureBounds || (renderGroup._textureBounds = new Bounds());
            renderGroup._textureBounds.copyFrom(bounds);
            if (lastTexture !== renderGroup.texture) {
              if (renderGroup.renderGroupParent) {
                renderGroup.renderGroupParent.structureDidChange = true;
              }
            }
          }
        } else if (renderGroup.texture) {
          TexturePool.returnTexture(renderGroup.texture, true);
          renderGroup.texture = null;
        }
      }
      _updateRenderGroups(renderGroup) {
        const renderer = this._renderer;
        const renderPipes = renderer.renderPipes;
        renderGroup.runOnRender(renderer);
        renderGroup.instructionSet.renderPipes = renderPipes;
        if (!renderGroup.structureDidChange) {
          validateRenderables(renderGroup, renderPipes);
        } else {
          clearList(renderGroup.childrenRenderablesToUpdate.list, 0);
        }
        updateRenderGroupTransforms(renderGroup);
        if (renderGroup.structureDidChange) {
          renderGroup.structureDidChange = false;
          this._buildInstructions(renderGroup, renderer);
        } else {
          this._updateRenderables(renderGroup);
        }
        renderGroup.childrenRenderablesToUpdate.index = 0;
        renderer.renderPipes.batch.upload(renderGroup.instructionSet);
        if (renderGroup.isCachedAsTexture && !renderGroup.textureNeedsUpdate)
          return;
        for (let i = 0; i < renderGroup.renderGroupChildren.length; i++) {
          this._updateRenderGroups(renderGroup.renderGroupChildren[i]);
        }
      }
      _updateRenderables(renderGroup) {
        const { list, index } = renderGroup.childrenRenderablesToUpdate;
        for (let i = 0; i < index; i++) {
          const container = list[i];
          if (container.didViewUpdate) {
            renderGroup.updateRenderable(container);
          }
        }
        clearList(list, index);
      }
      _buildInstructions(renderGroup, rendererOrPipes) {
        const root = renderGroup.root;
        const instructionSet = renderGroup.instructionSet;
        instructionSet.reset();
        const renderer = rendererOrPipes.renderPipes ? rendererOrPipes : rendererOrPipes.batch.renderer;
        const renderPipes = renderer.renderPipes;
        renderPipes.batch.buildStart(instructionSet);
        renderPipes.blendMode.buildStart();
        renderPipes.colorMask.buildStart();
        if (root.sortableChildren) {
          root.sortChildren();
        }
        root.collectRenderablesWithEffects(instructionSet, renderer, null);
        renderPipes.batch.buildEnd(instructionSet);
        renderPipes.blendMode.buildEnd(instructionSet);
      }
    }
    /** @ignore */
    RenderGroupSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "renderGroup"
    };

    "use strict";
    class SpritePipe {
      constructor(renderer) {
        this._renderer = renderer;
      }
      addRenderable(sprite, instructionSet) {
        const gpuSprite = this._getGpuSprite(sprite);
        if (sprite.didViewUpdate)
          this._updateBatchableSprite(sprite, gpuSprite);
        this._renderer.renderPipes.batch.addToBatch(gpuSprite, instructionSet);
      }
      updateRenderable(sprite) {
        const gpuSprite = this._getGpuSprite(sprite);
        if (sprite.didViewUpdate)
          this._updateBatchableSprite(sprite, gpuSprite);
        gpuSprite._batcher.updateElement(gpuSprite);
      }
      validateRenderable(sprite) {
        const gpuSprite = this._getGpuSprite(sprite);
        return !gpuSprite._batcher.checkAndUpdateTexture(
          gpuSprite,
          sprite._texture
        );
      }
      _updateBatchableSprite(sprite, batchableSprite) {
        batchableSprite.bounds = sprite.visualBounds;
        batchableSprite.texture = sprite._texture;
      }
      _getGpuSprite(sprite) {
        return sprite._gpuData[this._renderer.uid] || this._initGPUSprite(sprite);
      }
      _initGPUSprite(sprite) {
        const batchableSprite = new BatchableSprite();
        batchableSprite.renderable = sprite;
        batchableSprite.transform = sprite.groupTransform;
        batchableSprite.texture = sprite._texture;
        batchableSprite.bounds = sprite.visualBounds;
        batchableSprite.roundPixels = this._renderer._roundPixels | sprite._roundPixels;
        sprite._gpuData[this._renderer.uid] = batchableSprite;
        return batchableSprite;
      }
      destroy() {
        this._renderer = null;
      }
    }
    /** @ignore */
    SpritePipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "sprite"
    };

    "use strict";
    var __defProp$k = Object.defineProperty;
    var __getOwnPropSymbols$m = Object.getOwnPropertySymbols;
    var __hasOwnProp$m = Object.prototype.hasOwnProperty;
    var __propIsEnum$m = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$k = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$m.call(b, prop))
          __defNormalProp$k(a, prop, b[prop]);
      if (__getOwnPropSymbols$m)
        for (var prop of __getOwnPropSymbols$m(b)) {
          if (__propIsEnum$m.call(b, prop))
            __defNormalProp$k(a, prop, b[prop]);
        }
      return a;
    };
    const _BackgroundSystem = class _BackgroundSystem {
      constructor() {
        this.clearBeforeRender = true;
        this._backgroundColor = new Color(0);
        this.color = this._backgroundColor;
        this.alpha = 1;
      }
      /**
       * initiates the background system
       * @param options - the options for the background colors
       */
      init(options) {
        options = __spreadValues$k(__spreadValues$k({}, _BackgroundSystem.defaultOptions), options);
        this.clearBeforeRender = options.clearBeforeRender;
        this.color = options.background || options.backgroundColor || this._backgroundColor;
        this.alpha = options.backgroundAlpha;
        this._backgroundColor.setAlpha(options.backgroundAlpha);
      }
      /** The background color to fill if not transparent */
      get color() {
        return this._backgroundColor;
      }
      set color(value) {
        const incoming = Color.shared.setValue(value);
        if (incoming.alpha < 1 && this._backgroundColor.alpha === 1) {
          warn(
            "Cannot set a transparent background on an opaque canvas. To enable transparency, set backgroundAlpha < 1 when initializing your Application."
          );
        }
        this._backgroundColor.setValue(value);
      }
      /** The background color alpha. Setting this to 0 will make the canvas transparent. */
      get alpha() {
        return this._backgroundColor.alpha;
      }
      set alpha(value) {
        this._backgroundColor.setAlpha(value);
      }
      /** The background color as an [R, G, B, A] array. */
      get colorRgba() {
        return this._backgroundColor.toArray();
      }
      /**
       * destroys the background system
       * @internal
       */
      destroy() {
      }
    };
    /** @ignore */
    _BackgroundSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "background",
      priority: 0
    };
    /** default options used by the system */
    _BackgroundSystem.defaultOptions = {
      /**
       * {@link WebGLOptions.backgroundAlpha}
       * @default 1
       */
      backgroundAlpha: 1,
      /**
       * {@link WebGLOptions.backgroundColor}
       * @default 0x000000
       */
      backgroundColor: 0,
      /**
       * {@link WebGLOptions.clearBeforeRender}
       * @default true
       */
      clearBeforeRender: true
    };
    let BackgroundSystem = _BackgroundSystem;

    "use strict";
    const BLEND_MODE_FILTERS = {};
    extensions.handle(ExtensionType.BlendMode, (value) => {
      if (!value.name) {
        throw new Error("BlendMode extension must have a name property");
      }
      BLEND_MODE_FILTERS[value.name] = value.ref;
    }, (value) => {
      delete BLEND_MODE_FILTERS[value.name];
    });
    class BlendModePipe {
      constructor(renderer) {
        this._blendModeStack = [];
        this._isAdvanced = false;
        this._filterHash = /* @__PURE__ */ Object.create(null);
        this._renderer = renderer;
        this._renderer.runners.prerender.add(this);
      }
      prerender() {
        this._activeBlendMode = "normal";
        this._isAdvanced = false;
      }
      /**
       * Push a blend mode onto the internal stack and apply it to the instruction set if needed.
       * @param renderable - The renderable or {@link RenderGroup} associated with the change.
       * @param blendMode - The blend mode to activate.
       * @param instructionSet - The instruction set being built.
       */
      pushBlendMode(renderable, blendMode, instructionSet) {
        this._blendModeStack.push(blendMode);
        this.setBlendMode(renderable, blendMode, instructionSet);
      }
      /**
       * Pop the last blend mode from the stack and apply the new top-of-stack mode.
       * @param instructionSet - The instruction set being built.
       */
      popBlendMode(instructionSet) {
        var _a;
        this._blendModeStack.pop();
        const blendMode = (_a = this._blendModeStack[this._activeBlendMode.length - 1]) != null ? _a : "normal";
        this.setBlendMode(null, blendMode, instructionSet);
      }
      /**
       * Ensure a blend mode switch is added to the instruction set when the mode changes.
       * If an advanced blend mode is active, subsequent renderables will be collected so they can be
       * rendered within a single filter pass.
       * @param renderable - The renderable or {@link RenderGroup} to associate with the change, or null when unwinding.
       * @param blendMode - The target blend mode.
       * @param instructionSet - The instruction set being built.
       */
      setBlendMode(renderable, blendMode, instructionSet) {
        var _a;
        const isRenderGroup = renderable instanceof RenderGroup;
        if (this._activeBlendMode === blendMode) {
          if (this._isAdvanced && renderable && !isRenderGroup) {
            (_a = this._renderableList) == null ? void 0 : _a.push(renderable);
          }
          return;
        }
        if (this._isAdvanced)
          this._endAdvancedBlendMode(instructionSet);
        this._activeBlendMode = blendMode;
        if (!renderable)
          return;
        this._isAdvanced = !!BLEND_MODE_FILTERS[blendMode];
        if (this._isAdvanced)
          this._beginAdvancedBlendMode(renderable, instructionSet);
      }
      _beginAdvancedBlendMode(renderable, instructionSet) {
        this._renderer.renderPipes.batch.break(instructionSet);
        const blendMode = this._activeBlendMode;
        if (!BLEND_MODE_FILTERS[blendMode]) {
          warn(`Unable to assign BlendMode: '${blendMode}'. You may want to include: import 'pixi.js/advanced-blend-modes'`);
          return;
        }
        const filterEffect = this._ensureFilterEffect(blendMode);
        const isRenderGroup = renderable instanceof RenderGroup;
        const instruction = {
          renderPipeId: "filter",
          action: "pushFilter",
          filterEffect,
          renderables: isRenderGroup ? null : [renderable],
          container: isRenderGroup ? renderable.root : null,
          canBundle: false
        };
        this._renderableList = instruction.renderables;
        instructionSet.add(instruction);
      }
      _ensureFilterEffect(blendMode) {
        let filterEffect = this._filterHash[blendMode];
        if (!filterEffect) {
          filterEffect = this._filterHash[blendMode] = new FilterEffect();
          filterEffect.filters = [new BLEND_MODE_FILTERS[blendMode]()];
        }
        return filterEffect;
      }
      _endAdvancedBlendMode(instructionSet) {
        this._isAdvanced = false;
        this._renderableList = null;
        this._renderer.renderPipes.batch.break(instructionSet);
        instructionSet.add({
          renderPipeId: "filter",
          action: "popFilter",
          canBundle: false
        });
      }
      /**
       * called when the instruction build process is starting this will reset internally to the default blend mode
       * @internal
       */
      buildStart() {
        this._isAdvanced = false;
      }
      /**
       * called when the instruction build process is finished, ensuring that if there is an advanced blend mode
       * active, we add the final render instructions added to the instruction set
       * @param instructionSet - The instruction set we are adding to
       * @internal
       */
      buildEnd(instructionSet) {
        if (!this._isAdvanced)
          return;
        this._endAdvancedBlendMode(instructionSet);
      }
      /** @internal */
      destroy() {
        this._renderer = null;
        this._renderableList = null;
        for (const i in this._filterHash) {
          this._filterHash[i].destroy();
        }
        this._filterHash = null;
      }
    }
    /** @ignore */
    BlendModePipe.extension = {
      type: [
        ExtensionType.WebGLPipes,
        ExtensionType.WebGPUPipes,
        ExtensionType.CanvasPipes
      ],
      name: "blendMode"
    };

    "use strict";
    var __defProp$j = Object.defineProperty;
    var __getOwnPropSymbols$l = Object.getOwnPropertySymbols;
    var __hasOwnProp$l = Object.prototype.hasOwnProperty;
    var __propIsEnum$l = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$j = (obj, key, value) => key in obj ? __defProp$j(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$j = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$l.call(b, prop))
          __defNormalProp$j(a, prop, b[prop]);
      if (__getOwnPropSymbols$l)
        for (var prop of __getOwnPropSymbols$l(b)) {
          if (__propIsEnum$l.call(b, prop))
            __defNormalProp$j(a, prop, b[prop]);
        }
      return a;
    };
    const imageTypes = {
      png: "image/png",
      jpg: "image/jpeg",
      webp: "image/webp"
    };
    const _ExtractSystem = class _ExtractSystem {
      /** @param renderer - The renderer this System works for. */
      constructor(renderer) {
        this._renderer = renderer;
      }
      _normalizeOptions(options, defaults = {}) {
        if (options instanceof Container || options instanceof Texture) {
          return __spreadValues$j({
            target: options
          }, defaults);
        }
        return __spreadValues$j(__spreadValues$j({}, defaults), options);
      }
      /**
       * Creates an IImage from a display object or texture.
       * @param options - Options for creating the image, or the target to extract
       * @returns Promise that resolves with the generated IImage
       * @example
       * ```ts
       * // Basic usage with a sprite
       * const sprite = new Sprite(texture);
       * const image = await renderer.extract.image(sprite);
       * document.body.appendChild(image);
       *
       * // Advanced usage with options
       * const image = await renderer.extract.image({
       *     target: container,
       *     format: 'webp',
       *     quality: 0.8,
       *     frame: new Rectangle(0, 0, 100, 100),
       *     resolution: 2,
       *     clearColor: '#ff0000',
       *     antialias: true
       * });
       *
       * // Extract directly from a texture
       * const texture = Texture.from('myTexture.png');
       * const image = await renderer.extract.image(texture);
       * ```
       * @see {@link ExtractImageOptions} For detailed options
       * @see {@link ExtractSystem.base64} For base64 string output
       * @see {@link ExtractSystem.canvas} For canvas output
       * @see {@link ImageLike} For the image interface
       * @category rendering
       */
      async image(options) {
        const image = DOMAdapter.get().createImage();
        image.src = await this.base64(options);
        return image;
      }
      /**
       * Converts the target into a base64 encoded string.
       *
       * This method works by first creating
       * a canvas using `Extract.canvas` and then converting it to a base64 string.
       * @param options - The options for creating the base64 string, or the target to extract
       * @returns Promise that resolves with the base64 encoded string
       * @example
       * ```ts
       * // Basic usage with a sprite
       * const sprite = new Sprite(texture);
       * const base64 = await renderer.extract.base64(sprite);
       * console.log(base64); // data:image/png;base64,...
       *
       * // Advanced usage with options
       * const base64 = await renderer.extract.base64({
       *     target: container,
       *     format: 'webp',
       *     quality: 0.8,
       *     frame: new Rectangle(0, 0, 100, 100),
       *     resolution: 2
       * });
       * ```
       * @throws Will throw an error if the platform doesn't support any of:
       * - ICanvas.toDataURL
       * - ICanvas.toBlob
       * - ICanvas.convertToBlob
       * @see {@link ExtractImageOptions} For detailed options
       * @see {@link ExtractSystem.canvas} For canvas output
       * @see {@link ExtractSystem.image} For HTMLImage output
       * @category rendering
       */
      async base64(options) {
        options = this._normalizeOptions(
          options,
          _ExtractSystem.defaultImageOptions
        );
        const { format, quality } = options;
        const canvas = this.canvas(options);
        if (canvas.toBlob !== void 0) {
          return new Promise((resolve, reject) => {
            canvas.toBlob((blob) => {
              if (!blob) {
                reject(new Error("ICanvas.toBlob failed!"));
                return;
              }
              const reader = new FileReader();
              reader.onload = () => resolve(reader.result);
              reader.onerror = reject;
              reader.readAsDataURL(blob);
            }, imageTypes[format], quality);
          });
        }
        if (canvas.toDataURL !== void 0) {
          return canvas.toDataURL(imageTypes[format], quality);
        }
        if (canvas.convertToBlob !== void 0) {
          const blob = await canvas.convertToBlob({ type: imageTypes[format], quality });
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = reject;
            reader.readAsDataURL(blob);
          });
        }
        throw new Error("Extract.base64() requires ICanvas.toDataURL, ICanvas.toBlob, or ICanvas.convertToBlob to be implemented");
      }
      /**
       * Creates a Canvas element, renders the target to it and returns it.
       * This method is useful for creating static images or when you need direct canvas access.
       * @param options - The options for creating the canvas, or the target to extract
       * @returns A Canvas element with the texture rendered on
       * @example
       * ```ts
       * // Basic canvas extraction from a sprite
       * const sprite = new Sprite(texture);
       * const canvas = renderer.extract.canvas(sprite);
       * document.body.appendChild(canvas);
       *
       * // Extract with custom region
       * const canvas = renderer.extract.canvas({
       *     target: container,
       *     frame: new Rectangle(0, 0, 100, 100)
       * });
       *
       * // Extract with high resolution
       * const canvas = renderer.extract.canvas({
       *     target: sprite,
       *     resolution: 2,
       *     clearColor: '#ff0000'
       * });
       *
       * // Extract directly from a texture
       * const texture = Texture.from('myTexture.png');
       * const canvas = renderer.extract.canvas(texture);
       *
       * // Extract with anti-aliasing
       * const canvas = renderer.extract.canvas({
       *     target: graphics,
       *     antialias: true
       * });
       * ```
       * @see {@link ExtractOptions} For detailed options
       * @see {@link ExtractSystem.image} For HTMLImage output
       * @see {@link ExtractSystem.pixels} For raw pixel data
       * @category rendering
       */
      canvas(options) {
        options = this._normalizeOptions(options);
        const target = options.target;
        const renderer = this._renderer;
        if (target instanceof Texture) {
          return renderer.texture.generateCanvas(target);
        }
        const texture = renderer.textureGenerator.generateTexture(options);
        const canvas = renderer.texture.generateCanvas(texture);
        texture.destroy(true);
        return canvas;
      }
      /**
       * Returns a one-dimensional array containing the pixel data of the entire texture in RGBA order,
       * with integer values between 0 and 255 (inclusive).
       * > [!NOE] The returned array is a flat Uint8Array where every 4 values represent RGBA
       * @param options - The options for extracting the image, or the target to extract
       * @returns One-dimensional Uint8Array containing the pixel data in RGBA format
       * @example
       * ```ts
       * // Basic pixel extraction
       * const sprite = new Sprite(texture);
       * const pixels = renderer.extract.pixels(sprite);
       * console.log(pixels[0], pixels[1], pixels[2], pixels[3]); // R,G,B,A values
       *
       * // Extract with custom region
       * const pixels = renderer.extract.pixels({
       *     target: sprite,
       *     frame: new Rectangle(0, 0, 100, 100)
       * });
       *
       * // Extract with high resolution
       * const pixels = renderer.extract.pixels({
       *     target: sprite,
       *     resolution: 2
       * });
       * ```
       * @see {@link ExtractOptions} For detailed options
       * @see {@link ExtractSystem.canvas} For canvas output
       * @see {@link ExtractSystem.image} For image output
       * @category rendering
       */
      pixels(options) {
        options = this._normalizeOptions(options);
        const target = options.target;
        const renderer = this._renderer;
        const texture = target instanceof Texture ? target : renderer.textureGenerator.generateTexture(options);
        const pixelInfo = renderer.texture.getPixels(texture);
        if (target instanceof Container) {
          texture.destroy(true);
        }
        return pixelInfo;
      }
      /**
       * Creates a texture from a display object or existing texture.
       *
       * This is useful for creating
       * reusable textures from rendered content or making copies of existing textures.
       * > [!NOTE] The returned texture should be destroyed when no longer needed
       * @param options - The options for creating the texture, or the target to extract
       * @returns A new texture containing the extracted content
       * @example
       * ```ts
       * // Basic texture extraction from a sprite
       * const sprite = new Sprite(texture);
       * const extractedTexture = renderer.extract.texture(sprite);
       *
       * // Extract with custom region
       * const regionTexture = renderer.extract.texture({
       *     target: container,
       *     frame: new Rectangle(0, 0, 100, 100)
       * });
       *
       * // Extract with high resolution
       * const hiResTexture = renderer.extract.texture({
       *     target: sprite,
       *     resolution: 2,
       *     clearColor: '#ff0000'
       * });
       *
       * // Create a new sprite from extracted texture
       * const newSprite = new Sprite(
       *     renderer.extract.texture({
       *         target: graphics,
       *         antialias: true
       *     })
       * );
       *
       * // Clean up when done
       * extractedTexture.destroy(true);
       * ```
       * @see {@link ExtractOptions} For detailed options
       * @see {@link Texture} For texture management
       * @see {@link GenerateTextureSystem} For texture generation
       * @category rendering
       */
      texture(options) {
        options = this._normalizeOptions(options);
        if (options.target instanceof Texture)
          return options.target;
        return this._renderer.textureGenerator.generateTexture(options);
      }
      /**
       * Extracts and downloads content from the renderer as an image file.
       * This is a convenient way to save screenshots or export rendered content.
       * > [!NOTE] The download will use PNG format regardless of the filename extension
       * @param options - The options for downloading and extracting the image, or the target to extract
       * @example
       * ```ts
       * // Basic download with default filename
       * const sprite = new Sprite(texture);
       * renderer.extract.download(sprite); // Downloads as 'image.png'
       *
       * // Download with custom filename
       * renderer.extract.download({
       *     target: sprite,
       *     filename: 'screenshot.png'
       * });
       *
       * // Download with custom region
       * renderer.extract.download({
       *     target: container,
       *     filename: 'region.png',
       *     frame: new Rectangle(0, 0, 100, 100)
       * });
       *
       * // Download with high resolution and background
       * renderer.extract.download({
       *     target: stage,
       *     filename: 'hd-screenshot.png',
       *     resolution: 2,
       *     clearColor: '#ff0000'
       * });
       *
       * // Download with anti-aliasing
       * renderer.extract.download({
       *     target: graphics,
       *     filename: 'smooth.png',
       *     antialias: true
       * });
       * ```
       * @see {@link ExtractDownloadOptions} For detailed options
       * @see {@link ExtractSystem.image} For creating images without download
       * @see {@link ExtractSystem.canvas} For canvas output
       * @category rendering
       */
      download(options) {
        var _a;
        options = this._normalizeOptions(options);
        const canvas = this.canvas(options);
        const link = document.createElement("a");
        link.download = (_a = options.filename) != null ? _a : "image.png";
        link.href = canvas.toDataURL("image/png");
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
      /**
       * Logs the target to the console as an image. This is a useful way to debug what's happening in the renderer.
       * The image will be displayed in the browser's console using CSS background images.
       * @param options - The options for logging the image, or the target to log
       * @param options.width - The width of the logged image preview in the console (in pixels)
       * @example
       * ```ts
       * // Basic usage
       * const sprite = new Sprite(texture);
       * renderer.extract.log(sprite);
       * ```
       * @see {@link ExtractSystem.canvas} For getting raw canvas output
       * @see {@link ExtractSystem.pixels} For raw pixel data
       * @category rendering
       * @advanced
       */
      log(options) {
        var _a;
        const width = (_a = options.width) != null ? _a : 200;
        options = this._normalizeOptions(options);
        const canvas = this.canvas(options);
        const base64 = canvas.toDataURL();
        console.log(`[Pixi Texture] ${canvas.width}px ${canvas.height}px`);
        const style = [
          "font-size: 1px;",
          `padding: ${width}px ${300}px;`,
          `background: url(${base64}) no-repeat;`,
          "background-size: contain;"
        ].join(" ");
        console.log("%c ", style);
      }
      destroy() {
        this._renderer = null;
      }
    };
    /** @ignore */
    _ExtractSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "extract"
    };
    /**
     * Default options for image extraction.
     * @example
     * ```ts
     * // Customize default options
     * ExtractSystem.defaultImageOptions.format = 'webp';
     * ExtractSystem.defaultImageOptions.quality = 0.8;
     *
     * // Use defaults
     * const image = await renderer.extract.image(sprite);
     * ```
     */
    _ExtractSystem.defaultImageOptions = {
      format: "png",
      quality: 1
    };
    let ExtractSystem = _ExtractSystem;

    "use strict";
    var __getOwnPropSymbols$k = Object.getOwnPropertySymbols;
    var __hasOwnProp$k = Object.prototype.hasOwnProperty;
    var __propIsEnum$k = Object.prototype.propertyIsEnumerable;
    var __objRest$8 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$k.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$k)
        for (var prop of __getOwnPropSymbols$k(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$k.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class RenderTexture extends Texture {
      /**
       * Creates a RenderTexture. Pass `dynamic: true` in options to allow resizing after creation.
       * @param options - Options for the RenderTexture, including width, height, and dynamic.
       * @returns A new RenderTexture instance.
       * @example
       * const rt = RenderTexture.create({ width: 100, height: 100, dynamic: true });
       * rt.resize(500, 500);
       */
      static create(options) {
        const _a = options, { dynamic } = _a, rest = __objRest$8(_a, ["dynamic"]);
        return new RenderTexture({
          source: new TextureSource(rest),
          dynamic: dynamic != null ? dynamic : false
        });
      }
      /**
       * Resizes the render texture.
       * @param width - The new width of the render texture.
       * @param height - The new height of the render texture.
       * @param resolution - The new resolution of the render texture.
       * @returns This texture.
       */
      resize(width, height, resolution) {
        this.source.resize(width, height, resolution);
        return this;
      }
    }

    "use strict";
    var __defProp$i = Object.defineProperty;
    var __defProps$9 = Object.defineProperties;
    var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$j = Object.getOwnPropertySymbols;
    var __hasOwnProp$j = Object.prototype.hasOwnProperty;
    var __propIsEnum$j = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$i = (obj, key, value) => key in obj ? __defProp$i(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$i = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$j.call(b, prop))
          __defNormalProp$i(a, prop, b[prop]);
      if (__getOwnPropSymbols$j)
        for (var prop of __getOwnPropSymbols$j(b)) {
          if (__propIsEnum$j.call(b, prop))
            __defNormalProp$i(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$9 = (a, b) => __defProps$9(a, __getOwnPropDescs$9(b));
    const tempRect = new Rectangle();
    const tempBounds = new Bounds();
    const noColor = [0, 0, 0, 0];
    class GenerateTextureSystem {
      constructor(renderer) {
        this._renderer = renderer;
      }
      /**
       * Creates a texture from a display object that can be used for creating sprites and other textures.
       * This is particularly useful for optimizing performance when a complex container needs to be reused.
       * @param options - Generate texture options or a container to convert to texture
       * @returns A new RenderTexture containing the rendered display object
       * @example
       * ```ts
       * // Basic usage with a container
       * const container = new Container();
       * container.addChild(
       *     new Graphics()
       *         .circle(0, 0, 50)
       *         .fill('red')
       * );
       *
       * const texture = renderer.textureGenerator.generateTexture(container);
       *
       * // Advanced usage with options
       * const texture = renderer.textureGenerator.generateTexture({
       *     target: container,
       *     frame: new Rectangle(0, 0, 100, 100), // Specific region
       *     resolution: 2,                        // High DPI
       *     clearColor: '#ff0000',               // Red background
       *     antialias: true                      // Smooth edges
       * });
       *
       * // Create a sprite from the generated texture
       * const sprite = new Sprite(texture);
       *
       * // Clean up when done
       * texture.destroy(true);
       * ```
       * @see {@link GenerateTextureOptions} For detailed texture generation options
       * @see {@link RenderTexture} For the type of texture created
       * @category rendering
       */
      generateTexture(options) {
        var _a;
        if (options instanceof Container) {
          options = {
            target: options,
            frame: void 0,
            textureSourceOptions: {},
            resolution: void 0
          };
        }
        const resolution = options.resolution || this._renderer.resolution;
        const antialias = options.antialias || this._renderer.view.antialias;
        const container = options.target;
        let clearColor = options.clearColor;
        if (clearColor) {
          const isRGBAArray = Array.isArray(clearColor) && clearColor.length === 4;
          clearColor = isRGBAArray ? clearColor : Color.shared.setValue(clearColor).toArray();
        } else {
          clearColor = noColor;
        }
        const region = ((_a = options.frame) == null ? void 0 : _a.copyTo(tempRect)) || getLocalBounds(container, tempBounds).rectangle;
        region.width = Math.max(region.width, 1 / resolution) | 0;
        region.height = Math.max(region.height, 1 / resolution) | 0;
        const target = RenderTexture.create(__spreadProps$9(__spreadValues$i({}, options.textureSourceOptions), {
          width: region.width,
          height: region.height,
          resolution,
          antialias
        }));
        const transform = Matrix.shared.translate(-region.x, -region.y);
        this._renderer.render({
          container,
          transform,
          target,
          clearColor
        });
        target.source.updateMipmaps();
        return target;
      }
      destroy() {
        this._renderer = null;
      }
    }
    /** @ignore */
    GenerateTextureSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "textureGenerator"
    };

    "use strict";
    var __defProp$h = Object.defineProperty;
    var __getOwnPropSymbols$i = Object.getOwnPropertySymbols;
    var __hasOwnProp$i = Object.prototype.hasOwnProperty;
    var __propIsEnum$i = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$h = (obj, key, value) => key in obj ? __defProp$h(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$h = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$i.call(b, prop))
          __defNormalProp$h(a, prop, b[prop]);
      if (__getOwnPropSymbols$i)
        for (var prop of __getOwnPropSymbols$i(b)) {
          if (__propIsEnum$i.call(b, prop))
            __defNormalProp$h(a, prop, b[prop]);
        }
      return a;
    };
    const _GCSystem = class _GCSystem {
      /**
       * Creates a new GCSystem instance.
       * @param renderer - The renderer this garbage collection system works for
       */
      constructor(renderer) {
        /** Array of resources being tracked for garbage collection */
        this._managedResources = [];
        this._managedResourceHashes = [];
        this._ready = false;
        this._renderer = renderer;
      }
      /**
       * Initializes the garbage collection system with the provided options.
       * @param options - Configuration options
       */
      init(options) {
        options = __spreadValues$h(__spreadValues$h({}, _GCSystem.defaultOptions), options);
        this.maxUnusedTime = options.gcMaxUnusedTime;
        this._frequency = options.gcFrequency;
        this.enabled = options.gcActive;
        this.now = performance.now();
      }
      /**
       * Gets whether the garbage collection system is currently enabled.
       * @returns True if GC is enabled, false otherwise
       */
      get enabled() {
        return !!this._handler;
      }
      /**
       * Enables or disables the garbage collection system.
       * When enabled, schedules periodic cleanup of resources.
       * When disabled, cancels all scheduled cleanups.
       */
      set enabled(value) {
        if (this.enabled === value)
          return;
        if (value) {
          this._handler = this._renderer.scheduler.repeat(
            () => {
              this._ready = true;
            },
            this._frequency,
            false
          );
        } else {
          this._renderer.scheduler.cancel(this._handler);
          this._handler = 0;
        }
      }
      /**
       * Called before rendering. Updates the current timestamp.
       * @param options - The render options
       * @param options.container - The container to render
       */
      prerender({ container }) {
        this.now = performance.now();
        container.renderGroup.gcTick = this._renderer.tick++;
        this._updateInstructionGCTick(container.renderGroup, container.renderGroup.gcTick);
      }
      /** Performs garbage collection after rendering. */
      postrender() {
        if (!this._ready || !this.enabled)
          return;
        this.run();
        this._ready = false;
      }
      /**
       * Updates the GC tick counter for a render group and its children.
       * @param renderGroup - The render group to update
       * @param gcTick - The new tick value
       */
      _updateInstructionGCTick(renderGroup, gcTick) {
        renderGroup.instructionSet.gcTick = gcTick;
        for (const child of renderGroup.renderGroupChildren) {
          this._updateInstructionGCTick(child, gcTick);
        }
      }
      /**
       * Registers a resource for garbage collection tracking.
       * @param resource - The resource to track
       * @param type - The type of resource to track
       */
      addResource(resource, type) {
        var _a, _b;
        if (resource._gcLastUsed !== -1) {
          resource._gcLastUsed = this.now;
          (_a = resource._onTouch) == null ? void 0 : _a.call(resource, this.now);
          return;
        }
        const index = this._managedResources.length;
        resource._gcData = {
          index,
          type
        };
        resource._gcLastUsed = this.now;
        (_b = resource._onTouch) == null ? void 0 : _b.call(resource, this.now);
        resource.once("unload", this.removeResource, this);
        this._managedResources.push(resource);
      }
      /**
       * Removes a resource from garbage collection tracking.
       * Call this when manually destroying a resource.
       * @param resource - The resource to stop tracking
       */
      removeResource(resource) {
        const gcData = resource._gcData;
        if (!gcData)
          return;
        const index = gcData.index;
        const last = this._managedResources.length - 1;
        if (index !== last) {
          const lastResource = this._managedResources[last];
          this._managedResources[index] = lastResource;
          lastResource._gcData.index = index;
        }
        this._managedResources.length--;
        resource._gcData = null;
        resource._gcLastUsed = -1;
      }
      /**
       * Registers a hash-based resource collection for garbage collection tracking.
       * Resources in the hash will be automatically tracked and cleaned up when unused.
       * @param context - The object containing the hash property
       * @param hash - The property name on context that holds the resource hash
       * @param type - The type of resources in the hash ('resource' or 'renderable')
       * @param priority - Processing priority (lower values are processed first)
       */
      addResourceHash(context, hash, type, priority = 0) {
        this._managedResourceHashes.push({
          context,
          hash,
          type,
          priority
        });
        this._managedResourceHashes.sort((a, b) => a.priority - b.priority);
      }
      /**
       * Performs garbage collection by cleaning up unused resources.
       * Removes resources that haven't been used for longer than maxUnusedTime.
       */
      run() {
        const now = performance.now();
        const managedResourceHashes = this._managedResourceHashes;
        for (const hashEntry of managedResourceHashes) {
          this.runOnHash(hashEntry, now);
        }
        let writeIndex = 0;
        for (let i = 0; i < this._managedResources.length; i++) {
          const resource = this._managedResources[i];
          writeIndex = this.runOnResource(resource, now, writeIndex);
        }
        this._managedResources.length = writeIndex;
      }
      updateRenderableGCTick(renderable, now) {
        var _a, _b, _c, _d, _e;
        const renderGroup = (_a = renderable.renderGroup) != null ? _a : renderable.parentRenderGroup;
        const currentTick = (_c = (_b = renderGroup == null ? void 0 : renderGroup.instructionSet) == null ? void 0 : _b.gcTick) != null ? _c : -1;
        if (((_d = renderGroup == null ? void 0 : renderGroup.gcTick) != null ? _d : 0) === currentTick) {
          renderable._gcLastUsed = now;
          (_e = renderable._onTouch) == null ? void 0 : _e.call(renderable, now);
        }
      }
      runOnResource(resource, now, writeIndex) {
        const gcData = resource._gcData;
        if (gcData.type === "renderable") {
          this.updateRenderableGCTick(resource, now);
        }
        const isRecentlyUsed = now - resource._gcLastUsed < this.maxUnusedTime;
        if (isRecentlyUsed || !resource.autoGarbageCollect) {
          this._managedResources[writeIndex] = resource;
          gcData.index = writeIndex;
          writeIndex++;
        } else {
          resource.unload();
          resource._gcData = null;
          resource._gcLastUsed = -1;
          resource.off("unload", this.removeResource, this);
        }
        return writeIndex;
      }
      /**
       * Creates a clone of the hash, copying all non-null entries up to (but not including) the stop key.
       * @param hashValue - The original hash to clone from
       * @param stopKey - The key to stop at (exclusive)
       * @returns A new hash object with copied entries
       */
      _createHashClone(hashValue, stopKey) {
        const hashClone = /* @__PURE__ */ Object.create(null);
        for (const k in hashValue) {
          if (k === stopKey)
            break;
          if (hashValue[k] !== null)
            hashClone[k] = hashValue[k];
        }
        return hashClone;
      }
      runOnHash(hashEntry, now) {
        var _a;
        const { context, hash, type } = hashEntry;
        const hashValue = context[hash];
        let hashClone = null;
        let nullCount = 0;
        for (const key in hashValue) {
          const resource = hashValue[key];
          if (resource === null) {
            nullCount++;
            if (nullCount === 1e4 && !hashClone) {
              hashClone = this._createHashClone(hashValue, key);
            }
            continue;
          }
          if (resource._gcLastUsed === -1) {
            resource._gcLastUsed = now;
            (_a = resource._onTouch) == null ? void 0 : _a.call(resource, now);
            if (hashClone)
              hashClone[key] = resource;
            continue;
          }
          if (type === "renderable") {
            this.updateRenderableGCTick(resource, now);
          }
          const isRecentlyUsed = now - resource._gcLastUsed < this.maxUnusedTime;
          if (!isRecentlyUsed && resource.autoGarbageCollect) {
            if (!hashClone) {
              if (nullCount + 1 !== 1e4) {
                hashValue[key] = null;
                nullCount++;
              } else {
                hashClone = this._createHashClone(hashValue, key);
              }
            }
            resource.unload();
            resource._gcData = null;
            resource._gcLastUsed = -1;
          } else if (hashClone) {
            hashClone[key] = resource;
          }
        }
        if (hashClone) {
          context[hash] = hashClone;
        }
      }
      /** Cleans up the garbage collection system. Disables GC and removes all tracked resources. */
      destroy() {
        this.enabled = false;
        this._managedResources.forEach((resource) => {
          resource.off("unload", this.removeResource, this);
        });
        this._managedResources.length = 0;
        this._managedResourceHashes.length = 0;
        this._renderer = null;
      }
    };
    /** @ignore */
    _GCSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "gc",
      priority: 0
    };
    /** Default options for the GCSystem */
    _GCSystem.defaultOptions = {
      /** Enable/disable the garbage collector */
      gcActive: true,
      /** Time in ms before an unused resource is collected (default 1 minute) */
      gcMaxUnusedTime: 6e4,
      /** How often to run garbage collection in ms (default 30 seconds) */
      gcFrequency: 3e4
    };
    let GCSystem = _GCSystem;

    "use strict";
    class GlobalUniformSystem {
      constructor(renderer) {
        this._stackIndex = 0;
        this._globalUniformDataStack = [];
        this._uniformsPool = [];
        this._activeUniforms = [];
        this._bindGroupPool = [];
        this._activeBindGroups = [];
        this._renderer = renderer;
      }
      reset() {
        this._stackIndex = 0;
        for (let i = 0; i < this._activeUniforms.length; i++) {
          this._uniformsPool.push(this._activeUniforms[i]);
        }
        for (let i = 0; i < this._activeBindGroups.length; i++) {
          this._bindGroupPool.push(this._activeBindGroups[i]);
        }
        this._activeUniforms.length = 0;
        this._activeBindGroups.length = 0;
      }
      start(options) {
        this.reset();
        this.push(options);
      }
      bind({
        size,
        projectionMatrix,
        worldTransformMatrix,
        worldColor,
        offset
      }) {
        const renderTarget = this._renderer.renderTarget.renderTarget;
        const currentGlobalUniformData = this._stackIndex ? this._globalUniformDataStack[this._stackIndex - 1] : {
          projectionData: renderTarget,
          worldTransformMatrix: new Matrix(),
          worldColor: 4294967295,
          offset: new Point()
        };
        const globalUniformData = {
          projectionMatrix: projectionMatrix || this._renderer.renderTarget.projectionMatrix,
          resolution: size || renderTarget.size,
          worldTransformMatrix: worldTransformMatrix || currentGlobalUniformData.worldTransformMatrix,
          worldColor: worldColor || currentGlobalUniformData.worldColor,
          offset: offset || currentGlobalUniformData.offset,
          bindGroup: null
        };
        const uniformGroup = this._uniformsPool.pop() || this._createUniforms();
        this._activeUniforms.push(uniformGroup);
        const uniforms = uniformGroup.uniforms;
        uniforms.uProjectionMatrix = globalUniformData.projectionMatrix;
        uniforms.uResolution = globalUniformData.resolution;
        uniforms.uWorldTransformMatrix.copyFrom(globalUniformData.worldTransformMatrix);
        uniforms.uWorldTransformMatrix.tx -= globalUniformData.offset.x;
        uniforms.uWorldTransformMatrix.ty -= globalUniformData.offset.y;
        color32BitToUniform(
          globalUniformData.worldColor,
          uniforms.uWorldColorAlpha,
          0
        );
        uniformGroup.update();
        let bindGroup;
        if (this._renderer.renderPipes.uniformBatch) {
          bindGroup = this._renderer.renderPipes.uniformBatch.getUniformBindGroup(uniformGroup, false);
        } else {
          bindGroup = this._bindGroupPool.pop() || new BindGroup();
          this._activeBindGroups.push(bindGroup);
          bindGroup.setResource(uniformGroup, 0);
        }
        globalUniformData.bindGroup = bindGroup;
        this._currentGlobalUniformData = globalUniformData;
      }
      push(options) {
        this.bind(options);
        this._globalUniformDataStack[this._stackIndex++] = this._currentGlobalUniformData;
      }
      pop() {
        this._currentGlobalUniformData = this._globalUniformDataStack[--this._stackIndex - 1];
        if (this._renderer.type === RendererType.WEBGL) {
          this._currentGlobalUniformData.bindGroup.resources[0].update();
        }
      }
      get bindGroup() {
        return this._currentGlobalUniformData.bindGroup;
      }
      get globalUniformData() {
        return this._currentGlobalUniformData;
      }
      get uniformGroup() {
        return this._currentGlobalUniformData.bindGroup.resources[0];
      }
      _createUniforms() {
        const globalUniforms = new UniformGroup({
          uProjectionMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uWorldTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          // TODO - someone smart - set this to be a unorm8x4 rather than a vec4<f32>
          uWorldColorAlpha: { value: new Float32Array(4), type: "vec4<f32>" },
          uResolution: { value: [0, 0], type: "vec2<f32>" }
        }, {
          isStatic: true
        });
        return globalUniforms;
      }
      destroy() {
        this._renderer = null;
        this._globalUniformDataStack.length = 0;
        this._uniformsPool.length = 0;
        this._activeUniforms.length = 0;
        this._bindGroupPool.length = 0;
        this._activeBindGroups.length = 0;
        this._currentGlobalUniformData = null;
      }
    }
    /** @ignore */
    GlobalUniformSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "globalUniforms"
    };

    "use strict";
    let uid = 1;
    class SchedulerSystem {
      constructor() {
        this._tasks = [];
        /** a small off set to apply to the repeat schedules. This is just to make sure they run at slightly different times */
        this._offset = 0;
      }
      /** Initializes the scheduler system and starts the ticker. */
      init() {
        Ticker.system.add(this._update, this);
      }
      /**
       * Schedules a repeating task.
       * @param func - The function to execute.
       * @param duration - The interval duration in milliseconds.
       * @param useOffset - this will spread out tasks so that they do not all run at the same time
       * @returns The unique identifier for the scheduled task.
       */
      repeat(func, duration, useOffset = true) {
        const id = uid++;
        let offset = 0;
        if (useOffset) {
          this._offset += 1e3;
          offset = this._offset;
        }
        this._tasks.push({
          func,
          duration,
          start: performance.now(),
          offset,
          last: performance.now(),
          repeat: true,
          id
        });
        return id;
      }
      /**
       * Cancels a scheduled task.
       * @param id - The unique identifier of the task to cancel.
       */
      cancel(id) {
        for (let i = 0; i < this._tasks.length; i++) {
          if (this._tasks[i].id === id) {
            this._tasks.splice(i, 1);
            return;
          }
        }
      }
      /**
       * Updates and executes the scheduled tasks.
       * @private
       */
      _update() {
        const now = performance.now();
        for (let i = 0; i < this._tasks.length; i++) {
          const task = this._tasks[i];
          if (now - task.offset - task.last >= task.duration) {
            const elapsed = now - task.start;
            task.func(elapsed);
            task.last = now;
          }
        }
      }
      /**
       * Destroys the scheduler system and removes all tasks.
       * @internal
       */
      destroy() {
        Ticker.system.remove(this._update, this);
        this._tasks.length = 0;
      }
    }
    /** @ignore */
    SchedulerSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "scheduler",
      priority: 0
    };

    "use strict";
    let saidHello = false;
    function sayHello(type) {
      if (saidHello) {
        return;
      }
      if (DOMAdapter.get().getNavigator().userAgent.toLowerCase().indexOf("chrome") > -1) {
        const args = [
          `%c  %c  %c  %c  %c PixiJS %c v${VERSION} (${type}) http://www.pixijs.com/

`,
          "background: #E72264; padding:5px 0;",
          "background: #6CA2EA; padding:5px 0;",
          "background: #B5D33D; padding:5px 0;",
          "background: #FED23F; padding:5px 0;",
          "color: #FFFFFF; background: #E72264; padding:5px 0;",
          "color: #E72264; background: #FFFFFF; padding:5px 0;"
        ];
        globalThis.console.log(...args);
      } else if (globalThis.console) {
        globalThis.console.log(`PixiJS ${VERSION} - ${type} - http://www.pixijs.com/`);
      }
      saidHello = true;
    }

    "use strict";
    class HelloSystem {
      constructor(renderer) {
        this._renderer = renderer;
      }
      /**
       * It all starts here! This initiates every system, passing in the options for any system by name.
       * @param options - the config for the renderer and all its systems
       */
      init(options) {
        if (options.hello) {
          let name = this._renderer.name;
          if (this._renderer.type === RendererType.WEBGL) {
            name += ` ${this._renderer.context.webGLVersion}`;
          }
          sayHello(name);
        }
      }
    }
    /** @ignore */
    HelloSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "hello",
      priority: -2
    };
    /** The default options for the system. */
    HelloSystem.defaultOptions = {
      /** {@link WebGLOptions.hello} */
      hello: false
    };

    "use strict";
    function cleanHash(hash) {
      let clean = false;
      for (const i in hash) {
        if (hash[i] == void 0) {
          clean = true;
          break;
        }
      }
      if (!clean)
        return hash;
      const cleanHash2 = /* @__PURE__ */ Object.create(null);
      for (const i in hash) {
        const value = hash[i];
        if (value) {
          cleanHash2[i] = value;
        }
      }
      return cleanHash2;
    }
    function cleanArray(arr) {
      let offset = 0;
      for (let i = 0; i < arr.length; i++) {
        if (arr[i] == void 0) {
          offset++;
        } else {
          arr[i - offset] = arr[i];
        }
      }
      arr.length -= offset;
      return arr;
    }

    "use strict";
    var __defProp$g = Object.defineProperty;
    var __getOwnPropSymbols$h = Object.getOwnPropertySymbols;
    var __hasOwnProp$h = Object.prototype.hasOwnProperty;
    var __propIsEnum$h = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$g = (obj, key, value) => key in obj ? __defProp$g(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$g = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$h.call(b, prop))
          __defNormalProp$g(a, prop, b[prop]);
      if (__getOwnPropSymbols$h)
        for (var prop of __getOwnPropSymbols$h(b)) {
          if (__propIsEnum$h.call(b, prop))
            __defNormalProp$g(a, prop, b[prop]);
        }
      return a;
    };
    let renderableGCTick = 0;
    const _RenderableGCSystem = class _RenderableGCSystem {
      /**
       * Creates a new RenderableGCSystem instance.
       * @param renderer - The renderer this garbage collection system works for
       */
      constructor(renderer) {
        /** Array of renderables being tracked for garbage collection */
        this._managedRenderables = [];
        /** Array of hash objects being tracked for cleanup */
        this._managedHashes = [];
        /** Array of arrays being tracked for cleanup */
        this._managedArrays = [];
        this._renderer = renderer;
      }
      /**
       * Initializes the garbage collection system with the provided options.
       * @param options - Configuration options for the renderer
       */
      init(options) {
        options = __spreadValues$g(__spreadValues$g({}, _RenderableGCSystem.defaultOptions), options);
        this.maxUnusedTime = options.renderableGCMaxUnusedTime;
        this._frequency = options.renderableGCFrequency;
        this.enabled = options.renderableGCActive;
      }
      /**
       * Gets whether the garbage collection system is currently enabled.
       * @returns True if GC is enabled, false otherwise
       */
      get enabled() {
        return !!this._handler;
      }
      /**
       * Enables or disables the garbage collection system.
       * When enabled, schedules periodic cleanup of resources.
       * When disabled, cancels all scheduled cleanups.
       */
      set enabled(value) {
        if (this.enabled === value)
          return;
        if (value) {
          this._handler = this._renderer.scheduler.repeat(
            () => this.run(),
            this._frequency,
            false
          );
          this._hashHandler = this._renderer.scheduler.repeat(
            () => {
              for (const hash of this._managedHashes) {
                hash.context[hash.hash] = cleanHash(hash.context[hash.hash]);
              }
            },
            this._frequency
          );
          this._arrayHandler = this._renderer.scheduler.repeat(
            () => {
              for (const array of this._managedArrays) {
                cleanArray(array.context[array.hash]);
              }
            },
            this._frequency
          );
        } else {
          this._renderer.scheduler.cancel(this._handler);
          this._renderer.scheduler.cancel(this._hashHandler);
          this._renderer.scheduler.cancel(this._arrayHandler);
        }
      }
      /**
       * Adds a hash table to be managed by the garbage collector.
       * @param context - The object containing the hash table
       * @param hash - The property name of the hash table
       */
      addManagedHash(context, hash) {
        this._managedHashes.push({ context, hash });
      }
      /**
       * Adds an array to be managed by the garbage collector.
       * @param context - The object containing the array
       * @param hash - The property name of the array
       */
      addManagedArray(context, hash) {
        this._managedArrays.push({ context, hash });
      }
      /**
       * Updates the GC timestamp and tracking before rendering.
       * @param options - The render options
       * @param options.container - The container to render
       */
      prerender({
        container
      }) {
        this._now = performance.now();
        container.renderGroup.gcTick = renderableGCTick++;
        this._updateInstructionGCTick(container.renderGroup, container.renderGroup.gcTick);
      }
      /**
       * Starts tracking a renderable for garbage collection.
       * @param renderable - The renderable to track
       */
      addRenderable(renderable) {
        if (!this.enabled)
          return;
        if (renderable._lastUsed === -1) {
          this._managedRenderables.push(renderable);
          renderable.once("destroyed", this._removeRenderable, this);
        }
        renderable._lastUsed = this._now;
      }
      /**
       * Performs garbage collection by cleaning up unused renderables.
       * Removes renderables that haven't been used for longer than maxUnusedTime.
       */
      run() {
        var _a, _b, _c, _d;
        const now = this._now;
        const managedRenderables = this._managedRenderables;
        const renderPipes = this._renderer.renderPipes;
        let offset = 0;
        for (let i = 0; i < managedRenderables.length; i++) {
          const renderable = managedRenderables[i];
          if (renderable === null) {
            offset++;
            continue;
          }
          const renderGroup = (_a = renderable.renderGroup) != null ? _a : renderable.parentRenderGroup;
          const currentTick = (_c = (_b = renderGroup == null ? void 0 : renderGroup.instructionSet) == null ? void 0 : _b.gcTick) != null ? _c : -1;
          if (((_d = renderGroup == null ? void 0 : renderGroup.gcTick) != null ? _d : 0) === currentTick) {
            renderable._lastUsed = now;
          }
          if (now - renderable._lastUsed > this.maxUnusedTime) {
            if (!renderable.destroyed) {
              const rp = renderPipes;
              if (renderGroup)
                renderGroup.structureDidChange = true;
              rp[renderable.renderPipeId].destroyRenderable(renderable);
            }
            renderable._lastUsed = -1;
            offset++;
            renderable.off("destroyed", this._removeRenderable, this);
          } else {
            managedRenderables[i - offset] = renderable;
          }
        }
        managedRenderables.length -= offset;
      }
      /** Cleans up the garbage collection system. Disables GC and removes all tracked resources. */
      destroy() {
        this.enabled = false;
        this._renderer = null;
        this._managedRenderables.length = 0;
        this._managedHashes.length = 0;
        this._managedArrays.length = 0;
      }
      /**
       * Removes a renderable from being tracked when it's destroyed.
       * @param renderable - The renderable to stop tracking
       */
      _removeRenderable(renderable) {
        const index = this._managedRenderables.indexOf(renderable);
        if (index >= 0) {
          renderable.off("destroyed", this._removeRenderable, this);
          this._managedRenderables[index] = null;
        }
      }
      /**
       * Updates the GC tick counter for a render group and its children.
       * @param renderGroup - The render group to update
       * @param gcTick - The new tick value
       */
      _updateInstructionGCTick(renderGroup, gcTick) {
        renderGroup.instructionSet.gcTick = gcTick;
        for (const child of renderGroup.renderGroupChildren) {
          this._updateInstructionGCTick(child, gcTick);
        }
      }
    };
    /**
     * Extension metadata for registering this system with the renderer.
     * @ignore
     */
    _RenderableGCSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "renderableGC",
      priority: 0
    };
    /**
     * Default configuration options for the garbage collection system.
     * These can be overridden when initializing the renderer.
     */
    _RenderableGCSystem.defaultOptions = {
      /** Enable/disable the garbage collector */
      renderableGCActive: true,
      /** Time in ms before an unused resource is collected (default 1 minute) */
      renderableGCMaxUnusedTime: 6e4,
      /** How often to run garbage collection in ms (default 30 seconds) */
      renderableGCFrequency: 3e4
    };
    let RenderableGCSystem = _RenderableGCSystem;

    "use strict";
    const _TextureGCSystem = class _TextureGCSystem {
      /**
       * Frame count since started.
       * @readonly
       * @deprecated since 8.15.0
       */
      get count() {
        return this._renderer.tick;
      }
      /**
       * Frame count since last garbage collection.
       * @readonly
       * @deprecated since 8.15.0
       */
      get checkCount() {
        return this._checkCount;
      }
      set checkCount(value) {
        deprecation("8.15.0", "TextureGCSystem.run is deprecated, please use the GCSystem instead.");
        this._checkCount = value;
      }
      /**
       * Maximum idle frames before a texture is destroyed by garbage collection.
       * @see TextureGCSystem.defaultMaxIdle
       * @deprecated since 8.15.0
       */
      get maxIdle() {
        return this._renderer.gc.maxUnusedTime / 1e3 * 60;
      }
      set maxIdle(value) {
        deprecation("8.15.0", "TextureGCSystem.run is deprecated, please use the GCSystem instead.");
        this._renderer.gc.maxUnusedTime = value / 60 * 1e3;
      }
      /**
       * Frames between two garbage collections.
       * @see TextureGCSystem.defaultCheckCountMax
       * @deprecated since 8.15.0
       */
      // eslint-disable-next-line dot-notation
      get checkCountMax() {
        return Math.floor(this._renderer.gc["_frequency"] / 1e3);
      }
      set checkCountMax(_value) {
        deprecation("8.15.0", "TextureGCSystem.run is deprecated, please use the GCSystem instead.");
      }
      /**
       * Current garbage collection mode.
       * @see TextureGCSystem.defaultMode
       * @deprecated since 8.15.0
       */
      get active() {
        return this._renderer.gc.enabled;
      }
      set active(value) {
        deprecation("8.15.0", "TextureGCSystem.run is deprecated, please use the GCSystem instead.");
        this._renderer.gc.enabled = value;
      }
      /** @param renderer - The renderer this System works for. */
      constructor(renderer) {
        this._renderer = renderer;
        this._checkCount = 0;
      }
      init(options) {
        if (options.textureGCActive !== _TextureGCSystem.defaultOptions.textureGCActive) {
          this.active = options.textureGCActive;
        }
        if (options.textureGCMaxIdle !== _TextureGCSystem.defaultOptions.textureGCMaxIdle) {
          this.maxIdle = options.textureGCMaxIdle;
        }
        if (options.textureGCCheckCountMax !== _TextureGCSystem.defaultOptions.textureGCCheckCountMax) {
          this.checkCountMax = options.textureGCCheckCountMax;
        }
      }
      /**
       * Checks to see when the last time a texture was used.
       * If the texture has not been used for a specified amount of time, it will be removed from the GPU.
       * @deprecated since 8.15.0
       */
      run() {
        deprecation("8.15.0", "TextureGCSystem.run is deprecated, please use the GCSystem instead.");
        this._renderer.gc.run();
      }
      destroy() {
        this._renderer = null;
      }
    };
    /** @ignore */
    _TextureGCSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem
      ],
      name: "textureGC"
    };
    /**
     * Default options for the TextureGCSystem
     * @deprecated since 8.15.0
     */
    _TextureGCSystem.defaultOptions = {
      /**
       * If set to true, this will enable the garbage collector on the GPU.
       * @default true
       */
      textureGCActive: true,
      /**
       * @deprecated since 8.3.0
       * @see {@link TextureGCSystemOptions.textureGCMaxIdle}
       */
      textureGCAMaxIdle: null,
      /**
       * The maximum idle frames before a texture is destroyed by garbage collection.
       * @default 60 * 60
       */
      textureGCMaxIdle: 60 * 60,
      /**
       * Frames between two garbage collections.
       * @default 600
       */
      textureGCCheckCountMax: 600
    };
    let TextureGCSystem = _TextureGCSystem;

    "use strict";
    var __defProp$f = Object.defineProperty;
    var __getOwnPropSymbols$g = Object.getOwnPropertySymbols;
    var __hasOwnProp$g = Object.prototype.hasOwnProperty;
    var __propIsEnum$g = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$f = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$g.call(b, prop))
          __defNormalProp$f(a, prop, b[prop]);
      if (__getOwnPropSymbols$g)
        for (var prop of __getOwnPropSymbols$g(b)) {
          if (__propIsEnum$g.call(b, prop))
            __defNormalProp$f(a, prop, b[prop]);
        }
      return a;
    };
    const _ViewSystem = class _ViewSystem {
      /**
       * Whether CSS dimensions of canvas view should be resized to screen dimensions automatically.
       * This is only supported for HTMLCanvasElement and will be ignored if the canvas is an OffscreenCanvas.
       * @type {boolean}
       */
      get autoDensity() {
        return this.texture.source.autoDensity;
      }
      set autoDensity(value) {
        this.texture.source.autoDensity = value;
      }
      /** The resolution / device pixel ratio of the renderer. */
      get resolution() {
        return this.texture.source._resolution;
      }
      set resolution(value) {
        this.texture.source.resize(
          this.texture.source.width,
          this.texture.source.height,
          value
        );
      }
      /**
       * initiates the view system
       * @param options - the options for the view
       */
      init(options) {
        options = __spreadValues$f(__spreadValues$f({}, _ViewSystem.defaultOptions), options);
        if (options.view) {
          deprecation(v8_0_0, "ViewSystem.view has been renamed to ViewSystem.canvas");
          options.canvas = options.view;
        }
        this.screen = new Rectangle(0, 0, options.width, options.height);
        this.canvas = options.canvas || DOMAdapter.get().createCanvas();
        this.antialias = !!options.antialias;
        this.texture = getCanvasTexture(this.canvas, options);
        this.renderTarget = new RenderTarget({
          colorTextures: [this.texture],
          depth: !!options.depth,
          isRoot: true
        });
        this.texture.source.transparent = options.backgroundAlpha < 1;
        this.resolution = options.resolution;
      }
      /**
       * Resizes the screen and canvas to the specified dimensions.
       * @param desiredScreenWidth - The new width of the screen.
       * @param desiredScreenHeight - The new height of the screen.
       * @param resolution
       */
      resize(desiredScreenWidth, desiredScreenHeight, resolution) {
        this.texture.source.resize(desiredScreenWidth, desiredScreenHeight, resolution);
        this.screen.width = this.texture.frame.width;
        this.screen.height = this.texture.frame.height;
      }
      /**
       * Destroys this System and optionally removes the canvas from the dom.
       * @param {options | false} options - The options for destroying the view, or "false".
       * @example
       * viewSystem.destroy();
       * viewSystem.destroy(true);
       * viewSystem.destroy({ removeView: true });
       */
      destroy(options = false) {
        const removeView = typeof options === "boolean" ? options : !!(options == null ? void 0 : options.removeView);
        if (removeView && this.canvas.parentNode) {
          this.canvas.parentNode.removeChild(this.canvas);
        }
        this.texture.destroy();
      }
    };
    /** @ignore */
    _ViewSystem.extension = {
      type: [
        ExtensionType.WebGLSystem,
        ExtensionType.WebGPUSystem,
        ExtensionType.CanvasSystem
      ],
      name: "view",
      priority: 0
    };
    /** The default options for the view system. */
    _ViewSystem.defaultOptions = {
      /**
       * {@link WebGLOptions.width}
       * @default 800
       */
      width: 800,
      /**
       * {@link WebGLOptions.height}
       * @default 600
       */
      height: 600,
      /**
       * {@link WebGLOptions.autoDensity}
       * @default false
       */
      autoDensity: false,
      /**
       * {@link WebGLOptions.antialias}
       * @default false
       */
      antialias: false
    };
    let ViewSystem = _ViewSystem;

    "use strict";
    const SharedSystems = [
      BackgroundSystem,
      GlobalUniformSystem,
      HelloSystem,
      ViewSystem,
      RenderGroupSystem,
      GCSystem,
      TextureGCSystem,
      GenerateTextureSystem,
      ExtractSystem,
      RendererInitHook,
      RenderableGCSystem,
      SchedulerSystem
    ];
    const SharedRenderPipes = [
      BlendModePipe,
      BatcherPipe,
      SpritePipe,
      RenderGroupPipe,
      AlphaMaskPipe,
      StencilMaskPipe,
      ColorMaskPipe,
      CustomRenderPipe
    ];

    "use strict";
    const DefaultWebGLSystems = [
      ...SharedSystems,
      GlUboSystem,
      GlBackBufferSystem,
      GlContextSystem,
      GlLimitsSystem,
      GlBufferSystem,
      GlTextureSystem,
      GlRenderTargetSystem,
      GlGeometrySystem,
      GlUniformGroupSystem,
      GlShaderSystem,
      GlEncoderSystem,
      GlStateSystem,
      GlStencilSystem,
      GlColorMaskSystem
    ];
    const DefaultWebGLPipes = [...SharedRenderPipes];
    const DefaultWebGLAdapters = [GlBatchAdaptor, GlMeshAdaptor, GlGraphicsAdaptor];
    const systems$1 = [];
    const renderPipes$1 = [];
    const renderPipeAdaptors$1 = [];
    extensions.handleByNamedList(ExtensionType.WebGLSystem, systems$1);
    extensions.handleByNamedList(ExtensionType.WebGLPipes, renderPipes$1);
    extensions.handleByNamedList(ExtensionType.WebGLPipesAdaptor, renderPipeAdaptors$1);
    extensions.add(...DefaultWebGLSystems, ...DefaultWebGLPipes, ...DefaultWebGLAdapters);
    class WebGLRenderer extends AbstractRenderer {
      constructor() {
        const systemConfig = {
          name: "webgl",
          type: RendererType.WEBGL,
          systems: systems$1,
          renderPipes: renderPipes$1,
          renderPipeAdaptors: renderPipeAdaptors$1
        };
        super(systemConfig);
      }
    }

    var WebGLRenderer$1 = {
        __proto__: null,
        WebGLRenderer: WebGLRenderer
    };

    "use strict";
    class BindGroupSystem {
      constructor(renderer) {
        this._hash = /* @__PURE__ */ Object.create(null);
        this._renderer = renderer;
      }
      contextChange(gpu) {
        this._gpu = gpu;
      }
      getBindGroup(bindGroup, program, groupIndex) {
        bindGroup._updateKey();
        const gpuBindGroup = this._hash[bindGroup._key] || this._createBindGroup(bindGroup, program, groupIndex);
        return gpuBindGroup;
      }
      _createBindGroup(group, program, groupIndex) {
        var _a;
        const device = this._gpu.device;
        const groupLayout = program.layout[groupIndex];
        const entries = [];
        const renderer = this._renderer;
        for (const j in groupLayout) {
          const resource = (_a = group.resources[j]) != null ? _a : group.resources[groupLayout[j]];
          let gpuResource;
          if (resource._resourceType === "uniformGroup") {
            const uniformGroup = resource;
            renderer.ubo.updateUniformGroup(uniformGroup);
            const buffer = uniformGroup.buffer;
            gpuResource = {
              buffer: renderer.buffer.getGPUBuffer(buffer),
              offset: 0,
              size: buffer.descriptor.size
            };
          } else if (resource._resourceType === "buffer") {
            const buffer = resource;
            gpuResource = {
              buffer: renderer.buffer.getGPUBuffer(buffer),
              offset: 0,
              size: buffer.descriptor.size
            };
          } else if (resource._resourceType === "bufferResource") {
            const bufferResource = resource;
            gpuResource = {
              buffer: renderer.buffer.getGPUBuffer(bufferResource.buffer),
              offset: bufferResource.offset,
              size: bufferResource.size
            };
          } else if (resource._resourceType === "textureSampler") {
            const sampler = resource;
            gpuResource = renderer.texture.getGpuSampler(sampler);
          } else if (resource._resourceType === "textureSource") {
            const texture = resource;
            gpuResource = renderer.texture.getGpuSource(texture).createView();
          }
          entries.push({
            binding: groupLayout[j],
            resource: gpuResource
          });
        }
        const layout = renderer.shader.getProgramData(program).bindGroups[groupIndex];
        const gpuBindGroup = device.createBindGroup({
          layout,
          entries
        });
        this._hash[group._key] = gpuBindGroup;
        return gpuBindGroup;
      }
      destroy() {
        this._hash = null;
        this._renderer = null;
      }
    }
    /** @ignore */
    BindGroupSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "bindGroup"
    };

    "use strict";
    class GpuBufferData {
      constructor(gpuBuffer) {
        this.gpuBuffer = gpuBuffer;
      }
      destroy() {
        this.gpuBuffer.destroy();
        this.gpuBuffer = null;
      }
    }
    class GpuBufferSystem {
      constructor(renderer) {
        this._renderer = renderer;
        this._managedBuffers = new GCManagedHash({
          renderer,
          type: "resource",
          onUnload: this.onBufferUnload.bind(this),
          name: "gpuBuffer"
        });
      }
      contextChange(gpu) {
        this._gpu = gpu;
      }
      getGPUBuffer(buffer) {
        var _a;
        buffer._gcLastUsed = this._renderer.gc.now;
        return ((_a = buffer._gpuData[this._renderer.uid]) == null ? void 0 : _a.gpuBuffer) || this.createGPUBuffer(buffer);
      }
      updateBuffer(buffer) {
        const gpuBuffer = this.getGPUBuffer(buffer);
        const data = buffer.data;
        if (buffer._updateID && data) {
          buffer._updateID = 0;
          this._gpu.device.queue.writeBuffer(
            gpuBuffer,
            0,
            data.buffer,
            0,
            // round to the nearest 4 bytes
            (buffer._updateSize || data.byteLength) + 3 & ~3
          );
        }
        return gpuBuffer;
      }
      /** dispose all WebGL resources of all managed buffers */
      destroyAll() {
        this._managedBuffers.removeAll();
      }
      onBufferUnload(buffer) {
        buffer.off("update", this.updateBuffer, this);
        buffer.off("change", this.onBufferChange, this);
      }
      createGPUBuffer(buffer) {
        const gpuBuffer = this._gpu.device.createBuffer(buffer.descriptor);
        buffer._updateID = 0;
        buffer._resourceId = uid$1("resource");
        if (buffer.data) {
          fastCopy(buffer.data.buffer, gpuBuffer.getMappedRange());
          gpuBuffer.unmap();
        }
        buffer._gpuData[this._renderer.uid] = new GpuBufferData(gpuBuffer);
        if (this._managedBuffers.add(buffer)) {
          buffer.on("update", this.updateBuffer, this);
          buffer.on("change", this.onBufferChange, this);
        }
        return gpuBuffer;
      }
      onBufferChange(buffer) {
        this._managedBuffers.remove(buffer);
        buffer._updateID = 0;
        this.createGPUBuffer(buffer);
      }
      destroy() {
        this._managedBuffers.destroy();
        this._renderer = null;
        this._gpu = null;
      }
    }
    /** @ignore */
    GpuBufferSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "buffer"
    };

    "use strict";
    class UboBatch {
      constructor({ minUniformOffsetAlignment }) {
        this._minUniformOffsetAlignment = 256;
        this.byteIndex = 0;
        this._minUniformOffsetAlignment = minUniformOffsetAlignment;
        this.data = new Float32Array(65535);
      }
      clear() {
        this.byteIndex = 0;
      }
      addEmptyGroup(size) {
        if (size > this._minUniformOffsetAlignment / 4) {
          throw new Error(`UniformBufferBatch: array is too large: ${size * 4}`);
        }
        const start = this.byteIndex;
        let newSize = start + size * 4;
        newSize = Math.ceil(newSize / this._minUniformOffsetAlignment) * this._minUniformOffsetAlignment;
        if (newSize > this.data.length * 4) {
          throw new Error("UniformBufferBatch: ubo batch got too big");
        }
        this.byteIndex = newSize;
        return start;
      }
      addGroup(array) {
        const offset = this.addEmptyGroup(array.length);
        for (let i = 0; i < array.length; i++) {
          this.data[offset / 4 + i] = array[i];
        }
        return offset;
      }
      destroy() {
        this.data = null;
      }
    }

    "use strict";
    class GpuColorMaskSystem {
      constructor(renderer) {
        this._colorMaskCache = 15;
        this._renderer = renderer;
      }
      setMask(colorMask) {
        if (this._colorMaskCache === colorMask)
          return;
        this._colorMaskCache = colorMask;
        this._renderer.pipeline.setColorMask(colorMask);
      }
      destroy() {
        this._renderer = null;
        this._colorMaskCache = null;
      }
    }
    /** @ignore */
    GpuColorMaskSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "colorMask"
    };

    "use strict";
    class GpuDeviceSystem {
      /**
       * @param {WebGPURenderer} renderer - The renderer this System works for.
       */
      constructor(renderer) {
        this._renderer = renderer;
      }
      async init(options) {
        if (this._initPromise)
          return this._initPromise;
        this._initPromise = (options.gpu ? Promise.resolve(options.gpu) : this._createDeviceAndAdaptor(options)).then((gpu) => {
          this.gpu = gpu;
          this._renderer.runners.contextChange.emit(this.gpu);
        });
        return this._initPromise;
      }
      /**
       * Handle the context change event
       * @param gpu
       */
      contextChange(gpu) {
        this._renderer.gpu = gpu;
      }
      /**
       * Helper class to create a WebGL Context
       * @param {object} options - An options object that gets passed in to the canvas element containing the
       *    context attributes
       * @see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext
       * @returns {WebGLRenderingContext} the WebGL context
       */
      async _createDeviceAndAdaptor(options) {
        const adapter = await DOMAdapter.get().getNavigator().gpu.requestAdapter({
          powerPreference: options.powerPreference,
          forceFallbackAdapter: options.forceFallbackAdapter
        });
        const requiredFeatures = [
          "texture-compression-bc",
          "texture-compression-astc",
          "texture-compression-etc2"
        ].filter((feature) => adapter.features.has(feature));
        const device = await adapter.requestDevice({
          requiredFeatures
        });
        return { adapter, device };
      }
      destroy() {
        this.gpu = null;
        this._renderer = null;
      }
    }
    /** @ignore */
    GpuDeviceSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "device"
    };
    /** The default options for the GpuDeviceSystem. */
    GpuDeviceSystem.defaultOptions = {
      /**
       * {@link WebGPUOptions.powerPreference}
       * @default default
       */
      powerPreference: void 0,
      /**
       * Force the use of the fallback adapter
       * @default false
       */
      forceFallbackAdapter: false
    };

    "use strict";
    var __defProp$e = Object.defineProperty;
    var __getOwnPropSymbols$f = Object.getOwnPropertySymbols;
    var __hasOwnProp$f = Object.prototype.hasOwnProperty;
    var __propIsEnum$f = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$e = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$f.call(b, prop))
          __defNormalProp$e(a, prop, b[prop]);
      if (__getOwnPropSymbols$f)
        for (var prop of __getOwnPropSymbols$f(b)) {
          if (__propIsEnum$f.call(b, prop))
            __defNormalProp$e(a, prop, b[prop]);
        }
      return a;
    };
    class GpuEncoderSystem {
      constructor(renderer) {
        this._boundBindGroup = /* @__PURE__ */ Object.create(null);
        this._boundVertexBuffer = /* @__PURE__ */ Object.create(null);
        this._renderer = renderer;
      }
      renderStart() {
        this.commandFinished = new Promise((resolve) => {
          this._resolveCommandFinished = resolve;
        });
        this.commandEncoder = this._renderer.gpu.device.createCommandEncoder();
      }
      beginRenderPass(gpuRenderTarget) {
        this.endRenderPass();
        this._clearCache();
        this.renderPassEncoder = this.commandEncoder.beginRenderPass(gpuRenderTarget.descriptor);
      }
      endRenderPass() {
        if (this.renderPassEncoder) {
          this.renderPassEncoder.end();
        }
        this.renderPassEncoder = null;
      }
      setViewport(viewport) {
        this.renderPassEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
      }
      setPipelineFromGeometryProgramAndState(geometry, program, state, topology) {
        const pipeline = this._renderer.pipeline.getPipeline(geometry, program, state, topology);
        this.setPipeline(pipeline);
      }
      setPipeline(pipeline) {
        if (this._boundPipeline === pipeline)
          return;
        this._boundPipeline = pipeline;
        this.renderPassEncoder.setPipeline(pipeline);
      }
      _setVertexBuffer(index, buffer) {
        if (this._boundVertexBuffer[index] === buffer)
          return;
        this._boundVertexBuffer[index] = buffer;
        this.renderPassEncoder.setVertexBuffer(index, this._renderer.buffer.updateBuffer(buffer));
      }
      _setIndexBuffer(buffer) {
        if (this._boundIndexBuffer === buffer)
          return;
        this._boundIndexBuffer = buffer;
        const indexFormat = buffer.data.BYTES_PER_ELEMENT === 2 ? "uint16" : "uint32";
        this.renderPassEncoder.setIndexBuffer(this._renderer.buffer.updateBuffer(buffer), indexFormat);
      }
      resetBindGroup(index) {
        this._boundBindGroup[index] = null;
      }
      setBindGroup(index, bindGroup, program) {
        if (this._boundBindGroup[index] === bindGroup)
          return;
        this._boundBindGroup[index] = bindGroup;
        bindGroup._touch(this._renderer.gc.now, this._renderer.tick);
        const gpuBindGroup = this._renderer.bindGroup.getBindGroup(bindGroup, program, index);
        this.renderPassEncoder.setBindGroup(index, gpuBindGroup);
      }
      setGeometry(geometry, program) {
        const buffersToBind = this._renderer.pipeline.getBufferNamesToBind(geometry, program);
        for (const i in buffersToBind) {
          this._setVertexBuffer(parseInt(i, 10), geometry.attributes[buffersToBind[i]].buffer);
        }
        if (geometry.indexBuffer) {
          this._setIndexBuffer(geometry.indexBuffer);
        }
      }
      _setShaderBindGroups(shader, skipSync) {
        for (const i in shader.groups) {
          const bindGroup = shader.groups[i];
          if (!skipSync) {
            this._syncBindGroup(bindGroup);
          }
          this.setBindGroup(i, bindGroup, shader.gpuProgram);
        }
      }
      _syncBindGroup(bindGroup) {
        for (const j in bindGroup.resources) {
          const resource = bindGroup.resources[j];
          if (resource.isUniformGroup) {
            this._renderer.ubo.updateUniformGroup(resource);
          }
        }
      }
      draw(options) {
        const { geometry, shader, state, topology, size, start, instanceCount, skipSync } = options;
        this.setPipelineFromGeometryProgramAndState(geometry, shader.gpuProgram, state, topology);
        this.setGeometry(geometry, shader.gpuProgram);
        this._setShaderBindGroups(shader, skipSync);
        if (geometry.indexBuffer) {
          this.renderPassEncoder.drawIndexed(
            size || geometry.indexBuffer.data.length,
            instanceCount != null ? instanceCount : geometry.instanceCount,
            start || 0
          );
        } else {
          this.renderPassEncoder.draw(size || geometry.getSize(), instanceCount != null ? instanceCount : geometry.instanceCount, start || 0);
        }
      }
      finishRenderPass() {
        if (this.renderPassEncoder) {
          this.renderPassEncoder.end();
          this.renderPassEncoder = null;
        }
      }
      postrender() {
        this.finishRenderPass();
        this._gpu.device.queue.submit([this.commandEncoder.finish()]);
        this._resolveCommandFinished();
        this.commandEncoder = null;
      }
      // restores a render pass if finishRenderPass was called
      // not optimised as really used for debugging!
      // used when we want to stop drawing and log a texture..
      restoreRenderPass() {
        const descriptor = this._renderer.renderTarget.adaptor.getDescriptor(
          this._renderer.renderTarget.renderTarget,
          false,
          [0, 0, 0, 1]
        );
        this.renderPassEncoder = this.commandEncoder.beginRenderPass(descriptor);
        const boundPipeline = this._boundPipeline;
        const boundVertexBuffer = __spreadValues$e({}, this._boundVertexBuffer);
        const boundIndexBuffer = this._boundIndexBuffer;
        const boundBindGroup = __spreadValues$e({}, this._boundBindGroup);
        this._clearCache();
        const viewport = this._renderer.renderTarget.viewport;
        this.renderPassEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
        this.setPipeline(boundPipeline);
        for (const i in boundVertexBuffer) {
          this._setVertexBuffer(i, boundVertexBuffer[i]);
        }
        for (const i in boundBindGroup) {
          this.setBindGroup(i, boundBindGroup[i], null);
        }
        this._setIndexBuffer(boundIndexBuffer);
      }
      _clearCache() {
        for (let i = 0; i < 16; i++) {
          this._boundBindGroup[i] = null;
          this._boundVertexBuffer[i] = null;
        }
        this._boundIndexBuffer = null;
        this._boundPipeline = null;
      }
      destroy() {
        this._renderer = null;
        this._gpu = null;
        this._boundBindGroup = null;
        this._boundVertexBuffer = null;
        this._boundIndexBuffer = null;
        this._boundPipeline = null;
      }
      contextChange(gpu) {
        this._gpu = gpu;
      }
    }
    /** @ignore */
    GpuEncoderSystem.extension = {
      type: [ExtensionType.WebGPUSystem],
      name: "encoder",
      priority: 1
    };

    "use strict";
    class GpuLimitsSystem {
      constructor(renderer) {
        this._renderer = renderer;
      }
      contextChange() {
        this.maxTextures = this._renderer.device.gpu.device.limits.maxSampledTexturesPerShaderStage;
        this.maxBatchableTextures = this.maxTextures;
      }
      destroy() {
      }
    }
    /** @ignore */
    GpuLimitsSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "limits"
    };

    "use strict";
    class GpuStencilSystem {
      constructor(renderer) {
        this._renderTargetStencilState = /* @__PURE__ */ Object.create(null);
        this._renderer = renderer;
        renderer.renderTarget.onRenderTargetChange.add(this);
      }
      onRenderTargetChange(renderTarget) {
        let stencilState = this._renderTargetStencilState[renderTarget.uid];
        if (!stencilState) {
          stencilState = this._renderTargetStencilState[renderTarget.uid] = {
            stencilMode: STENCIL_MODES.DISABLED,
            stencilReference: 0
          };
        }
        this._activeRenderTarget = renderTarget;
        this.setStencilMode(stencilState.stencilMode, stencilState.stencilReference);
      }
      setStencilMode(stencilMode, stencilReference) {
        const stencilState = this._renderTargetStencilState[this._activeRenderTarget.uid];
        stencilState.stencilMode = stencilMode;
        stencilState.stencilReference = stencilReference;
        const renderer = this._renderer;
        renderer.pipeline.setStencilMode(stencilMode);
        renderer.encoder.renderPassEncoder.setStencilReference(stencilReference);
      }
      destroy() {
        this._renderer.renderTarget.onRenderTargetChange.remove(this);
        this._renderer = null;
        this._activeRenderTarget = null;
        this._renderTargetStencilState = null;
      }
    }
    /** @ignore */
    GpuStencilSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "stencil"
    };

    "use strict";
    const WGSL_ALIGN_SIZE_DATA = {
      i32: { align: 4, size: 4 },
      u32: { align: 4, size: 4 },
      f32: { align: 4, size: 4 },
      f16: { align: 2, size: 2 },
      "vec2<i32>": { align: 8, size: 8 },
      "vec2<u32>": { align: 8, size: 8 },
      "vec2<f32>": { align: 8, size: 8 },
      "vec2<f16>": { align: 4, size: 4 },
      "vec3<i32>": { align: 16, size: 12 },
      "vec3<u32>": { align: 16, size: 12 },
      "vec3<f32>": { align: 16, size: 12 },
      "vec3<f16>": { align: 8, size: 6 },
      "vec4<i32>": { align: 16, size: 16 },
      "vec4<u32>": { align: 16, size: 16 },
      "vec4<f32>": { align: 16, size: 16 },
      "vec4<f16>": { align: 8, size: 8 },
      "mat2x2<f32>": { align: 8, size: 16 },
      "mat2x2<f16>": { align: 4, size: 8 },
      "mat3x2<f32>": { align: 8, size: 24 },
      "mat3x2<f16>": { align: 4, size: 12 },
      "mat4x2<f32>": { align: 8, size: 32 },
      "mat4x2<f16>": { align: 4, size: 16 },
      "mat2x3<f32>": { align: 16, size: 32 },
      "mat2x3<f16>": { align: 8, size: 16 },
      "mat3x3<f32>": { align: 16, size: 48 },
      "mat3x3<f16>": { align: 8, size: 24 },
      "mat4x3<f32>": { align: 16, size: 64 },
      "mat4x3<f16>": { align: 8, size: 32 },
      "mat2x4<f32>": { align: 16, size: 32 },
      "mat2x4<f16>": { align: 8, size: 16 },
      "mat3x4<f32>": { align: 16, size: 48 },
      "mat3x4<f16>": { align: 8, size: 24 },
      "mat4x4<f32>": { align: 16, size: 64 },
      "mat4x4<f16>": { align: 8, size: 32 }
    };
    function createUboElementsWGSL(uniformData) {
      const uboElements = uniformData.map((data) => ({
        data,
        offset: 0,
        size: 0
      }));
      let offset = 0;
      for (let i = 0; i < uboElements.length; i++) {
        const uboElement = uboElements[i];
        let size = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].size;
        const align = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].align;
        if (!WGSL_ALIGN_SIZE_DATA[uboElement.data.type]) {
          throw new Error(`[Pixi.js] WebGPU UniformBuffer: Unknown type ${uboElement.data.type}`);
        }
        if (uboElement.data.size > 1) {
          size = Math.max(size, align) * uboElement.data.size;
        }
        offset = Math.ceil(offset / align) * align;
        uboElement.size = size;
        uboElement.offset = offset;
        offset += size;
      }
      offset = Math.ceil(offset / 16) * 16;
      return { uboElements, size: offset };
    }

    "use strict";
    function generateArraySyncWGSL(uboElement, offsetToAdd) {
      const { size, align } = WGSL_ALIGN_SIZE_DATA[uboElement.data.type];
      const remainder = (align - size) / 4;
      const data = uboElement.data.type.indexOf("i32") >= 0 ? "dataInt32" : "data";
      return `
         v = uv.${uboElement.data.name};
         ${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ""}

         arrayOffset = offset;

         t = 0;

         for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)
         {
             for(var j = 0; j < ${size / 4}; j++)
             {
                 ${data}[arrayOffset++] = v[t++];
             }
             ${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
         }
     `;
    }

    "use strict";
    function createUboSyncFunctionWGSL(uboElements) {
      return createUboSyncFunction(
        uboElements,
        "uboWgsl",
        generateArraySyncWGSL,
        uboSyncFunctionsWGSL
      );
    }

    "use strict";
    class GpuUboSystem extends UboSystem {
      constructor() {
        super({
          createUboElements: createUboElementsWGSL,
          generateUboSync: createUboSyncFunctionWGSL
        });
      }
    }
    /** @ignore */
    GpuUboSystem.extension = {
      type: [ExtensionType.WebGPUSystem],
      name: "ubo"
    };

    "use strict";
    const minUniformOffsetAlignment = 128;
    class GpuUniformBatchPipe {
      constructor(renderer) {
        this._bindGroupHash = /* @__PURE__ */ Object.create(null);
        // number of buffers..
        this._buffers = [];
        this._bindGroups = [];
        this._bufferResources = [];
        this._renderer = renderer;
        this._batchBuffer = new UboBatch({ minUniformOffsetAlignment });
        const totalBuffers = 256 / minUniformOffsetAlignment;
        for (let i = 0; i < totalBuffers; i++) {
          let usage = BufferUsage.UNIFORM | BufferUsage.COPY_DST;
          if (i === 0)
            usage |= BufferUsage.COPY_SRC;
          this._buffers.push(new Buffer({
            data: this._batchBuffer.data,
            usage
          }));
        }
      }
      renderEnd() {
        this._uploadBindGroups();
        this._resetBindGroups();
      }
      _resetBindGroups() {
        this._bindGroupHash = /* @__PURE__ */ Object.create(null);
        this._batchBuffer.clear();
      }
      // just works for single bind groups for now
      getUniformBindGroup(group, duplicate) {
        if (!duplicate && this._bindGroupHash[group.uid]) {
          return this._bindGroupHash[group.uid];
        }
        this._renderer.ubo.ensureUniformGroup(group);
        const data = group.buffer.data;
        const offset = this._batchBuffer.addEmptyGroup(data.length);
        this._renderer.ubo.syncUniformGroup(group, this._batchBuffer.data, offset / 4);
        this._bindGroupHash[group.uid] = this._getBindGroup(offset / minUniformOffsetAlignment);
        return this._bindGroupHash[group.uid];
      }
      getUboResource(group) {
        this._renderer.ubo.updateUniformGroup(group);
        const data = group.buffer.data;
        const offset = this._batchBuffer.addGroup(data);
        return this._getBufferResource(offset / minUniformOffsetAlignment);
      }
      getArrayBindGroup(data) {
        const offset = this._batchBuffer.addGroup(data);
        return this._getBindGroup(offset / minUniformOffsetAlignment);
      }
      getArrayBufferResource(data) {
        const offset = this._batchBuffer.addGroup(data);
        const index = offset / minUniformOffsetAlignment;
        return this._getBufferResource(index);
      }
      _getBufferResource(index) {
        if (!this._bufferResources[index]) {
          const buffer = this._buffers[index % 2];
          this._bufferResources[index] = new BufferResource({
            buffer,
            offset: (index / 2 | 0) * 256,
            size: minUniformOffsetAlignment
          });
        }
        return this._bufferResources[index];
      }
      _getBindGroup(index) {
        if (!this._bindGroups[index]) {
          const bindGroup = new BindGroup({
            0: this._getBufferResource(index)
          });
          this._bindGroups[index] = bindGroup;
        }
        return this._bindGroups[index];
      }
      _uploadBindGroups() {
        const bufferSystem = this._renderer.buffer;
        const firstBuffer = this._buffers[0];
        firstBuffer.update(this._batchBuffer.byteIndex);
        bufferSystem.updateBuffer(firstBuffer);
        const commandEncoder = this._renderer.gpu.device.createCommandEncoder();
        for (let i = 1; i < this._buffers.length; i++) {
          const buffer = this._buffers[i];
          commandEncoder.copyBufferToBuffer(
            bufferSystem.getGPUBuffer(firstBuffer),
            minUniformOffsetAlignment,
            bufferSystem.getGPUBuffer(buffer),
            0,
            this._batchBuffer.byteIndex
          );
        }
        this._renderer.gpu.device.queue.submit([commandEncoder.finish()]);
      }
      destroy() {
        var _a;
        for (let i = 0; i < this._bindGroups.length; i++) {
          (_a = this._bindGroups[i]) == null ? void 0 : _a.destroy();
        }
        this._bindGroups = null;
        this._bindGroupHash = null;
        for (let i = 0; i < this._buffers.length; i++) {
          this._buffers[i].destroy();
        }
        this._buffers = null;
        for (let i = 0; i < this._bufferResources.length; i++) {
          this._bufferResources[i].destroy();
        }
        this._bufferResources = null;
        this._batchBuffer.destroy();
        this._renderer = null;
      }
    }
    /** @ignore */
    GpuUniformBatchPipe.extension = {
      type: [
        ExtensionType.WebGPUPipes
      ],
      name: "uniformBatch"
    };

    "use strict";
    var __defProp$d = Object.defineProperty;
    var __defProps$8 = Object.defineProperties;
    var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$e = Object.getOwnPropertySymbols;
    var __hasOwnProp$e = Object.prototype.hasOwnProperty;
    var __propIsEnum$e = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$d = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$e.call(b, prop))
          __defNormalProp$d(a, prop, b[prop]);
      if (__getOwnPropSymbols$e)
        for (var prop of __getOwnPropSymbols$e(b)) {
          if (__propIsEnum$e.call(b, prop))
            __defNormalProp$d(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
    const topologyStringToId = {
      "point-list": 0,
      "line-list": 1,
      "line-strip": 2,
      "triangle-list": 3,
      "triangle-strip": 4
    };
    function getGraphicsStateKey(geometryLayout, shaderKey, state, blendMode, topology) {
      return geometryLayout << 24 | shaderKey << 16 | state << 10 | blendMode << 5 | topology;
    }
    function getGlobalStateKey(stencilStateId, multiSampleCount, colorMask, renderTarget, colorTargetCount) {
      return colorMask << 8 | stencilStateId << 5 | renderTarget << 3 | colorTargetCount << 1 | multiSampleCount;
    }
    class PipelineSystem {
      constructor(renderer) {
        this._moduleCache = /* @__PURE__ */ Object.create(null);
        this._bufferLayoutsCache = /* @__PURE__ */ Object.create(null);
        this._bindingNamesCache = /* @__PURE__ */ Object.create(null);
        this._pipeCache = /* @__PURE__ */ Object.create(null);
        this._pipeStateCaches = /* @__PURE__ */ Object.create(null);
        this._colorMask = 15;
        this._multisampleCount = 1;
        this._colorTargetCount = 1;
        this._renderer = renderer;
      }
      contextChange(gpu) {
        this._gpu = gpu;
        this.setStencilMode(STENCIL_MODES.DISABLED);
        this._updatePipeHash();
      }
      setMultisampleCount(multisampleCount) {
        if (this._multisampleCount === multisampleCount)
          return;
        this._multisampleCount = multisampleCount;
        this._updatePipeHash();
      }
      setRenderTarget(renderTarget) {
        this._multisampleCount = renderTarget.msaaSamples;
        this._depthStencilAttachment = renderTarget.descriptor.depthStencilAttachment ? 1 : 0;
        this._colorTargetCount = renderTarget.colorTargetCount;
        this._updatePipeHash();
      }
      setColorMask(colorMask) {
        if (this._colorMask === colorMask)
          return;
        this._colorMask = colorMask;
        this._updatePipeHash();
      }
      setStencilMode(stencilMode) {
        if (this._stencilMode === stencilMode)
          return;
        this._stencilMode = stencilMode;
        this._stencilState = GpuStencilModesToPixi[stencilMode];
        this._updatePipeHash();
      }
      setPipeline(geometry, program, state, passEncoder) {
        const pipeline = this.getPipeline(geometry, program, state);
        passEncoder.setPipeline(pipeline);
      }
      getPipeline(geometry, program, state, topology) {
        if (!geometry._layoutKey) {
          ensureAttributes(geometry, program.attributeData);
          this._generateBufferKey(geometry);
        }
        topology || (topology = geometry.topology);
        const key = getGraphicsStateKey(
          geometry._layoutKey,
          program._layoutKey,
          state.data,
          state._blendModeId,
          topologyStringToId[topology]
        );
        if (this._pipeCache[key])
          return this._pipeCache[key];
        this._pipeCache[key] = this._createPipeline(geometry, program, state, topology);
        return this._pipeCache[key];
      }
      _createPipeline(geometry, program, state, topology) {
        const device = this._gpu.device;
        const buffers = this._createVertexBufferLayouts(geometry, program);
        const blendModes = this._renderer.state.getColorTargets(state, this._colorTargetCount);
        const writeMask = this._stencilMode === STENCIL_MODES.RENDERING_MASK_ADD ? 0 : this._colorMask;
        for (let i = 0; i < blendModes.length; i++) {
          blendModes[i].writeMask = writeMask;
        }
        const layout = this._renderer.shader.getProgramData(program).pipeline;
        const descriptor = {
          // TODO later check if its helpful to create..
          // layout,
          vertex: {
            module: this._getModule(program.vertex.source),
            entryPoint: program.vertex.entryPoint,
            // geometry..
            buffers
          },
          fragment: {
            module: this._getModule(program.fragment.source),
            entryPoint: program.fragment.entryPoint,
            targets: blendModes
          },
          primitive: {
            topology,
            cullMode: state.cullMode
          },
          layout,
          multisample: {
            count: this._multisampleCount
          },
          // depthStencil,
          label: `PIXI Pipeline`
        };
        if (this._depthStencilAttachment) {
          descriptor.depthStencil = __spreadProps$8(__spreadValues$d({}, this._stencilState), {
            format: "depth24plus-stencil8",
            depthWriteEnabled: state.depthTest,
            depthCompare: state.depthTest ? "less" : "always"
          });
        }
        const pipeline = device.createRenderPipeline(descriptor);
        return pipeline;
      }
      _getModule(code) {
        return this._moduleCache[code] || this._createModule(code);
      }
      _createModule(code) {
        const device = this._gpu.device;
        this._moduleCache[code] = device.createShaderModule({
          code
        });
        return this._moduleCache[code];
      }
      _generateBufferKey(geometry) {
        const keyGen = [];
        let index = 0;
        const attributeKeys = Object.keys(geometry.attributes).sort();
        for (let i = 0; i < attributeKeys.length; i++) {
          const attribute = geometry.attributes[attributeKeys[i]];
          keyGen[index++] = attribute.offset;
          keyGen[index++] = attribute.format;
          keyGen[index++] = attribute.stride;
          keyGen[index++] = attribute.instance;
        }
        const stringKey = keyGen.join("|");
        geometry._layoutKey = createIdFromString(stringKey, "geometry");
        return geometry._layoutKey;
      }
      _generateAttributeLocationsKey(program) {
        const keyGen = [];
        let index = 0;
        const attributeKeys = Object.keys(program.attributeData).sort();
        for (let i = 0; i < attributeKeys.length; i++) {
          const attribute = program.attributeData[attributeKeys[i]];
          keyGen[index++] = attribute.location;
        }
        const stringKey = keyGen.join("|");
        program._attributeLocationsKey = createIdFromString(stringKey, "programAttributes");
        return program._attributeLocationsKey;
      }
      /**
       * Returns a hash of buffer names mapped to bind locations.
       * This is used to bind the correct buffer to the correct location in the shader.
       * @param geometry - The geometry where to get the buffer names
       * @param program - The program where to get the buffer names
       * @returns An object of buffer names mapped to the bind location.
       */
      getBufferNamesToBind(geometry, program) {
        const key = geometry._layoutKey << 16 | program._attributeLocationsKey;
        if (this._bindingNamesCache[key])
          return this._bindingNamesCache[key];
        const data = this._createVertexBufferLayouts(geometry, program);
        const bufferNamesToBind = /* @__PURE__ */ Object.create(null);
        const attributeData = program.attributeData;
        for (let i = 0; i < data.length; i++) {
          const attributes = Object.values(data[i].attributes);
          const shaderLocation = attributes[0].shaderLocation;
          for (const j in attributeData) {
            if (attributeData[j].location === shaderLocation) {
              bufferNamesToBind[i] = j;
              break;
            }
          }
        }
        this._bindingNamesCache[key] = bufferNamesToBind;
        return bufferNamesToBind;
      }
      _createVertexBufferLayouts(geometry, program) {
        if (!program._attributeLocationsKey)
          this._generateAttributeLocationsKey(program);
        const key = geometry._layoutKey << 16 | program._attributeLocationsKey;
        if (this._bufferLayoutsCache[key]) {
          return this._bufferLayoutsCache[key];
        }
        const vertexBuffersLayout = [];
        geometry.buffers.forEach((buffer) => {
          var _a;
          const bufferEntry = {
            arrayStride: 0,
            stepMode: "vertex",
            attributes: []
          };
          const bufferEntryAttributes = bufferEntry.attributes;
          for (const i in program.attributeData) {
            const attribute = geometry.attributes[i];
            if (((_a = attribute.divisor) != null ? _a : 1) !== 1) {
              warn(`Attribute ${i} has an invalid divisor value of '${attribute.divisor}'. WebGPU only supports a divisor value of 1`);
            }
            if (attribute.buffer === buffer) {
              bufferEntry.arrayStride = attribute.stride;
              bufferEntry.stepMode = attribute.instance ? "instance" : "vertex";
              bufferEntryAttributes.push({
                shaderLocation: program.attributeData[i].location,
                offset: attribute.offset,
                format: attribute.format
              });
            }
          }
          if (bufferEntryAttributes.length) {
            vertexBuffersLayout.push(bufferEntry);
          }
        });
        this._bufferLayoutsCache[key] = vertexBuffersLayout;
        return vertexBuffersLayout;
      }
      _updatePipeHash() {
        const key = getGlobalStateKey(
          this._stencilMode,
          this._multisampleCount,
          this._colorMask,
          this._depthStencilAttachment,
          this._colorTargetCount
        );
        if (!this._pipeStateCaches[key]) {
          this._pipeStateCaches[key] = /* @__PURE__ */ Object.create(null);
        }
        this._pipeCache = this._pipeStateCaches[key];
      }
      destroy() {
        this._renderer = null;
        this._bufferLayoutsCache = null;
      }
    }
    /** @ignore */
    PipelineSystem.extension = {
      type: [ExtensionType.WebGPUSystem],
      name: "pipeline"
    };

    "use strict";
    class GpuRenderTarget {
      constructor() {
        this.contexts = [];
        this.msaaTextures = [];
        this.msaaSamples = 1;
      }
    }

    "use strict";
    class GpuRenderTargetAdaptor {
      init(renderer, renderTargetSystem) {
        this._renderer = renderer;
        this._renderTargetSystem = renderTargetSystem;
      }
      copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
        const renderer = this._renderer;
        const baseGpuTexture = this._getGpuColorTexture(
          sourceRenderSurfaceTexture
        );
        const backGpuTexture = renderer.texture.getGpuSource(
          destinationTexture.source
        );
        renderer.encoder.commandEncoder.copyTextureToTexture(
          {
            texture: baseGpuTexture,
            origin: originSrc
          },
          {
            texture: backGpuTexture,
            origin: originDest
          },
          size
        );
        return destinationTexture;
      }
      startRenderPass(renderTarget, clear = true, clearColor, viewport) {
        const renderTargetSystem = this._renderTargetSystem;
        const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
        const descriptor = this.getDescriptor(renderTarget, clear, clearColor);
        gpuRenderTarget.descriptor = descriptor;
        this._renderer.pipeline.setRenderTarget(gpuRenderTarget);
        this._renderer.encoder.beginRenderPass(gpuRenderTarget);
        this._renderer.encoder.setViewport(viewport);
      }
      finishRenderPass() {
        this._renderer.encoder.endRenderPass();
      }
      /**
       * returns the gpu texture for the first color texture in the render target
       * mainly used by the filter manager to get copy the texture for blending
       * @param renderTarget
       * @returns a gpu texture
       */
      _getGpuColorTexture(renderTarget) {
        const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
        if (gpuRenderTarget.contexts[0]) {
          return gpuRenderTarget.contexts[0].getCurrentTexture();
        }
        return this._renderer.texture.getGpuSource(
          renderTarget.colorTextures[0].source
        );
      }
      getDescriptor(renderTarget, clear, clearValue) {
        if (typeof clear === "boolean") {
          clear = clear ? CLEAR.ALL : CLEAR.NONE;
        }
        const renderTargetSystem = this._renderTargetSystem;
        const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
        const colorAttachments = renderTarget.colorTextures.map(
          (texture, i) => {
            const context = gpuRenderTarget.contexts[i];
            let view;
            let resolveTarget;
            if (context) {
              const currentTexture = context.getCurrentTexture();
              const canvasTextureView = currentTexture.createView();
              view = canvasTextureView;
            } else {
              view = this._renderer.texture.getGpuSource(texture).createView({
                mipLevelCount: 1
              });
            }
            if (gpuRenderTarget.msaaTextures[i]) {
              resolveTarget = view;
              view = this._renderer.texture.getTextureView(
                gpuRenderTarget.msaaTextures[i]
              );
            }
            const loadOp = clear & CLEAR.COLOR ? "clear" : "load";
            clearValue != null ? clearValue : clearValue = renderTargetSystem.defaultClearColor;
            return {
              view,
              resolveTarget,
              clearValue,
              storeOp: "store",
              loadOp
            };
          }
        );
        let depthStencilAttachment;
        if ((renderTarget.stencil || renderTarget.depth) && !renderTarget.depthStencilTexture) {
          renderTarget.ensureDepthStencilTexture();
          renderTarget.depthStencilTexture.source.sampleCount = gpuRenderTarget.msaa ? 4 : 1;
        }
        if (renderTarget.depthStencilTexture) {
          const stencilLoadOp = clear & CLEAR.STENCIL ? "clear" : "load";
          const depthLoadOp = clear & CLEAR.DEPTH ? "clear" : "load";
          depthStencilAttachment = {
            view: this._renderer.texture.getGpuSource(renderTarget.depthStencilTexture.source).createView(),
            stencilStoreOp: "store",
            stencilLoadOp,
            depthClearValue: 1,
            depthLoadOp,
            depthStoreOp: "store"
          };
        }
        const descriptor = {
          colorAttachments,
          depthStencilAttachment
        };
        return descriptor;
      }
      clear(renderTarget, clear = true, clearColor, viewport) {
        if (!clear)
          return;
        const { gpu, encoder } = this._renderer;
        const device = gpu.device;
        const standAlone = encoder.commandEncoder === null;
        if (standAlone) {
          const commandEncoder = device.createCommandEncoder();
          const renderPassDescriptor = this.getDescriptor(renderTarget, clear, clearColor);
          const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
          passEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
          passEncoder.end();
          const gpuCommands = commandEncoder.finish();
          device.queue.submit([gpuCommands]);
        } else {
          this.startRenderPass(renderTarget, clear, clearColor, viewport);
        }
      }
      initGpuRenderTarget(renderTarget) {
        renderTarget.isRoot = true;
        const gpuRenderTarget = new GpuRenderTarget();
        gpuRenderTarget.colorTargetCount = renderTarget.colorTextures.length;
        renderTarget.colorTextures.forEach((colorTexture, i) => {
          if (colorTexture instanceof CanvasSource) {
            const context = colorTexture.resource.getContext(
              "webgpu"
            );
            const alphaMode = colorTexture.transparent ? "premultiplied" : "opaque";
            try {
              context.configure({
                device: this._renderer.gpu.device,
                usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
                format: "bgra8unorm",
                alphaMode
              });
            } catch (e) {
              console.error(e);
            }
            gpuRenderTarget.contexts[i] = context;
          }
          gpuRenderTarget.msaa = colorTexture.source.antialias;
          if (colorTexture.source.antialias) {
            const msaaTexture = new TextureSource({
              width: 0,
              height: 0,
              sampleCount: 4
            });
            gpuRenderTarget.msaaTextures[i] = msaaTexture;
          }
        });
        if (gpuRenderTarget.msaa) {
          gpuRenderTarget.msaaSamples = 4;
          if (renderTarget.depthStencilTexture) {
            renderTarget.depthStencilTexture.source.sampleCount = 4;
          }
        }
        return gpuRenderTarget;
      }
      destroyGpuRenderTarget(gpuRenderTarget) {
        gpuRenderTarget.contexts.forEach((context) => {
          context.unconfigure();
        });
        gpuRenderTarget.msaaTextures.forEach((texture) => {
          texture.destroy();
        });
        gpuRenderTarget.msaaTextures.length = 0;
        gpuRenderTarget.contexts.length = 0;
      }
      ensureDepthStencilTexture(renderTarget) {
        const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
        if (renderTarget.depthStencilTexture && gpuRenderTarget.msaa) {
          renderTarget.depthStencilTexture.source.sampleCount = 4;
        }
      }
      resizeGpuRenderTarget(renderTarget) {
        const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
        gpuRenderTarget.width = renderTarget.width;
        gpuRenderTarget.height = renderTarget.height;
        if (gpuRenderTarget.msaa) {
          renderTarget.colorTextures.forEach((colorTexture, i) => {
            const msaaTexture = gpuRenderTarget.msaaTextures[i];
            msaaTexture == null ? void 0 : msaaTexture.resize(
              colorTexture.source.width,
              colorTexture.source.height,
              colorTexture.source._resolution
            );
          });
        }
      }
    }

    "use strict";
    class GpuRenderTargetSystem extends RenderTargetSystem {
      constructor(renderer) {
        super(renderer);
        this.adaptor = new GpuRenderTargetAdaptor();
        this.adaptor.init(renderer, this);
      }
    }
    /** @ignore */
    GpuRenderTargetSystem.extension = {
      type: [ExtensionType.WebGPUSystem],
      name: "renderTarget"
    };

    "use strict";

    "use strict";
    class GpuShaderSystem {
      constructor() {
        this._gpuProgramData = /* @__PURE__ */ Object.create(null);
      }
      contextChange(gpu) {
        this._gpu = gpu;
      }
      getProgramData(program) {
        return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);
      }
      _createGPUProgramData(program) {
        const device = this._gpu.device;
        const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));
        const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };
        this._gpuProgramData[program._layoutKey] = {
          bindGroups,
          pipeline: device.createPipelineLayout(pipelineLayoutDesc)
        };
        return this._gpuProgramData[program._layoutKey];
      }
      destroy() {
        this._gpu = null;
        this._gpuProgramData = null;
      }
    }
    /** @ignore */
    GpuShaderSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "shader"
    };

    "use strict";
    const GpuBlendModesToPixi = {};
    GpuBlendModesToPixi.normal = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.add = {
      alpha: {
        srcFactor: "src-alpha",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.multiply = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "dst",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.screen = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one-minus-src",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.overlay = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one-minus-src",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.none = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "zero",
        dstFactor: "zero",
        operation: "add"
      }
    };
    GpuBlendModesToPixi["normal-npm"] = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "src-alpha",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      }
    };
    GpuBlendModesToPixi["add-npm"] = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "add"
      },
      color: {
        srcFactor: "src-alpha",
        dstFactor: "one",
        operation: "add"
      }
    };
    GpuBlendModesToPixi["screen-npm"] = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "src-alpha",
        dstFactor: "one-minus-src",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.erase = {
      alpha: {
        srcFactor: "zero",
        dstFactor: "one-minus-src-alpha",
        operation: "add"
      },
      color: {
        srcFactor: "zero",
        dstFactor: "one-minus-src",
        operation: "add"
      }
    };
    GpuBlendModesToPixi.min = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "min"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "min"
      }
    };
    GpuBlendModesToPixi.max = {
      alpha: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "max"
      },
      color: {
        srcFactor: "one",
        dstFactor: "one",
        operation: "max"
      }
    };

    "use strict";
    class GpuStateSystem {
      constructor() {
        this.defaultState = new State();
        this.defaultState.blend = true;
      }
      contextChange(gpu) {
        this.gpu = gpu;
      }
      /**
       * Gets the blend mode data for the current state
       * @param state - The state to get the blend mode from
       * @param count - The number of color targets to create
       */
      getColorTargets(state, count) {
        const blend = GpuBlendModesToPixi[state.blendMode] || GpuBlendModesToPixi.normal;
        const targets = [];
        const target = {
          format: "bgra8unorm",
          writeMask: 0,
          blend
        };
        for (let i = 0; i < count; i++) {
          targets[i] = target;
        }
        return targets;
      }
      destroy() {
        this.gpu = null;
      }
    }
    /** @ignore */
    GpuStateSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "state"
    };

    "use strict";
    const gpuUploadBufferImageResource = {
      type: "image",
      upload(source, gpuTexture, gpu) {
        const resource = source.resource;
        const total = (source.pixelWidth | 0) * (source.pixelHeight | 0);
        const bytesPerPixel = resource.byteLength / total;
        gpu.device.queue.writeTexture(
          { texture: gpuTexture },
          resource,
          {
            offset: 0,
            rowsPerImage: source.pixelHeight,
            bytesPerRow: source.pixelWidth * bytesPerPixel
          },
          {
            width: source.pixelWidth,
            height: source.pixelHeight,
            depthOrArrayLayers: 1
          }
        );
      }
    };

    "use strict";
    const blockDataMap = {
      "bc1-rgba-unorm": { blockBytes: 8, blockWidth: 4, blockHeight: 4 },
      "bc2-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
      "bc3-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
      "bc7-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
      "etc1-rgb-unorm": { blockBytes: 8, blockWidth: 4, blockHeight: 4 },
      "etc2-rgba8unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
      "astc-4x4-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 }
    };
    const defaultBlockData = { blockBytes: 4, blockWidth: 1, blockHeight: 1 };
    const gpuUploadCompressedTextureResource = {
      type: "compressed",
      upload(source, gpuTexture, gpu) {
        let mipWidth = source.pixelWidth;
        let mipHeight = source.pixelHeight;
        const blockData = blockDataMap[source.format] || defaultBlockData;
        for (let i = 0; i < source.resource.length; i++) {
          const levelBuffer = source.resource[i];
          const bytesPerRow = Math.ceil(mipWidth / blockData.blockWidth) * blockData.blockBytes;
          gpu.device.queue.writeTexture(
            {
              texture: gpuTexture,
              mipLevel: i
            },
            levelBuffer,
            {
              offset: 0,
              bytesPerRow
            },
            {
              width: Math.ceil(mipWidth / blockData.blockWidth) * blockData.blockWidth,
              height: Math.ceil(mipHeight / blockData.blockHeight) * blockData.blockHeight,
              depthOrArrayLayers: 1
            }
          );
          mipWidth = Math.max(mipWidth >> 1, 1);
          mipHeight = Math.max(mipHeight >> 1, 1);
        }
      }
    };

    "use strict";
    const gpuUploadImageResource = {
      type: "image",
      upload(source, gpuTexture, gpu) {
        const resource = source.resource;
        if (!resource)
          return;
        if (globalThis.HTMLImageElement && resource instanceof HTMLImageElement) {
          const canvas = DOMAdapter.get().createCanvas(resource.width, resource.height);
          const context = canvas.getContext("2d");
          context.drawImage(resource, 0, 0, resource.width, resource.height);
          source.resource = canvas;
          warn("ImageSource: Image element passed, converting to canvas and replacing resource.");
        }
        const width = Math.min(gpuTexture.width, source.resourceWidth || source.pixelWidth);
        const height = Math.min(gpuTexture.height, source.resourceHeight || source.pixelHeight);
        const premultipliedAlpha = source.alphaMode === "premultiply-alpha-on-upload";
        gpu.device.queue.copyExternalImageToTexture(
          { source: resource },
          { texture: gpuTexture, premultipliedAlpha },
          {
            width,
            height
          }
        );
      }
    };

    "use strict";
    const gpuUploadVideoResource = {
      type: "video",
      upload(source, gpuTexture, gpu) {
        gpuUploadImageResource.upload(source, gpuTexture, gpu);
      }
    };

    "use strict";
    class GpuMipmapGenerator {
      constructor(device) {
        this.device = device;
        this.sampler = device.createSampler({ minFilter: "linear" });
        this.pipelines = {};
      }
      _getMipmapPipeline(format) {
        let pipeline = this.pipelines[format];
        if (!pipeline) {
          if (!this.mipmapShaderModule) {
            this.mipmapShaderModule = this.device.createShaderModule({
              code: (
                /* wgsl */
                `
                        var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
                        vec2<f32>(-1.0, -1.0), vec2<f32>(-1.0, 3.0), vec2<f32>(3.0, -1.0));

                        struct VertexOutput {
                        @builtin(position) position : vec4<f32>,
                        @location(0) texCoord : vec2<f32>,
                        };

                        @vertex
                        fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {
                        var output : VertexOutput;
                        output.texCoord = pos[vertexIndex] * vec2<f32>(0.5, -0.5) + vec2<f32>(0.5);
                        output.position = vec4<f32>(pos[vertexIndex], 0.0, 1.0);
                        return output;
                        }

                        @group(0) @binding(0) var imgSampler : sampler;
                        @group(0) @binding(1) var img : texture_2d<f32>;

                        @fragment
                        fn fragmentMain(@location(0) texCoord : vec2<f32>) -> @location(0) vec4<f32> {
                        return textureSample(img, imgSampler, texCoord);
                        }
                    `
              )
            });
          }
          pipeline = this.device.createRenderPipeline({
            layout: "auto",
            vertex: {
              module: this.mipmapShaderModule,
              entryPoint: "vertexMain"
            },
            fragment: {
              module: this.mipmapShaderModule,
              entryPoint: "fragmentMain",
              targets: [{ format }]
            }
          });
          this.pipelines[format] = pipeline;
        }
        return pipeline;
      }
      /**
       * Generates mipmaps for the given GPUTexture from the data in level 0.
       * @param {module:External.GPUTexture} texture - Texture to generate mipmaps for.
       * @returns {module:External.GPUTexture} - The originally passed texture
       */
      generateMipmap(texture) {
        const pipeline = this._getMipmapPipeline(texture.format);
        if (texture.dimension === "3d" || texture.dimension === "1d") {
          throw new Error("Generating mipmaps for non-2d textures is currently unsupported!");
        }
        let mipTexture = texture;
        const arrayLayerCount = texture.depthOrArrayLayers || 1;
        const renderToSource = texture.usage & GPUTextureUsage.RENDER_ATTACHMENT;
        if (!renderToSource) {
          const mipTextureDescriptor = {
            size: {
              width: Math.ceil(texture.width / 2),
              height: Math.ceil(texture.height / 2),
              depthOrArrayLayers: arrayLayerCount
            },
            format: texture.format,
            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
            mipLevelCount: texture.mipLevelCount - 1
          };
          mipTexture = this.device.createTexture(mipTextureDescriptor);
        }
        const commandEncoder = this.device.createCommandEncoder({});
        const bindGroupLayout = pipeline.getBindGroupLayout(0);
        for (let arrayLayer = 0; arrayLayer < arrayLayerCount; ++arrayLayer) {
          let srcView = texture.createView({
            baseMipLevel: 0,
            mipLevelCount: 1,
            dimension: "2d",
            baseArrayLayer: arrayLayer,
            arrayLayerCount: 1
          });
          let dstMipLevel = renderToSource ? 1 : 0;
          for (let i = 1; i < texture.mipLevelCount; ++i) {
            const dstView = mipTexture.createView({
              baseMipLevel: dstMipLevel++,
              mipLevelCount: 1,
              dimension: "2d",
              baseArrayLayer: arrayLayer,
              arrayLayerCount: 1
            });
            const passEncoder = commandEncoder.beginRenderPass({
              colorAttachments: [{
                view: dstView,
                storeOp: "store",
                loadOp: "clear",
                clearValue: { r: 0, g: 0, b: 0, a: 0 }
              }]
            });
            const bindGroup = this.device.createBindGroup({
              layout: bindGroupLayout,
              entries: [{
                binding: 0,
                resource: this.sampler
              }, {
                binding: 1,
                resource: srcView
              }]
            });
            passEncoder.setPipeline(pipeline);
            passEncoder.setBindGroup(0, bindGroup);
            passEncoder.draw(3, 1, 0, 0);
            passEncoder.end();
            srcView = dstView;
          }
        }
        if (!renderToSource) {
          const mipLevelSize = {
            width: Math.ceil(texture.width / 2),
            height: Math.ceil(texture.height / 2),
            depthOrArrayLayers: arrayLayerCount
          };
          for (let i = 1; i < texture.mipLevelCount; ++i) {
            commandEncoder.copyTextureToTexture({
              texture: mipTexture,
              mipLevel: i - 1
            }, {
              texture,
              mipLevel: i
            }, mipLevelSize);
            mipLevelSize.width = Math.ceil(mipLevelSize.width / 2);
            mipLevelSize.height = Math.ceil(mipLevelSize.height / 2);
          }
        }
        this.device.queue.submit([commandEncoder.finish()]);
        if (!renderToSource) {
          mipTexture.destroy();
        }
        return texture;
      }
    }

    "use strict";
    class GPUTextureGpuData {
      constructor(gpuTexture) {
        this.textureView = null;
        this.gpuTexture = gpuTexture;
      }
      /** Destroys this GPU data instance. */
      destroy() {
        this.gpuTexture.destroy();
        this.textureView = null;
        this.gpuTexture = null;
      }
    }
    class GpuTextureSystem {
      constructor(renderer) {
        this._gpuSamplers = /* @__PURE__ */ Object.create(null);
        this._bindGroupHash = /* @__PURE__ */ Object.create(null);
        this._uploads = {
          image: gpuUploadImageResource,
          buffer: gpuUploadBufferImageResource,
          video: gpuUploadVideoResource,
          compressed: gpuUploadCompressedTextureResource
        };
        this._renderer = renderer;
        renderer.renderableGC.addManagedHash(this, "_bindGroupHash");
        this._managedTextures = new GCManagedHash({
          renderer,
          type: "resource",
          onUnload: this.onSourceUnload.bind(this),
          name: "gpuTextureSource"
        });
      }
      /**
       * @deprecated since 8.15.0
       */
      get managedTextures() {
        return Object.values(this._managedTextures.items);
      }
      contextChange(gpu) {
        this._gpu = gpu;
      }
      /**
       * Initializes a texture source, if it has already been initialized nothing will happen.
       * @param source - The texture source to initialize.
       * @returns The initialized texture source.
       */
      initSource(source) {
        var _a;
        return ((_a = source._gpuData[this._renderer.uid]) == null ? void 0 : _a.gpuTexture) || this._initSource(source);
      }
      _initSource(source) {
        if (source.autoGenerateMipmaps) {
          const biggestDimension = Math.max(source.pixelWidth, source.pixelHeight);
          source.mipLevelCount = Math.floor(Math.log2(biggestDimension)) + 1;
        }
        let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
        if (source.uploadMethodId !== "compressed") {
          usage |= GPUTextureUsage.RENDER_ATTACHMENT;
          usage |= GPUTextureUsage.COPY_SRC;
        }
        const blockData = blockDataMap[source.format] || { blockBytes: 4, blockWidth: 1, blockHeight: 1 };
        const width = Math.ceil(source.pixelWidth / blockData.blockWidth) * blockData.blockWidth;
        const height = Math.ceil(source.pixelHeight / blockData.blockHeight) * blockData.blockHeight;
        const textureDescriptor = {
          label: source.label,
          size: { width, height },
          format: source.format,
          sampleCount: source.sampleCount,
          mipLevelCount: source.mipLevelCount,
          dimension: source.dimension,
          usage
        };
        const gpuTexture = this._gpu.device.createTexture(textureDescriptor);
        source._gpuData[this._renderer.uid] = new GPUTextureGpuData(gpuTexture);
        const added = this._managedTextures.add(source);
        if (added) {
          source.on("update", this.onSourceUpdate, this);
          source.on("resize", this.onSourceResize, this);
          source.on("updateMipmaps", this.onUpdateMipmaps, this);
        }
        this.onSourceUpdate(source);
        return gpuTexture;
      }
      onSourceUpdate(source) {
        const gpuTexture = this.getGpuSource(source);
        if (!gpuTexture)
          return;
        if (this._uploads[source.uploadMethodId]) {
          this._uploads[source.uploadMethodId].upload(source, gpuTexture, this._gpu);
        }
        if (source.autoGenerateMipmaps && source.mipLevelCount > 1) {
          this.onUpdateMipmaps(source);
        }
      }
      onUpdateMipmaps(source) {
        if (!this._mipmapGenerator) {
          this._mipmapGenerator = new GpuMipmapGenerator(this._gpu.device);
        }
        const gpuTexture = this.getGpuSource(source);
        this._mipmapGenerator.generateMipmap(gpuTexture);
      }
      onSourceUnload(source) {
        source.off("update", this.onSourceUpdate, this);
        source.off("resize", this.onSourceResize, this);
        source.off("updateMipmaps", this.onUpdateMipmaps, this);
      }
      onSourceResize(source) {
        source._gcLastUsed = this._renderer.gc.now;
        const gpuData = source._gpuData[this._renderer.uid];
        const gpuTexture = gpuData == null ? void 0 : gpuData.gpuTexture;
        if (!gpuTexture) {
          this.initSource(source);
        } else if (gpuTexture.width !== source.pixelWidth || gpuTexture.height !== source.pixelHeight) {
          gpuData.destroy();
          this._bindGroupHash[source.uid] = null;
          source._gpuData[this._renderer.uid] = null;
          this.initSource(source);
        }
      }
      _initSampler(sampler) {
        this._gpuSamplers[sampler._resourceId] = this._gpu.device.createSampler(sampler);
        return this._gpuSamplers[sampler._resourceId];
      }
      getGpuSampler(sampler) {
        return this._gpuSamplers[sampler._resourceId] || this._initSampler(sampler);
      }
      getGpuSource(source) {
        var _a;
        source._gcLastUsed = this._renderer.gc.now;
        return ((_a = source._gpuData[this._renderer.uid]) == null ? void 0 : _a.gpuTexture) || this.initSource(source);
      }
      /**
       * this returns s bind group for a specific texture, the bind group contains
       * - the texture source
       * - the texture style
       * - the texture matrix
       * This is cached so the bind group should only be created once per texture
       * @param texture - the texture you want the bindgroup for
       * @returns the bind group for the texture
       */
      getTextureBindGroup(texture) {
        return this._bindGroupHash[texture.uid] || this._createTextureBindGroup(texture);
      }
      _createTextureBindGroup(texture) {
        const source = texture.source;
        this._bindGroupHash[texture.uid] = new BindGroup({
          0: source,
          1: source.style,
          2: new UniformGroup({
            uTextureMatrix: { type: "mat3x3<f32>", value: texture.textureMatrix.mapCoord }
          })
        });
        return this._bindGroupHash[texture.uid];
      }
      getTextureView(texture) {
        const source = texture.source;
        source._gcLastUsed = this._renderer.gc.now;
        let gpuData = source._gpuData[this._renderer.uid];
        let textureView = null;
        if (!gpuData) {
          this.initSource(source);
          gpuData = source._gpuData[this._renderer.uid];
        }
        textureView = gpuData.textureView || gpuData.gpuTexture.createView();
        return textureView;
      }
      generateCanvas(texture) {
        const renderer = this._renderer;
        const commandEncoder = renderer.gpu.device.createCommandEncoder();
        const canvas = DOMAdapter.get().createCanvas();
        canvas.width = texture.source.pixelWidth;
        canvas.height = texture.source.pixelHeight;
        const context = canvas.getContext("webgpu");
        context.configure({
          device: renderer.gpu.device,
          usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
          format: DOMAdapter.get().getNavigator().gpu.getPreferredCanvasFormat(),
          alphaMode: "premultiplied"
        });
        commandEncoder.copyTextureToTexture({
          texture: renderer.texture.getGpuSource(texture.source),
          origin: {
            x: 0,
            y: 0
          }
        }, {
          texture: context.getCurrentTexture()
        }, {
          width: canvas.width,
          height: canvas.height
        });
        renderer.gpu.device.queue.submit([commandEncoder.finish()]);
        return canvas;
      }
      getPixels(texture) {
        const webGPUCanvas = this.generateCanvas(texture);
        const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(webGPUCanvas.width, webGPUCanvas.height);
        const context = canvasAndContext.context;
        context.drawImage(webGPUCanvas, 0, 0);
        const { width, height } = webGPUCanvas;
        const imageData = context.getImageData(0, 0, width, height);
        const pixels = new Uint8ClampedArray(imageData.data.buffer);
        CanvasPool.returnCanvasAndContext(canvasAndContext);
        return { pixels, width, height };
      }
      destroy() {
        this._managedTextures.destroy();
        for (const k of Object.keys(this._bindGroupHash)) {
          const key = Number(k);
          const bindGroup = this._bindGroupHash[key];
          bindGroup == null ? void 0 : bindGroup.destroy();
        }
        this._renderer = null;
        this._gpu = null;
        this._mipmapGenerator = null;
        this._gpuSamplers = null;
        this._bindGroupHash = null;
      }
    }
    /** @ignore */
    GpuTextureSystem.extension = {
      type: [
        ExtensionType.WebGPUSystem
      ],
      name: "texture"
    };

    "use strict";

    "use strict";
    class GpuGraphicsAdaptor {
      constructor() {
        this._maxTextures = 0;
      }
      contextChange(renderer) {
        const localUniforms = new UniformGroup({
          uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
          uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
          uRound: { value: 0, type: "f32" }
        });
        this._maxTextures = renderer.limits.maxBatchableTextures;
        const gpuProgram = compileHighShaderGpuProgram({
          name: "graphics",
          bits: [
            colorBit,
            generateTextureBatchBit(this._maxTextures),
            localUniformBitGroup2,
            roundPixelsBit
          ]
        });
        this.shader = new Shader({
          gpuProgram,
          resources: {
            // added on the fly!
            localUniforms
          }
        });
      }
      execute(graphicsPipe, renderable) {
        const context = renderable.context;
        const shader = context.customShader || this.shader;
        const renderer = graphicsPipe.renderer;
        const contextSystem = renderer.graphicsContext;
        const {
          batcher,
          instructions
        } = contextSystem.getContextRenderData(context);
        const encoder = renderer.encoder;
        encoder.setGeometry(batcher.geometry, shader.gpuProgram);
        const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
        encoder.setBindGroup(0, globalUniformsBindGroup, shader.gpuProgram);
        const localBindGroup = renderer.renderPipes.uniformBatch.getUniformBindGroup(shader.resources.localUniforms, true);
        encoder.setBindGroup(2, localBindGroup, shader.gpuProgram);
        const batches = instructions.instructions;
        let topology = null;
        for (let i = 0; i < instructions.instructionSize; i++) {
          const batch = batches[i];
          if (batch.topology !== topology) {
            topology = batch.topology;
            encoder.setPipelineFromGeometryProgramAndState(
              batcher.geometry,
              shader.gpuProgram,
              graphicsPipe.state,
              batch.topology
            );
          }
          shader.groups[1] = batch.bindGroup;
          if (!batch.gpuBindGroup) {
            const textureBatch = batch.textures;
            batch.bindGroup = getTextureBatchBindGroup(
              textureBatch.textures,
              textureBatch.count,
              this._maxTextures
            );
            batch.gpuBindGroup = renderer.bindGroup.getBindGroup(
              batch.bindGroup,
              shader.gpuProgram,
              1
            );
          }
          encoder.setBindGroup(1, batch.bindGroup, shader.gpuProgram);
          encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
        }
      }
      destroy() {
        this.shader.destroy(true);
        this.shader = null;
      }
    }
    /** @ignore */
    GpuGraphicsAdaptor.extension = {
      type: [
        ExtensionType.WebGPUPipesAdaptor
      ],
      name: "graphics"
    };

    "use strict";
    class GpuMeshAdapter {
      init() {
        const gpuProgram = compileHighShaderGpuProgram({
          name: "mesh",
          bits: [
            localUniformBit,
            textureBit,
            roundPixelsBit
          ]
        });
        this._shader = new Shader({
          gpuProgram,
          resources: {
            uTexture: Texture.EMPTY._source,
            uSampler: Texture.EMPTY._source.style,
            textureUniforms: {
              uTextureMatrix: { type: "mat3x3<f32>", value: new Matrix() }
            }
          }
        });
      }
      execute(meshPipe, mesh) {
        const renderer = meshPipe.renderer;
        let shader = mesh._shader;
        if (!shader) {
          shader = this._shader;
          shader.groups[2] = renderer.texture.getTextureBindGroup(mesh.texture);
        } else if (!shader.gpuProgram) {
          warn("Mesh shader has no gpuProgram", mesh.shader);
          return;
        }
        const gpuProgram = shader.gpuProgram;
        if (gpuProgram.autoAssignGlobalUniforms) {
          shader.groups[0] = renderer.globalUniforms.bindGroup;
        }
        if (gpuProgram.autoAssignLocalUniforms) {
          const localUniforms = meshPipe.localUniforms;
          shader.groups[1] = renderer.renderPipes.uniformBatch.getUniformBindGroup(localUniforms, true);
        }
        renderer.encoder.draw({
          geometry: mesh._geometry,
          shader,
          state: mesh.state
        });
      }
      destroy() {
        this._shader.destroy(true);
        this._shader = null;
      }
    }
    /** @ignore */
    GpuMeshAdapter.extension = {
      type: [
        ExtensionType.WebGPUPipesAdaptor
      ],
      name: "mesh"
    };

    "use strict";
    const DefaultWebGPUSystems = [
      ...SharedSystems,
      GpuUboSystem,
      GpuEncoderSystem,
      GpuDeviceSystem,
      GpuLimitsSystem,
      GpuBufferSystem,
      GpuTextureSystem,
      GpuRenderTargetSystem,
      GpuShaderSystem,
      GpuStateSystem,
      PipelineSystem,
      GpuColorMaskSystem,
      GpuStencilSystem,
      BindGroupSystem
    ];
    const DefaultWebGPUPipes = [...SharedRenderPipes, GpuUniformBatchPipe];
    const DefaultWebGPUAdapters = [GpuBatchAdaptor, GpuMeshAdapter, GpuGraphicsAdaptor];
    const systems = [];
    const renderPipes = [];
    const renderPipeAdaptors = [];
    extensions.handleByNamedList(ExtensionType.WebGPUSystem, systems);
    extensions.handleByNamedList(ExtensionType.WebGPUPipes, renderPipes);
    extensions.handleByNamedList(ExtensionType.WebGPUPipesAdaptor, renderPipeAdaptors);
    extensions.add(...DefaultWebGPUSystems, ...DefaultWebGPUPipes, ...DefaultWebGPUAdapters);
    class WebGPURenderer extends AbstractRenderer {
      constructor() {
        const systemConfig = {
          name: "webgpu",
          type: RendererType.WEBGPU,
          systems,
          renderPipes,
          renderPipeAdaptors
        };
        super(systemConfig);
      }
    }

    var WebGPURenderer$1 = {
        __proto__: null,
        WebGPURenderer: WebGPURenderer
    };

    "use strict";
    const DEPRECATED_DRAW_MODES = {
      POINTS: "point-list",
      LINES: "line-list",
      LINE_STRIP: "line-strip",
      TRIANGLES: "triangle-list",
      TRIANGLE_STRIP: "triangle-strip"
    };
    const DRAW_MODES = new Proxy(DEPRECATED_DRAW_MODES, {
      get(target, prop) {
        deprecation(v8_0_0, `DRAW_MODES.${prop} is deprecated, use '${DEPRECATED_DRAW_MODES[prop]}' instead`);
        return target[prop];
      }
    });

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";

    "use strict";
    var DEPRECATED_WRAP_MODES = /* @__PURE__ */ ((DEPRECATED_WRAP_MODES2) => {
      DEPRECATED_WRAP_MODES2["CLAMP"] = "clamp-to-edge";
      DEPRECATED_WRAP_MODES2["REPEAT"] = "repeat";
      DEPRECATED_WRAP_MODES2["MIRRORED_REPEAT"] = "mirror-repeat";
      return DEPRECATED_WRAP_MODES2;
    })(DEPRECATED_WRAP_MODES || {});
    const WRAP_MODES = new Proxy(DEPRECATED_WRAP_MODES, {
      get(target, prop) {
        deprecation(v8_0_0, `DRAW_MODES.${prop} is deprecated, use '${DEPRECATED_WRAP_MODES[prop]}' instead`);
        return target[prop];
      }
    });
    var DEPRECATED_SCALE_MODES = /* @__PURE__ */ ((DEPRECATED_SCALE_MODES2) => {
      DEPRECATED_SCALE_MODES2["NEAREST"] = "nearest";
      DEPRECATED_SCALE_MODES2["LINEAR"] = "linear";
      return DEPRECATED_SCALE_MODES2;
    })(DEPRECATED_SCALE_MODES || {});
    const SCALE_MODES = new Proxy(DEPRECATED_SCALE_MODES, {
      get(target, prop) {
        deprecation(v8_0_0, `DRAW_MODES.${prop} is deprecated, use '${DEPRECATED_SCALE_MODES[prop]}' instead`);
        return target[prop];
      }
    });

    "use strict";

    "use strict";
    class TextureUvs {
      constructor() {
        this.x0 = 0;
        this.y0 = 0;
        this.x1 = 1;
        this.y1 = 0;
        this.x2 = 1;
        this.y2 = 1;
        this.x3 = 0;
        this.y3 = 1;
        this.uvsFloat32 = new Float32Array(8);
      }
      /**
       * Sets the texture Uvs based on the given frame information.
       * @protected
       * @param frame - The frame of the texture
       * @param baseFrame - The base frame of the texture
       * @param rotate - Rotation of frame, see {@link groupD8}
       */
      set(frame, baseFrame, rotate) {
        const tw = baseFrame.width;
        const th = baseFrame.height;
        if (rotate) {
          const w2 = frame.width / 2 / tw;
          const h2 = frame.height / 2 / th;
          const cX = frame.x / tw + w2;
          const cY = frame.y / th + h2;
          rotate = groupD8.add(rotate, groupD8.NW);
          this.x0 = cX + w2 * groupD8.uX(rotate);
          this.y0 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          this.x1 = cX + w2 * groupD8.uX(rotate);
          this.y1 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          this.x2 = cX + w2 * groupD8.uX(rotate);
          this.y2 = cY + h2 * groupD8.uY(rotate);
          rotate = groupD8.add(rotate, 2);
          this.x3 = cX + w2 * groupD8.uX(rotate);
          this.y3 = cY + h2 * groupD8.uY(rotate);
        } else {
          this.x0 = frame.x / tw;
          this.y0 = frame.y / th;
          this.x1 = (frame.x + frame.width) / tw;
          this.y1 = frame.y / th;
          this.x2 = (frame.x + frame.width) / tw;
          this.y2 = (frame.y + frame.height) / th;
          this.x3 = frame.x / tw;
          this.y3 = (frame.y + frame.height) / th;
        }
        this.uvsFloat32[0] = this.x0;
        this.uvsFloat32[1] = this.y0;
        this.uvsFloat32[2] = this.x1;
        this.uvsFloat32[3] = this.y1;
        this.uvsFloat32[4] = this.x2;
        this.uvsFloat32[5] = this.y2;
        this.uvsFloat32[6] = this.x3;
        this.uvsFloat32[7] = this.y3;
      }
      toString() {
        return `[pixi.js/core:TextureUvs x0=${this.x0} y0=${this.y0} x1=${this.x1} y1=${this.y1} x2=${this.x2} y2=${this.y2} x3=${this.x3} y3=${this.y3}]`;
      }
    }

    "use strict";
    function parseFunctionBody(fn) {
      const fnStr = fn.toString();
      const bodyStart = fnStr.indexOf("{");
      const bodyEnd = fnStr.lastIndexOf("}");
      if (bodyStart === -1 || bodyEnd === -1) {
        throw new Error("getFunctionBody: No body found in function definition");
      }
      return fnStr.slice(bodyStart + 1, bodyEnd).trim();
    }

    "use strict";

    "use strict";

    "use strict";
    function getFastGlobalBounds(target, bounds) {
      deprecation("8.7.0", "Use container.getFastGlobalBounds() instead");
      return target.getFastGlobalBounds(true, bounds);
    }

    "use strict";

    "use strict";

    "use strict";
    var __defProp$c = Object.defineProperty;
    var __getOwnPropSymbols$d = Object.getOwnPropertySymbols;
    var __hasOwnProp$d = Object.prototype.hasOwnProperty;
    var __propIsEnum$d = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$c = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$d.call(b, prop))
          __defNormalProp$c(a, prop, b[prop]);
      if (__getOwnPropSymbols$d)
        for (var prop of __getOwnPropSymbols$d(b)) {
          if (__propIsEnum$d.call(b, prop))
            __defNormalProp$c(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$7 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$d.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$d)
        for (var prop of __getOwnPropSymbols$d(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$d.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class RenderContainer extends ViewContainer {
      /**
       * @param options - The options for the container.
       */
      constructor(options) {
        var _b, _c;
        if (typeof options === "function") {
          options = { render: options };
        }
        const _a = options, { render } = _a, rest = __objRest$7(_a, ["render"]);
        super(__spreadValues$c({
          label: "RenderContainer"
        }, rest));
        /** @internal */
        this.renderPipeId = "customRender";
        /** @internal */
        this.batched = false;
        if (render)
          this.render = render;
        this.containsPoint = (_b = options.containsPoint) != null ? _b : () => false;
        this.addBounds = (_c = options.addBounds) != null ? _c : () => false;
      }
      /** @private */
      updateBounds() {
        this._bounds.clear();
        this.addBounds(this._bounds);
      }
      /**
       * An overridable function that can be used to render the object using the current renderer.
       * @param _renderer - The current renderer
       */
      render(_renderer) {
      }
    }

    "use strict";
    function collectAllRenderables(container, instructionSet, rendererOrPipes) {
      deprecation("8.7.0", "Please use container.collectRenderables instead.");
      const renderer = rendererOrPipes.renderPipes ? rendererOrPipes : rendererOrPipes.batch.renderer;
      return container.collectRenderables(instructionSet, renderer, null);
    }

    "use strict";
    function updateLocalTransform(lt, container) {
      const scale = container._scale;
      const pivot = container._pivot;
      const position = container._position;
      const sx = scale._x;
      const sy = scale._y;
      const px = pivot._x;
      const py = pivot._y;
      lt.a = container._cx * sx;
      lt.b = container._sx * sx;
      lt.c = container._cy * sy;
      lt.d = container._sy * sy;
      lt.tx = position._x - (px * lt.a + py * lt.c);
      lt.ty = position._y - (px * lt.b + py * lt.d);
    }

    "use strict";
    function updateWorldTransform(local, parent, world) {
      const lta = local.a;
      const ltb = local.b;
      const ltc = local.c;
      const ltd = local.d;
      const lttx = local.tx;
      const ltty = local.ty;
      const pta = parent.a;
      const ptb = parent.b;
      const ptc = parent.c;
      const ptd = parent.d;
      world.a = lta * pta + ltb * ptc;
      world.b = lta * ptb + ltb * ptd;
      world.c = ltc * pta + ltd * ptc;
      world.d = ltc * ptb + ltd * ptd;
      world.tx = lttx * pta + ltty * ptc + parent.tx;
      world.ty = lttx * ptb + ltty * ptd + parent.ty;
    }

    "use strict";

    "use strict";

    "use strict";
    function buildGeometryFromPath(options) {
      if (options instanceof GraphicsPath) {
        options = {
          path: options,
          textureMatrix: null,
          out: null
        };
      }
      const vertices = [];
      const uvs = [];
      const indices = [];
      const shapePath = options.path.shapePath;
      const textureMatrix = options.textureMatrix;
      shapePath.shapePrimitives.forEach(({ shape, transform: matrix }) => {
        const indexOffset = indices.length;
        const vertOffset = vertices.length / 2;
        const points = [];
        const build = shapeBuilders[shape.type];
        build.build(shape, points);
        if (matrix) {
          transformVertices(points, matrix);
        }
        build.triangulate(points, vertices, 2, vertOffset, indices, indexOffset);
        const uvsOffset = uvs.length / 2;
        if (textureMatrix) {
          if (matrix) {
            textureMatrix.append(matrix.clone().invert());
          }
          buildUvs(vertices, 2, vertOffset, uvs, uvsOffset, 2, vertices.length / 2 - vertOffset, textureMatrix);
        } else {
          buildSimpleUvs(uvs, uvsOffset, 2, vertices.length / 2 - vertOffset);
        }
      });
      const out = options.out;
      if (out) {
        out.positions = new Float32Array(vertices);
        out.uvs = new Float32Array(uvs);
        out.indices = new Uint32Array(indices);
        return out;
      }
      const geometry = new MeshGeometry({
        positions: new Float32Array(vertices),
        uvs: new Float32Array(uvs),
        indices: new Uint32Array(indices)
      });
      return geometry;
    }

    "use strict";
    var __defProp$b = Object.defineProperty;
    var __getOwnPropSymbols$c = Object.getOwnPropertySymbols;
    var __hasOwnProp$c = Object.prototype.hasOwnProperty;
    var __propIsEnum$c = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$b = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$c.call(b, prop))
          __defNormalProp$b(a, prop, b[prop]);
      if (__getOwnPropSymbols$c)
        for (var prop of __getOwnPropSymbols$c(b)) {
          if (__propIsEnum$c.call(b, prop))
            __defNormalProp$b(a, prop, b[prop]);
        }
      return a;
    };
    const _RenderLayer = class _RenderLayer extends Container {
      /**
       * Creates a new RenderLayer instance
       * @param options - Configuration options for the RenderLayer
       * @param {boolean} [options.sortableChildren=false] - If true, layer children will be automatically sorted each render
       * @param {Function} [options.sortFunction] - Custom function to sort layer children. Default sorts by zIndex
       */
      constructor(options = {}) {
        options = __spreadValues$b(__spreadValues$b({}, _RenderLayer.defaultOptions), options);
        super();
        /**
         * The list of objects that this layer is responsible for rendering. Objects in this list maintain
         * their original parent in the scene graph but are rendered as part of this layer.
         * @example
         * ```ts
         * const layer = new RenderLayer();
         * const sprite = new Sprite(texture);
         *
         * // Add sprite to scene graph for transforms
         * container.addChild(sprite);
         *
         * // Add to layer for render order control
         * layer.attach(sprite);
         * console.log(layer.renderLayerChildren.length); // 1
         *
         * // Access objects in the layer
         * layer.renderLayerChildren.forEach(child => {
         *     console.log('Layer child:', child);
         * });
         *
         * // Check if object is in layer
         * const isInLayer = layer.renderLayerChildren.includes(sprite);
         *
         * // Clear all objects from layer
         * layer.detachAll();
         * console.log(layer.renderLayerChildren.length); // 0
         * ```
         * @readonly
         * @see {@link RenderLayer#attach} For adding objects to the layer
         * @see {@link RenderLayer#detach} For removing objects from the layer
         * @see {@link RenderLayer#detachAll} For removing all objects from the layer
         */
        this.renderLayerChildren = [];
        this.sortableChildren = options.sortableChildren;
        this.sortFunction = options.sortFunction;
      }
      /**
       * Adds one or more Containers to this render layer. The Containers will be rendered as part of this layer
       * while maintaining their original parent in the scene graph.
       *
       * If the Container already belongs to a layer, it will be removed from the old layer before being added to this one.
       * @example
       * ```ts
       * const layer = new RenderLayer();
       * const container = new Container();
       * const sprite1 = new Sprite(texture1);
       * const sprite2 = new Sprite(texture2);
       *
       * // Add sprites to scene graph for transforms
       * container.addChild(sprite1, sprite2);
       *
       * // Add sprites to layer for render order control
       * layer.attach(sprite1, sprite2);
       *
       * // Add single sprite with type checking
       * const typedSprite = layer.attach<Sprite>(new Sprite(texture3));
       * typedSprite.tint = 'red';
       *
       * // Automatically removes from previous layer if needed
       * const otherLayer = new RenderLayer();
       * otherLayer.attach(sprite1); // Removes from previous layer
       * ```
       * @param children - The Container(s) to add to this layer. Can be any Container or array of Containers.
       * @returns The first child that was added, for method chaining
       * @see {@link RenderLayer#detach} For removing objects from the layer
       * @see {@link RenderLayer#detachAll} For removing all objects from the layer
       * @see {@link Container#addChild} For adding to scene graph hierarchy
       */
      attach(...children) {
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          if (child.parentRenderLayer) {
            if (child.parentRenderLayer === this)
              continue;
            child.parentRenderLayer.detach(child);
          }
          this.renderLayerChildren.push(child);
          child.parentRenderLayer = this;
          const renderGroup = this.renderGroup || this.parentRenderGroup;
          if (renderGroup) {
            renderGroup.structureDidChange = true;
          }
        }
        return children[0];
      }
      /**
       * Removes one or more Containers from this render layer. The Containers will maintain their
       * original parent in the scene graph but will no longer be rendered as part of this layer.
       * @example
       * ```ts
       * const layer = new RenderLayer();
       * const container = new Container();
       * const sprite1 = new Sprite(texture1);
       * const sprite2 = new Sprite(texture2);
       *
       * // Add sprites to scene graph and layer
       * container.addChild(sprite1, sprite2);
       * layer.attach(sprite1, sprite2);
       *
       * // Remove single sprite from layer
       * layer.detach(sprite1);
       * // sprite1 is still child of container but not rendered in layer
       *
       * // Remove multiple sprites at once
       * const otherLayer = new RenderLayer();
       * otherLayer.attach(sprite3, sprite4);
       * otherLayer.detach(sprite3, sprite4);
       *
       * // Type-safe detachment
       * const typedSprite = layer.detach<Sprite>(spriteInLayer);
       * typedSprite.texture = newTexture; // TypeScript knows this is a Sprite
       * ```
       * @param children - The Container(s) to remove from this layer
       * @returns The first child that was removed, for method chaining
       * @see {@link RenderLayer#attach} For adding objects to the layer
       * @see {@link RenderLayer#detachAll} For removing all objects from the layer
       * @see {@link Container#removeChild} For removing from scene graph hierarchy
       */
      detach(...children) {
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          const index = this.renderLayerChildren.indexOf(child);
          if (index !== -1) {
            this.renderLayerChildren.splice(index, 1);
          }
          child.parentRenderLayer = null;
          const renderGroup = this.renderGroup || this.parentRenderGroup;
          if (renderGroup) {
            renderGroup.structureDidChange = true;
          }
        }
        return children[0];
      }
      /**
       * Removes all objects from this render layer. Objects will maintain their
       * original parent in the scene graph but will no longer be rendered as part of this layer.
       * @example
       * ```ts
       * const layer = new RenderLayer();
       * const container = new Container();
       *
       * // Add multiple sprites to scene graph and layer
       * const sprites = [
       *     new Sprite(texture1),
       *     new Sprite(texture2),
       *     new Sprite(texture3)
       * ];
       *
       * container.addChild(...sprites);  // Add to scene graph
       * layer.attach(...sprites);       // Add to render layer
       *
       * // Later, remove all sprites from layer at once
       * layer.detachAll();
       * console.log(layer.renderLayerChildren.length); // 0
       * console.log(container.children.length);        // 3 (still in scene graph)
       * ```
       * @returns The RenderLayer instance for method chaining
       * @see {@link RenderLayer#attach} For adding objects to the layer
       * @see {@link RenderLayer#detach} For removing individual objects
       * @see {@link Container#removeChildren} For removing from scene graph
       */
      detachAll() {
        const layerChildren = this.renderLayerChildren;
        for (let i = 0; i < layerChildren.length; i++) {
          layerChildren[i].parentRenderLayer = null;
        }
        this.renderLayerChildren.length = 0;
      }
      /**
       * Collects renderables for this layer and its children.
       * This method is called by the renderer to gather all objects that should be rendered in this layer.
       * @param instructionSet - The set of instructions to collect renderables into.
       * @param renderer - The renderer that is collecting renderables.
       * @param _currentLayer - The current render layer being processed.
       * @internal
       */
      collectRenderables(instructionSet, renderer, _currentLayer) {
        const layerChildren = this.renderLayerChildren;
        const length = layerChildren.length;
        if (this.sortableChildren) {
          this.sortRenderLayerChildren();
        }
        for (let i = 0; i < length; i++) {
          if (!layerChildren[i].parent) {
            warn(
              "Container must be added to both layer and scene graph. Layers only handle render order - the scene graph is required for transforms (addChild)",
              layerChildren[i]
            );
          }
          layerChildren[i].collectRenderables(instructionSet, renderer, this);
        }
      }
      /**
       * Sort the layer's children using the defined sort function. This method allows manual sorting
       * of layer children and is automatically called during rendering if sortableChildren is true.
       * @example
       * ```ts
       * const layer = new RenderLayer();
       *
       * // Add multiple sprites at different depths
       * const sprite1 = new Sprite(texture);
       * const sprite2 = new Sprite(texture);
       * const sprite3 = new Sprite(texture);
       *
       * sprite1.zIndex = 3;
       * sprite2.zIndex = 1;
       * sprite3.zIndex = 2;
       *
       * layer.attach(sprite1, sprite2, sprite3);
       *
       * // Manual sorting with default zIndex sort
       * layer.sortRenderLayerChildren();
       * // Order is now: sprite2 (1), sprite3 (2), sprite1 (3)
       *
       * // Custom sort by y position
       * layer.sortFunction = (a, b) => a.y - b.y;
       * layer.sortRenderLayerChildren();
       *
       * // Automatic sorting
       * layer.sortableChildren = true; // Will sort each render
       * ```
       * @returns The RenderLayer instance for method chaining
       * @see {@link RenderLayer#sortableChildren} For enabling automatic sorting
       * @see {@link RenderLayer#sortFunction} For customizing the sort logic
       */
      sortRenderLayerChildren() {
        this.renderLayerChildren.sort(this.sortFunction);
      }
      /**
       * Recursively calculates the global bounds of this RenderLayer and its children.
       * @param factorRenderLayers
       * @param bounds
       * @param _currentLayer
       * @internal
       */
      _getGlobalBoundsRecursive(factorRenderLayers, bounds, _currentLayer) {
        if (!factorRenderLayers)
          return;
        const children = this.renderLayerChildren;
        for (let i = 0; i < children.length; i++) {
          children[i]._getGlobalBoundsRecursive(true, bounds, this);
        }
      }
      /**
       * @inheritdoc
       * @internal
       */
      getFastGlobalBounds(factorRenderLayers, bounds) {
        return super.getFastGlobalBounds(factorRenderLayers, bounds);
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error. Please use `RenderLayer.attach()` instead.
       * @param {...any} _children
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      addChild(..._children) {
        throw new Error(
          "RenderLayer.addChild() is not available. Please use RenderLayer.attach()"
        );
      }
      /**
       * This method is not available in RenderLayer.
       * Calling this method will throw an error. Please use `RenderLayer.detach()` instead.
       * @param {...any} _children
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChild(..._children) {
        throw new Error(
          "RenderLayer.removeChild() is not available. Please use RenderLayer.detach()"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error. Please use `RenderLayer.detach()` instead.
       * @param {number} [_beginIndex]
       * @param {number} [_endIndex]
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChildren(_beginIndex, _endIndex) {
        throw new Error(
          "RenderLayer.removeChildren() is not available. Please use RenderLayer.detach()"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChildAt(_index) {
        throw new Error(
          "RenderLayer.removeChildAt() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      getChildAt(_index) {
        throw new Error(
          "RenderLayer.getChildAt() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {Container} _child
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      setChildIndex(_child, _index) {
        throw new Error(
          "RenderLayer.setChildIndex() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {Container} _child
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      getChildIndex(_child) {
        throw new Error(
          "RenderLayer.getChildIndex() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {Container} _child
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      addChildAt(_child, _index) {
        throw new Error(
          "RenderLayer.addChildAt() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param {Container} _child
       * @param {Container} _child2
       * @ignore
       */
      swapChildren(_child, _child2) {
        throw new Error(
          "RenderLayer.swapChildren() is not available"
        );
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param _child - The child to reparent
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      reparentChild(..._child) {
        throw new Error("RenderLayer.reparentChild() is not available with the render layer");
      }
      /**
       * This method is not available in RenderLayer.
       *
       * Calling this method will throw an error.
       * @param _child - The child to reparent
       * @param _index - The index to reparent the child to
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      reparentChildAt(_child, _index) {
        throw new Error("RenderLayer.reparentChildAt() is not available with the render layer");
      }
    };
    /**
     * Default options for RenderLayer instances. These options control the sorting behavior
     * of objects within the render layer.
     * @example
     * ```ts
     * // Create a custom render layer with modified default options
     * RenderLayer.defaultOptions = {
     *     sortableChildren: true,
     *     sortFunction: (a, b) => a.y - b.y // Sort by vertical position
     * };
     *
     * // All new render layers will use these defaults
     * const layer1 = new RenderLayer();
     * // layer1 will have sortableChildren = true
     * ```
     * @property {boolean} sortableChildren -
     * @property {Function} sortFunction -
     * @see {@link RenderLayer} For the main render layer class
     * @see {@link Container#zIndex} For the default sort property
     * @see {@link RenderLayer#sortRenderLayerChildren} For manual sorting
     */
    _RenderLayer.defaultOptions = {
      /** If true, layer children will be automatically sorted each render. Default is false. */
      sortableChildren: false,
      /**
       * Function used to sort layer children.
       * Default sorts by zIndex. Accepts two Container objects and returns
       * a number indicating their relative order.
       * @param a - First container to compare
       * @param b - Second container to compare
       * @returns Negative if a should render before b, positive if b should render before a
       */
      sortFunction: (a, b) => a.zIndex - b.zIndex
    };
    let RenderLayer = _RenderLayer;

    "use strict";
    function applyProjectiveTransformationToPlane(width, height, geometry, transformationMatrix) {
      const buffer = geometry.buffers[0];
      const vertices = buffer.data;
      const { verticesX, verticesY } = geometry;
      const sizeX = width / (verticesX - 1);
      const sizeY = height / (verticesY - 1);
      let index = 0;
      const a00 = transformationMatrix[0];
      const a01 = transformationMatrix[1];
      const a02 = transformationMatrix[2];
      const a10 = transformationMatrix[3];
      const a11 = transformationMatrix[4];
      const a12 = transformationMatrix[5];
      const a20 = transformationMatrix[6];
      const a21 = transformationMatrix[7];
      const a22 = transformationMatrix[8];
      for (let i = 0; i < vertices.length; i += 2) {
        const x = index % verticesX * sizeX;
        const y = (index / verticesX | 0) * sizeY;
        const newX = a00 * x + a01 * y + a02;
        const newY = a10 * x + a11 * y + a12;
        const w = a20 * x + a21 * y + a22;
        vertices[i] = newX / w;
        vertices[i + 1] = newY / w;
        index++;
      }
      buffer.update();
    }

    "use strict";
    function computeAdjugate(out, matrix) {
      const a00 = matrix[0];
      const a01 = matrix[1];
      const a02 = matrix[2];
      const a10 = matrix[3];
      const a11 = matrix[4];
      const a12 = matrix[5];
      const a20 = matrix[6];
      const a21 = matrix[7];
      const a22 = matrix[8];
      out[0] = a11 * a22 - a12 * a21;
      out[1] = a02 * a21 - a01 * a22;
      out[2] = a01 * a12 - a02 * a11;
      out[3] = a12 * a20 - a10 * a22;
      out[4] = a00 * a22 - a02 * a20;
      out[5] = a02 * a10 - a00 * a12;
      out[6] = a10 * a21 - a11 * a20;
      out[7] = a01 * a20 - a00 * a21;
      out[8] = a00 * a11 - a01 * a10;
      return out;
    }
    function multiplyMatrix3x3(out, a, b) {
      const a00 = a[0];
      const a01 = a[1];
      const a02 = a[2];
      const a10 = a[3];
      const a11 = a[4];
      const a12 = a[5];
      const a20 = a[6];
      const a21 = a[7];
      const a22 = a[8];
      const b00 = b[0];
      const b01 = b[1];
      const b02 = b[2];
      const b10 = b[3];
      const b11 = b[4];
      const b12 = b[5];
      const b20 = b[6];
      const b21 = b[7];
      const b22 = b[8];
      out[0] = b00 * a00 + b01 * a10 + b02 * a20;
      out[1] = b00 * a01 + b01 * a11 + b02 * a21;
      out[2] = b00 * a02 + b01 * a12 + b02 * a22;
      out[3] = b10 * a00 + b11 * a10 + b12 * a20;
      out[4] = b10 * a01 + b11 * a11 + b12 * a21;
      out[5] = b10 * a02 + b11 * a12 + b12 * a22;
      out[6] = b20 * a00 + b21 * a10 + b22 * a20;
      out[7] = b20 * a01 + b21 * a11 + b22 * a21;
      out[8] = b20 * a02 + b21 * a12 + b22 * a22;
      return out;
    }
    function multiplyMatrixAndVector(out, m, v) {
      const x = v[0];
      const y = v[1];
      const z = v[2];
      out[0] = m[0] * x + m[1] * y + m[2] * z;
      out[1] = m[3] * x + m[4] * y + m[5] * z;
      out[2] = m[6] * x + m[7] * y + m[8] * z;
      return out;
    }
    const tempMatrix = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    const tempVec = [0, 0, 0];
    const tempVec2 = [0, 0, 0];
    function generateBasisToPointsMatrix(out, x1, y1, x2, y2, x3, y3, x4, y4) {
      const m = tempMatrix;
      m[0] = x1;
      m[1] = x2;
      m[2] = x3;
      m[3] = y1;
      m[4] = y2;
      m[5] = y3;
      m[6] = 1;
      m[7] = 1;
      m[8] = 1;
      const adjugateM = computeAdjugate(
        out,
        // reusing out as adjugateM is only used once
        m
      );
      tempVec2[0] = x4;
      tempVec2[1] = y4;
      tempVec2[2] = 1;
      const v = multiplyMatrixAndVector(
        tempVec,
        adjugateM,
        tempVec2
      );
      const diagonalMatrix = out;
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = v[1];
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = v[2];
      return multiplyMatrix3x3(out, diagonalMatrix, m);
    }
    const tempSourceMatrix = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    const tempDestinationMatrix = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    function compute2DProjection(out, x1s, y1s, x1d, y1d, x2s, y2s, x2d, y2d, x3s, y3s, x3d, y3d, x4s, y4s, x4d, y4d) {
      const sourceMatrix = generateBasisToPointsMatrix(
        tempSourceMatrix,
        x1s,
        y1s,
        x2s,
        y2s,
        x3s,
        y3s,
        x4s,
        y4s
      );
      const destinationMatrix = generateBasisToPointsMatrix(
        tempDestinationMatrix,
        x1d,
        y1d,
        x2d,
        y2d,
        x3d,
        y3d,
        x4d,
        y4d
      );
      return multiplyMatrix3x3(
        out,
        computeAdjugate(sourceMatrix, sourceMatrix),
        destinationMatrix
      );
    }

    "use strict";
    class PerspectivePlaneGeometry extends PlaneGeometry {
      /**
       * @param options - Options to be applied to MeshPlane
       * @param options.width - The width of the plane
       * @param options.height - The height of the plane
       * @param options.verticesX - The amount of vertices on the x axis
       * @param options.verticesY - The amount of vertices on the y axis
       */
      constructor(options) {
        super(options);
        this._projectionMatrix = [0, 0, 0, 0, 0, 0, 0, 0, 0];
        const { width, height } = options;
        this.corners = [0, 0, width, 0, width, height, 0, height];
      }
      /**
       * Will set the corners of the quad to the given coordinates
       * Calculating the perspective so it looks correct!
       * @param x0 - x coordinate of the first corner
       * @param y0 - y coordinate of the first corner
       * @param x1 - x coordinate of the second corner
       * @param y1 - y coordinate of the second corner
       * @param x2 - x coordinate of the third corner
       * @param y2 - y coordinate of the third corner
       * @param x3 - x coordinate of the fourth corner
       * @param y3 - y coordinate of the fourth corner
       */
      setCorners(x0, y0, x1, y1, x2, y2, x3, y3) {
        const corners = this.corners;
        corners[0] = x0;
        corners[1] = y0;
        corners[2] = x1;
        corners[3] = y1;
        corners[4] = x2;
        corners[5] = y2;
        corners[6] = x3;
        corners[7] = y3;
        this.updateProjection();
      }
      /** Update the projection matrix based on the corners */
      updateProjection() {
        const { width, height } = this;
        const corners = this.corners;
        const projectionMatrix = compute2DProjection(
          this._projectionMatrix,
          0,
          0,
          // top-left source
          corners[0],
          corners[1],
          // top-left dest
          width,
          0,
          // top-right source
          corners[2],
          corners[3],
          // top-right dest
          width,
          height,
          // bottom-right source
          corners[4],
          corners[5],
          // bottom-right dest
          0,
          height,
          // bottom-left source
          corners[6],
          corners[7]
          // bottom-left dest
        );
        applyProjectiveTransformationToPlane(
          width,
          height,
          this,
          projectionMatrix
        );
      }
    }

    "use strict";
    var __defProp$a = Object.defineProperty;
    var __defProps$7 = Object.defineProperties;
    var __getOwnPropDescs$7 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$b = Object.getOwnPropertySymbols;
    var __hasOwnProp$b = Object.prototype.hasOwnProperty;
    var __propIsEnum$b = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$a = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$b.call(b, prop))
          __defNormalProp$a(a, prop, b[prop]);
      if (__getOwnPropSymbols$b)
        for (var prop of __getOwnPropSymbols$b(b)) {
          if (__propIsEnum$b.call(b, prop))
            __defNormalProp$a(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
    var __objRest$6 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$b.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$b)
        for (var prop of __getOwnPropSymbols$b(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$b.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const _PerspectiveMesh = class _PerspectiveMesh extends Mesh {
      /**
       * @param options - Options to be applied to PerspectiveMesh
       */
      constructor(options) {
        options = __spreadValues$a(__spreadValues$a({}, _PerspectiveMesh.defaultOptions), options);
        const _a = options, { texture, verticesX, verticesY } = _a, rest = __objRest$6(_a, ["texture", "verticesX", "verticesY"]);
        const planeGeometry = new PerspectivePlaneGeometry(definedProps({
          width: texture.width,
          height: texture.height,
          verticesX,
          verticesY
        }));
        super(definedProps(__spreadProps$7(__spreadValues$a({}, rest), { geometry: planeGeometry })));
        this._texture = texture;
        this.geometry.setCorners(
          options.x0,
          options.y0,
          options.x1,
          options.y1,
          options.x2,
          options.y2,
          options.x3,
          options.y3
        );
      }
      /** Update the geometry when the texture is updated */
      textureUpdated() {
        const geometry = this.geometry;
        if (!geometry)
          return;
        const { width, height } = this.texture;
        if (geometry.width !== width || geometry.height !== height) {
          geometry.width = width;
          geometry.height = height;
          geometry.updateProjection();
        }
      }
      set texture(value) {
        if (this._texture === value)
          return;
        super.texture = value;
        this.textureUpdated();
      }
      /**
       * The texture that the mesh uses for rendering. When changed, automatically updates
       * the geometry to match the new texture dimensions.
       * @example
       * ```ts
       * const mesh = new PerspectiveMesh({
       *     texture: Texture.from('initial.png'),
       * });
       *
       * // Update texture and maintain perspective
       * mesh.texture = Texture.from('newImage.png');
       * ```
       * @see {@link Texture} For texture creation and management
       * @see {@link PerspectiveMesh#setCorners} For adjusting the mesh perspective
       */
      get texture() {
        return this._texture;
      }
      /**
       * Sets the corners of the mesh to create a perspective transformation. The corners should be
       * specified in clockwise order starting from the top-left.
       *
       * The mesh automatically recalculates the UV coordinates to create the perspective effect.
       * @example
       * ```ts
       * const mesh = new PerspectiveMesh({
       *     texture: Texture.from('myImage.png'),
       * });
       *
       * // Create a basic perspective tilt
       * mesh.setCorners(
       *     0, 0,      // Top-left
       *     100, 20,   // Top-right (raised)
       *     100, 100,  // Bottom-right
       *     0, 80      // Bottom-left
       * );
       *
       * // Create a skewed billboard effect
       * mesh.setCorners(
       *     0, 30,     // Top-left (shifted down)
       *     128, 0,    // Top-right (raised)
       *     128, 128,  // Bottom-right
       *     0, 98      // Bottom-left (shifted up)
       * );
       *
       * // Animate perspective
       * app.ticker.add((delta) => {
       *     const time = performance.now() / 1000;
       *     const wave = Math.sin(time) * 20;
       *
       *     mesh.setCorners(
       *         0, wave,      // Top-left
       *         100, -wave,   // Top-right
       *         100, 100,     // Bottom-right
       *         0, 100        // Bottom-left
       *     );
       * });
       * ```
       * @param x0 - x-coordinate of the top-left corner
       * @param y0 - y-coordinate of the top-left corner
       * @param x1 - x-coordinate of the top-right corner
       * @param y1 - y-coordinate of the top-right corner
       * @param x2 - x-coordinate of the bottom-right corner
       * @param y2 - y-coordinate of the bottom-right corner
       * @param x3 - x-coordinate of the bottom-left corner
       * @param y3 - y-coordinate of the bottom-left corner
       * @returns The PerspectiveMesh instance for method chaining
       * @see {@link PerspectivePlaneGeometry} For the underlying geometry calculations
       */
      setCorners(x0, y0, x1, y1, x2, y2, x3, y3) {
        this.geometry.setCorners(x0, y0, x1, y1, x2, y2, x3, y3);
      }
    };
    /**
     * Default options for creating a PerspectiveMesh instance.
     *
     * Creates a 100x100 pixel square mesh
     * with a white texture and 10x10 vertex grid for the perspective calculations.
     * @example
     * ```ts
     * // Change defaults globally
     * PerspectiveMesh.defaultOptions = {
     *     ...PerspectiveMesh.defaultOptions,
     *     verticesX: 15,
     *     verticesY: 15,
     *     // Move top edge up for default skew
     *     y0: -20,
     *     y1: -20
     * };
     * ```
     * @see {@link PerspectivePlaneOptions} For all available options
     * @see {@link PerspectivePlaneGeometry} For how vertices affect perspective quality
     */
    _PerspectiveMesh.defaultOptions = {
      texture: Texture.WHITE,
      verticesX: 10,
      verticesY: 10,
      x0: 0,
      y0: 0,
      x1: 100,
      y1: 0,
      x2: 100,
      y2: 100,
      x3: 0,
      y3: 100
    };
    let PerspectiveMesh = _PerspectiveMesh;

    "use strict";
    var __defProp$9 = Object.defineProperty;
    var __defProps$6 = Object.defineProperties;
    var __getOwnPropDescs$6 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$a = Object.getOwnPropertySymbols;
    var __hasOwnProp$a = Object.prototype.hasOwnProperty;
    var __propIsEnum$a = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$9 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$a.call(b, prop))
          __defNormalProp$9(a, prop, b[prop]);
      if (__getOwnPropSymbols$a)
        for (var prop of __getOwnPropSymbols$a(b)) {
          if (__propIsEnum$a.call(b, prop))
            __defNormalProp$9(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$6 = (a, b) => __defProps$6(a, __getOwnPropDescs$6(b));
    var __objRest$5 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$a.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$a)
        for (var prop of __getOwnPropSymbols$a(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$a.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class MeshPlane extends Mesh {
      /**
       * @param options - Options to be applied to MeshPlane
       */
      constructor(options) {
        const _a = options, { texture, verticesX, verticesY } = _a, rest = __objRest$5(_a, ["texture", "verticesX", "verticesY"]);
        const planeGeometry = new PlaneGeometry(definedProps({
          width: texture.width,
          height: texture.height,
          verticesX,
          verticesY
        }));
        super(definedProps(__spreadProps$6(__spreadValues$9({}, rest), { geometry: planeGeometry, texture })));
        this.texture = texture;
        this.autoResize = true;
      }
      /**
       * Method used for overrides, to do something in case texture frame was changed.
       * Meshes based on plane can override it and change more details based on texture.
       * @internal
       */
      textureUpdated() {
        const geometry = this.geometry;
        const { width, height } = this.texture;
        if (this.autoResize && (geometry.width !== width || geometry.height !== height)) {
          geometry.width = width;
          geometry.height = height;
          geometry.build({});
        }
      }
      set texture(value) {
        var _a;
        (_a = this._texture) == null ? void 0 : _a.off("update", this.textureUpdated, this);
        super.texture = value;
        value.on("update", this.textureUpdated, this);
        this.textureUpdated();
      }
      /**
       * The texture that the mesh plane uses for rendering. When changed, automatically updates
       * geometry dimensions if autoResize is true and manages texture update event listeners.
       * @example
       * ```ts
       * const plane = new MeshPlane({
       *     texture: Assets.get('initial.png'),
       *     verticesX: 10,
       *     verticesY: 10
       * });
       *
       * // Update texture and auto-resize geometry
       * plane.texture = Assets.get('larger.png');
       * ```
       * @see {@link MeshPlane#autoResize} For controlling automatic geometry updates
       * @see {@link PlaneGeometry} For manual geometry updates
       * @see {@link Texture} For texture creation and management
       */
      get texture() {
        return this._texture;
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * meshPlane.destroy();
       * meshPlane.destroy(true);
       * meshPlane.destroy({ texture: true, textureSource: true });
       */
      destroy(options) {
        this.texture.off("update", this.textureUpdated, this);
        super.destroy(options);
      }
    }

    "use strict";
    var __defProp$8 = Object.defineProperty;
    var __getOwnPropSymbols$9 = Object.getOwnPropertySymbols;
    var __hasOwnProp$9 = Object.prototype.hasOwnProperty;
    var __propIsEnum$9 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$8 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$9.call(b, prop))
          __defNormalProp$8(a, prop, b[prop]);
      if (__getOwnPropSymbols$9)
        for (var prop of __getOwnPropSymbols$9(b)) {
          if (__propIsEnum$9.call(b, prop))
            __defNormalProp$8(a, prop, b[prop]);
        }
      return a;
    };
    const _RopeGeometry = class _RopeGeometry extends MeshGeometry {
      /**
       * @param options - Options to be applied to rope geometry
       */
      constructor(options) {
        const { width, points, textureScale } = __spreadValues$8(__spreadValues$8({}, _RopeGeometry.defaultOptions), options);
        super({
          positions: new Float32Array(points.length * 4),
          uvs: new Float32Array(points.length * 4),
          indices: new Uint32Array((points.length - 1) * 6)
        });
        this.points = points;
        this._width = width;
        this.textureScale = textureScale;
        this._build();
      }
      /**
       * The width (i.e., thickness) of the rope.
       * @readonly
       */
      get width() {
        return this._width;
      }
      /** Refreshes Rope indices and uvs */
      _build() {
        const points = this.points;
        if (!points)
          return;
        const vertexBuffer = this.getBuffer("aPosition");
        const uvBuffer = this.getBuffer("aUV");
        const indexBuffer = this.getIndex();
        if (points.length < 1) {
          return;
        }
        if (vertexBuffer.data.length / 4 !== points.length) {
          vertexBuffer.data = new Float32Array(points.length * 4);
          uvBuffer.data = new Float32Array(points.length * 4);
          indexBuffer.data = new Uint16Array((points.length - 1) * 6);
        }
        const uvs = uvBuffer.data;
        const indices = indexBuffer.data;
        uvs[0] = 0;
        uvs[1] = 0;
        uvs[2] = 0;
        uvs[3] = 1;
        let amount = 0;
        let prev = points[0];
        const textureWidth = this._width * this.textureScale;
        const total = points.length;
        for (let i = 0; i < total; i++) {
          const index = i * 4;
          if (this.textureScale > 0) {
            const dx = prev.x - points[i].x;
            const dy = prev.y - points[i].y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            prev = points[i];
            amount += distance / textureWidth;
          } else {
            amount = i / (total - 1);
          }
          uvs[index] = amount;
          uvs[index + 1] = 0;
          uvs[index + 2] = amount;
          uvs[index + 3] = 1;
        }
        let indexCount = 0;
        for (let i = 0; i < total - 1; i++) {
          const index = i * 2;
          indices[indexCount++] = index;
          indices[indexCount++] = index + 1;
          indices[indexCount++] = index + 2;
          indices[indexCount++] = index + 2;
          indices[indexCount++] = index + 1;
          indices[indexCount++] = index + 3;
        }
        uvBuffer.update();
        indexBuffer.update();
        this.updateVertices();
      }
      /** refreshes vertices of Rope mesh */
      updateVertices() {
        const points = this.points;
        if (points.length < 1) {
          return;
        }
        let lastPoint = points[0];
        let nextPoint;
        let perpX = 0;
        let perpY = 0;
        const vertices = this.buffers[0].data;
        const total = points.length;
        const halfWidth = this.textureScale > 0 ? this.textureScale * this._width / 2 : this._width / 2;
        for (let i = 0; i < total; i++) {
          const point = points[i];
          const index = i * 4;
          if (i < points.length - 1) {
            nextPoint = points[i + 1];
          } else {
            nextPoint = point;
          }
          perpY = -(nextPoint.x - lastPoint.x);
          perpX = nextPoint.y - lastPoint.y;
          let ratio = (1 - i / (total - 1)) * 10;
          if (ratio > 1) {
            ratio = 1;
          }
          const perpLength = Math.sqrt(perpX * perpX + perpY * perpY);
          if (perpLength < 1e-6) {
            perpX = 0;
            perpY = 0;
          } else {
            perpX /= perpLength;
            perpY /= perpLength;
            perpX *= halfWidth;
            perpY *= halfWidth;
          }
          vertices[index] = point.x + perpX;
          vertices[index + 1] = point.y + perpY;
          vertices[index + 2] = point.x - perpX;
          vertices[index + 3] = point.y - perpY;
          lastPoint = point;
        }
        this.buffers[0].update();
      }
      /** Refreshes Rope indices and uvs */
      update() {
        if (this.textureScale > 0) {
          this._build();
        } else {
          this.updateVertices();
        }
      }
    };
    /** Default options for RopeGeometry constructor. */
    _RopeGeometry.defaultOptions = {
      /** The width (i.e., thickness) of the rope. */
      width: 200,
      /** An array of points that determine the rope. */
      points: [],
      /** Rope texture scale, if zero then the rope texture is stretched. */
      textureScale: 0
    };
    let RopeGeometry = _RopeGeometry;

    "use strict";
    var __defProp$7 = Object.defineProperty;
    var __defProps$5 = Object.defineProperties;
    var __getOwnPropDescs$5 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$8 = Object.getOwnPropertySymbols;
    var __hasOwnProp$8 = Object.prototype.hasOwnProperty;
    var __propIsEnum$8 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$7 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$8.call(b, prop))
          __defNormalProp$7(a, prop, b[prop]);
      if (__getOwnPropSymbols$8)
        for (var prop of __getOwnPropSymbols$8(b)) {
          if (__propIsEnum$8.call(b, prop))
            __defNormalProp$7(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
    var __objRest$4 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$8.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$8)
        for (var prop of __getOwnPropSymbols$8(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$8.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const _MeshRope = class _MeshRope extends Mesh {
      /**
       * Note: The wrap mode of the texture is set to REPEAT if `textureScale` is positive.
       * @param options
       * @param options.texture - The texture to use on the rope.
       * @param options.points - An array of {@link math.Point} objects to construct this rope.
       * @param {number} options.textureScale - Optional. Positive values scale rope texture
       * keeping its aspect ratio. You can reduce alpha channel artifacts by providing a larger texture
       * and downsampling here. If set to zero, texture will be stretched instead.
       */
      constructor(options) {
        const _a = __spreadValues$7(__spreadValues$7({}, _MeshRope.defaultOptions), options), { texture, points, textureScale } = _a, rest = __objRest$4(_a, ["texture", "points", "textureScale"]);
        const ropeGeometry = new RopeGeometry(definedProps({ width: texture.height, points, textureScale }));
        if (textureScale > 0) {
          texture.source.style.addressMode = "repeat";
        }
        super(definedProps(__spreadProps$5(__spreadValues$7({}, rest), {
          texture,
          geometry: ropeGeometry
        })));
        this.autoUpdate = true;
        this.onRender = this._render;
      }
      _render() {
        const geometry = this.geometry;
        if (this.autoUpdate || geometry._width !== this.texture.height) {
          geometry._width = this.texture.height;
          geometry.update();
        }
      }
    };
    /**
     * Default options for creating a MeshRope instance. These values are used when specific
     * options aren't provided in the constructor.
     * @example
     * ```ts
     * // Use default options globally
     * MeshRope.defaultOptions = {
     *     textureScale: 0.5  // Set higher quality texture scaling
     * };
     *
     * // Create rope with modified defaults
     * const rope = new MeshRope({
     *     texture: Texture.from('rope.png'),
     *     points: [
     *         new Point(0, 0),
     *         new Point(100, 0)
     *     ]
     * }); // Will use textureScale: 0.5
     * ```
     * @property {number} textureScale - Controls texture scaling along the rope (0 = stretch)
     * @see {@link MeshRopeOptions} For all available options
     */
    _MeshRope.defaultOptions = {
      textureScale: 0
    };
    let MeshRope = _MeshRope;

    "use strict";
    var __defProp$6 = Object.defineProperty;
    var __defProps$4 = Object.defineProperties;
    var __getOwnPropDescs$4 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$7 = Object.getOwnPropertySymbols;
    var __hasOwnProp$7 = Object.prototype.hasOwnProperty;
    var __propIsEnum$7 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$6 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$7.call(b, prop))
          __defNormalProp$6(a, prop, b[prop]);
      if (__getOwnPropSymbols$7)
        for (var prop of __getOwnPropSymbols$7(b)) {
          if (__propIsEnum$7.call(b, prop))
            __defNormalProp$6(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$4 = (a, b) => __defProps$4(a, __getOwnPropDescs$4(b));
    var __objRest$3 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$7.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$7)
        for (var prop of __getOwnPropSymbols$7(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$7.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class MeshSimple extends Mesh {
      /**
       * @param options - Options to be used for construction
       */
      constructor(options) {
        const _a = options, { texture, vertices, uvs, indices, topology } = _a, rest = __objRest$3(_a, ["texture", "vertices", "uvs", "indices", "topology"]);
        const geometry = new MeshGeometry(definedProps({
          positions: vertices,
          uvs,
          indices,
          topology
        }));
        super(definedProps(__spreadProps$4(__spreadValues$6({}, rest), {
          texture,
          geometry
        })));
        this.autoUpdate = true;
        this.onRender = this._render;
      }
      /**
       * The vertex positions of the mesh as a TypedArray. Each vertex is represented by two
       * consecutive values (x, y) in the array. Changes to these values will update the mesh's shape.
       * @example
       * ```ts
       * // Read vertex positions
       * const vertices = mesh.vertices;
       * console.log('First vertex:', vertices[0], vertices[1]);
       *
       * // Modify vertices directly
       * vertices[0] += 10;  // Move first vertex right
       * vertices[1] -= 20;  // Move first vertex up
       *
       * // Animate vertices
       * app.ticker.add(() => {
       *     const time = performance.now() / 1000;
       *     const vertices = mesh.vertices;
       *
       *     // Wave motion
       *     for (let i = 0; i < vertices.length; i += 2) {
       *         vertices[i + 1] = Math.sin(time + i * 0.5) * 20;
       *     }
       * });
       * ```
       * @see {@link MeshSimple#autoUpdate} For controlling vertex buffer updates
       * @see {@link MeshGeometry#getBuffer} For direct buffer access
       */
      get vertices() {
        return this.geometry.getBuffer("aPosition").data;
      }
      set vertices(value) {
        this.geometry.getBuffer("aPosition").data = value;
      }
      _render() {
        if (this.autoUpdate) {
          this.geometry.getBuffer("aPosition").update();
        }
      }
    }

    "use strict";
    function getTextureDefaultMatrix(texture, out) {
      const { width, height } = texture.frame;
      out.scale(1 / width, 1 / height);
      return out;
    }

    "use strict";
    var __defProp$5 = Object.defineProperty;
    var __getOwnPropSymbols$6 = Object.getOwnPropertySymbols;
    var __hasOwnProp$6 = Object.prototype.hasOwnProperty;
    var __propIsEnum$6 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$5 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$6.call(b, prop))
          __defNormalProp$5(a, prop, b[prop]);
      if (__getOwnPropSymbols$6)
        for (var prop of __getOwnPropSymbols$6(b)) {
          if (__propIsEnum$6.call(b, prop))
            __defNormalProp$5(a, prop, b[prop]);
        }
      return a;
    };
    const _Particle = class _Particle {
      constructor(options) {
        if (options instanceof Texture) {
          this.texture = options;
          assignWithIgnore(this, _Particle.defaultOptions, {});
        } else {
          const combined = __spreadValues$5(__spreadValues$5({}, _Particle.defaultOptions), options);
          assignWithIgnore(this, combined, {});
        }
      }
      /**
       * The transparency of the particle. Values range from 0 (fully transparent)
       * to 1 (fully opaque). Values outside this range are clamped.
       * @example
       * ```ts
       * // Create a semi-transparent particle
       * const particle = new Particle({
       *     texture: Texture.from('particle.png'),
       *     alpha: 0.5
       * });
       *
       * // Fade out
       * particle.alpha *= 0.9;
       *
       * // Fade in
       * particle.alpha = Math.min(particle.alpha + 0.1, 1);
       *
       * // Values are clamped to valid range
       * particle.alpha = 1.5; // Becomes 1.0
       * particle.alpha = -0.5; // Becomes 0.0
       *
       * // Animate transparency
       * app.ticker.add((delta) => {
       *     const time = performance.now() / 1000;
       *     particle.alpha = 0.5 + Math.sin(time) * 0.5; // Pulse between 0-1
       * });
       * ```
       * @default 1
       * @see {@link Particle#tint} For controlling particle color
       * @see {@link Particle#color} For the combined color and alpha value
       */
      get alpha() {
        return this._alpha;
      }
      set alpha(value) {
        this._alpha = Math.min(Math.max(value, 0), 1);
        this._updateColor();
      }
      /**
       * The tint color of the particle. Can be set using hex numbers or CSS color strings.
       * The tint is multiplied with the texture color to create the final particle color.
       * @example
       * ```ts
       * // Create a red particle
       * const particle = new Particle({
       *     texture: Texture.from('particle.png'),
       *     tint: 0xff0000
       * });
       *
       * // Use CSS color strings
       * particle.tint = '#00ff00';  // Green
       * particle.tint = 'blue';     // Blue
       *
       * // Animate tint color
       * app.ticker.add(() => {
       *     const time = performance.now() / 1000;
       *
       *     // Cycle through hues
       *     const hue = (time * 50) % 360;
       *     particle.tint = `hsl(${hue}, 100%, 50%)`;
       * });
       *
       * // Reset to white (no tint)
       * particle.tint = 0xffffff;
       * ```
       * @type {ColorSource} Hex number or CSS color string
       * @default 0xffffff
       * @see {@link Particle#alpha} For controlling transparency
       * @see {@link Particle#color} For the combined color and alpha value
       * @see {@link Color} For supported color formats
       */
      get tint() {
        return bgr2rgb(this._tint);
      }
      set tint(value) {
        this._tint = Color.shared.setValue(value != null ? value : 16777215).toBgrNumber();
        this._updateColor();
      }
      _updateColor() {
        this.color = this._tint + ((this._alpha * 255 | 0) << 24);
      }
    };
    /**
     * Default options used when creating new particles. These values are applied when specific
     * options aren't provided in the constructor.
     * @example
     * ```ts
     * // Override defaults globally
     * Particle.defaultOptions = {
     *     ...Particle.defaultOptions,
     *     anchorX: 0.5,
     *     anchorY: 0.5,
     *     alpha: 0.8
     * };
     *
     * // New particles use modified defaults
     * const centeredParticle = new Particle(texture);
     * console.log(centeredParticle.anchorX); // 0.5
     * console.log(centeredParticle.alpha); // 0.8
     * ```
     * @see {@link ParticleOptions} For all available options
     * @see {@link Particle} For the particle implementation
     */
    _Particle.defaultOptions = {
      anchorX: 0,
      anchorY: 0,
      x: 0,
      y: 0,
      scaleX: 1,
      scaleY: 1,
      rotation: 0,
      tint: 16777215,
      alpha: 1
    };
    let Particle = _Particle;

    "use strict";
    const particleData = {
      vertex: {
        attributeName: "aVertex",
        format: "float32x2",
        code: `
            const texture = p.texture;
            const sx = p.scaleX;
            const sy = p.scaleY;
            const ax = p.anchorX;
            const ay = p.anchorY;
            const trim = texture.trim;
            const orig = texture.orig;

            if (trim)
            {
                w1 = trim.x - (ax * orig.width);
                w0 = w1 + trim.width;

                h1 = trim.y - (ay * orig.height);
                h0 = h1 + trim.height;
            }
            else
            {
                w1 = -ax * (orig.width);
                w0 = w1 + orig.width;

                h1 = -ay * (orig.height);
                h0 = h1 + orig.height;
            }

            f32v[offset] = w1 * sx;
            f32v[offset + 1] = h1 * sy;

            f32v[offset + stride] = w0 * sx;
            f32v[offset + stride + 1] = h1 * sy;

            f32v[offset + (stride * 2)] = w0 * sx;
            f32v[offset + (stride * 2) + 1] = h0 * sy;

            f32v[offset + (stride * 3)] = w1 * sx;
            f32v[offset + (stride * 3) + 1] = h0 * sy;
        `,
        dynamic: false
      },
      // positionData
      position: {
        attributeName: "aPosition",
        format: "float32x2",
        code: `
            var x = p.x;
            var y = p.y;

            f32v[offset] = x;
            f32v[offset + 1] = y;

            f32v[offset + stride] = x;
            f32v[offset + stride + 1] = y;

            f32v[offset + (stride * 2)] = x;
            f32v[offset + (stride * 2) + 1] = y;

            f32v[offset + (stride * 3)] = x;
            f32v[offset + (stride * 3) + 1] = y;
        `,
        dynamic: true
      },
      // rotationData
      rotation: {
        attributeName: "aRotation",
        format: "float32",
        code: `
            var rotation = p.rotation;

            f32v[offset] = rotation;
            f32v[offset + stride] = rotation;
            f32v[offset + (stride * 2)] = rotation;
            f32v[offset + (stride * 3)] = rotation;
        `,
        dynamic: false
      },
      // uvsData
      uvs: {
        attributeName: "aUV",
        format: "float32x2",
        code: `
            var uvs = p.texture.uvs;

            f32v[offset] = uvs.x0;
            f32v[offset + 1] = uvs.y0;

            f32v[offset + stride] = uvs.x1;
            f32v[offset + stride + 1] = uvs.y1;

            f32v[offset + (stride * 2)] = uvs.x2;
            f32v[offset + (stride * 2) + 1] = uvs.y2;

            f32v[offset + (stride * 3)] = uvs.x3;
            f32v[offset + (stride * 3) + 1] = uvs.y3;
        `,
        dynamic: false
      },
      // tintData
      color: {
        attributeName: "aColor",
        format: "unorm8x4",
        code: `
            const c = p.color;

            u32v[offset] = c;
            u32v[offset + stride] = c;
            u32v[offset + (stride * 2)] = c;
            u32v[offset + (stride * 3)] = c;
        `,
        dynamic: false
      }
    };

    "use strict";
    var __defProp$4 = Object.defineProperty;
    var __defProps$3 = Object.defineProperties;
    var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$5 = Object.getOwnPropertySymbols;
    var __hasOwnProp$5 = Object.prototype.hasOwnProperty;
    var __propIsEnum$5 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$4 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$5.call(b, prop))
          __defNormalProp$4(a, prop, b[prop]);
      if (__getOwnPropSymbols$5)
        for (var prop of __getOwnPropSymbols$5(b)) {
          if (__propIsEnum$5.call(b, prop))
            __defNormalProp$4(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
    var __objRest$2 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$5.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$5)
        for (var prop of __getOwnPropSymbols$5(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$5.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const emptyBounds = new Bounds(0, 0, 0, 0);
    const _ParticleContainer = class _ParticleContainer extends ViewContainer {
      /**
       * @param options - The options for creating the sprite.
       */
      constructor(options = {}) {
        options = __spreadProps$3(__spreadValues$4(__spreadValues$4({}, _ParticleContainer.defaultOptions), options), {
          dynamicProperties: __spreadValues$4(__spreadValues$4({}, _ParticleContainer.defaultOptions.dynamicProperties), options == null ? void 0 : options.dynamicProperties)
        });
        const _a = options, { dynamicProperties, shader, roundPixels, texture, particles } = _a, rest = __objRest$2(_a, ["dynamicProperties", "shader", "roundPixels", "texture", "particles"]);
        super(__spreadValues$4({
          label: "ParticleContainer"
        }, rest));
        /**
         * The unique identifier for the render pipe of this ParticleContainer.
         * @internal
         */
        this.renderPipeId = "particle";
        /** @internal */
        this.batched = false;
        /**
         * Indicates if the children of this ParticleContainer have changed and need to be updated.
         * @internal
         */
        this._childrenDirty = false;
        this.texture = texture || null;
        this.shader = shader;
        this._properties = {};
        for (const key in particleData) {
          const property = particleData[key];
          const dynamic = dynamicProperties[key];
          this._properties[key] = __spreadProps$3(__spreadValues$4({}, property), {
            dynamic
          });
        }
        this.allowChildren = true;
        this.roundPixels = roundPixels != null ? roundPixels : false;
        this.particleChildren = particles != null ? particles : [];
      }
      /**
       * Adds one or more particles to the container. The particles will be rendered using the container's shared texture
       * and properties. When adding multiple particles, they must all share the same base texture.
       * @example
       * ```ts
       * const container = new ParticleContainer();
       *
       * // Add a single particle
       * const particle = new Particle(Assets.get('particleTexture'));
       * container.addParticle(particle);
       *
       * // Add multiple particles at once
       * const particles = [
       *     new Particle(Assets.get('particleTexture')),
       *     new Particle(Assets.get('particleTexture')),
       *     new Particle(Assets.get('particleTexture'))
       * ];
       *
       * container.addParticle(...particles);
       * ```
       * @param children - The Particle(s) to add to the container
       * @returns The first particle that was added, for method chaining
       * @see {@link ParticleContainer#texture} For setting the shared texture
       * @see {@link ParticleContainer#update} For updating after modifications
       */
      addParticle(...children) {
        for (let i = 0; i < children.length; i++) {
          this.particleChildren.push(children[i]);
        }
        this.onViewUpdate();
        return children[0];
      }
      /**
       * Removes one or more particles from the container. The particles must already be children
       * of this container to be removed.
       * @example
       * ```ts
       * // Remove a single particle
       * container.removeParticle(particle1);
       *
       * // Remove multiple particles at once
       * container.removeParticle(particle2, particle3);
       * ```
       * @param children - The Particle(s) to remove from the container
       * @returns The first particle that was removed, for method chaining
       * @see {@link ParticleContainer#particleChildren} For accessing all particles
       * @see {@link ParticleContainer#removeParticles} For removing particles by index
       * @see {@link ParticleContainer#removeParticleAt} For removing a particle at a specific index
       */
      removeParticle(...children) {
        let didRemove = false;
        for (let i = 0; i < children.length; i++) {
          const index = this.particleChildren.indexOf(children[i]);
          if (index > -1) {
            this.particleChildren.splice(index, 1);
            didRemove = true;
          }
        }
        if (didRemove)
          this.onViewUpdate();
        return children[0];
      }
      /**
       * Updates the particle container's internal state. Call this method after manually modifying
       * the particleChildren array or when changing static properties of particles.
       * @example
       * ```ts
       * // Batch modify particles
       * container.particleChildren.push(...particles);
       * container.update(); // Required after direct array modification
       *
       * // Update static properties
       * container.particleChildren.forEach(particle => {
       *     particle.position.set(
       *         Math.random() * 800,
       *         Math.random() * 600
       *     );
       * });
       * container.update(); // Required after changing static positions
       * ```
       * @see {@link ParticleProperties} For configuring dynamic vs static properties
       * @see {@link ParticleContainer#particleChildren} For direct array access
       */
      update() {
        this._childrenDirty = true;
      }
      onViewUpdate() {
        this._childrenDirty = true;
        super.onViewUpdate();
      }
      /**
       * Returns a static empty bounds object since ParticleContainer does not calculate bounds automatically
       * for performance reasons. Use the `boundsArea` property to manually set container bounds.
       * @example
       * ```ts
       * const container = new ParticleContainer({
       *     texture: Texture.from('particle.png')
       * });
       *
       * // Default bounds are empty
       * console.log(container.bounds); // Bounds(0, 0, 0, 0)
       *
       * // Set manual bounds for the particle area
       * container.boundsArea = {
       *     minX: 0,
       *     minY: 0,
       *     maxX: 800,
       *     maxY: 600
       * };
       * ```
       * @readonly
       * @returns {Bounds} An empty bounds object (0,0,0,0)
       * @see {@link Container#boundsArea} For manually setting container bounds
       * @see {@link Bounds} For bounds object structure
       */
      get bounds() {
        return emptyBounds;
      }
      /** @private */
      updateBounds() {
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * particleContainer.destroy();
       * particleContainer.destroy(true);
       * particleContainer.destroy({ texture: true, textureSource: true, children: true });
       */
      destroy(options = false) {
        var _a, _b, _c;
        super.destroy(options);
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          const texture = (_b = this.texture) != null ? _b : (_a = this.particleChildren[0]) == null ? void 0 : _a.texture;
          if (texture) {
            texture.destroy(destroyTextureSource);
          }
        }
        this.texture = null;
        (_c = this.shader) == null ? void 0 : _c.destroy();
      }
      /**
       * Removes all particles from this container that are within the begin and end indexes.
       * @param beginIndex - The beginning position.
       * @param endIndex - The ending position. Default value is size of the container.
       * @returns - List of removed particles
       */
      removeParticles(beginIndex, endIndex) {
        beginIndex != null ? beginIndex : beginIndex = 0;
        endIndex != null ? endIndex : endIndex = this.particleChildren.length;
        const children = this.particleChildren.splice(
          beginIndex,
          endIndex - beginIndex
        );
        this.onViewUpdate();
        return children;
      }
      /**
       * Removes a particle from the specified index position.
       * @param index - The index to get the particle from
       * @returns The particle that was removed.
       */
      removeParticleAt(index) {
        const child = this.particleChildren.splice(index, 1);
        this.onViewUpdate();
        return child[0];
      }
      /**
       * Adds a particle to the container at a specified index. If the index is out of bounds an error will be thrown.
       * If the particle is already in this container, it will be moved to the specified index.
       * @param {Container} child - The particle to add.
       * @param {number} index - The absolute index where the particle will be positioned at the end of the operation.
       * @returns {Container} The particle that was added.
       */
      addParticleAt(child, index) {
        this.particleChildren.splice(index, 0, child);
        this.onViewUpdate();
        return child;
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.addParticle()` instead.
       * @param {...any} _children
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      addChild(..._children) {
        throw new Error(
          "ParticleContainer.addChild() is not available. Please use ParticleContainer.addParticle()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       * Calling this method will throw an error. Please use `ParticleContainer.removeParticle()` instead.
       * @param {...any} _children
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChild(..._children) {
        throw new Error(
          "ParticleContainer.removeChild() is not available. Please use ParticleContainer.removeParticle()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.removeParticles()` instead.
       * @param {number} [_beginIndex]
       * @param {number} [_endIndex]
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChildren(_beginIndex, _endIndex) {
        throw new Error(
          "ParticleContainer.removeChildren() is not available. Please use ParticleContainer.removeParticles()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.removeParticleAt()` instead.
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      removeChildAt(_index) {
        throw new Error(
          "ParticleContainer.removeChildAt() is not available. Please use ParticleContainer.removeParticleAt()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.getParticleAt()` instead.
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      getChildAt(_index) {
        throw new Error(
          "ParticleContainer.getChildAt() is not available. Please use ParticleContainer.getParticleAt()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.setParticleIndex()` instead.
       * @param {ContainerChild} _child
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      setChildIndex(_child, _index) {
        throw new Error(
          "ParticleContainer.setChildIndex() is not available. Please use ParticleContainer.setParticleIndex()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.getParticleIndex()` instead.
       * @param {ContainerChild} _child
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      getChildIndex(_child) {
        throw new Error(
          "ParticleContainer.getChildIndex() is not available. Please use ParticleContainer.getParticleIndex()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.addParticleAt()` instead.
       * @param {ContainerChild} _child
       * @param {number} _index
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      addChildAt(_child, _index) {
        throw new Error(
          "ParticleContainer.addChildAt() is not available. Please use ParticleContainer.addParticleAt()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error. Please use `ParticleContainer.swapParticles()` instead.
       * @param {ContainerChild} _child
       * @param {ContainerChild} _child2
       * @ignore
       */
      swapChildren(_child, _child2) {
        throw new Error(
          "ParticleContainer.swapChildren() is not available. Please use ParticleContainer.swapParticles()"
        );
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error.
       * @param _child - The child to reparent
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      reparentChild(..._child) {
        throw new Error("ParticleContainer.reparentChild() is not available with the particle container");
      }
      /**
       * This method is not available in ParticleContainer.
       *
       * Calling this method will throw an error.
       * @param _child - The child to reparent
       * @param _index - The index to reparent the child to
       * @throws {Error} Always throws an error as this method is not available.
       * @ignore
       */
      reparentChildAt(_child, _index) {
        throw new Error("ParticleContainer.reparentChildAt() is not available with the particle container");
      }
    };
    /**
     * Defines the default options for creating a ParticleContainer.
     * @example
     * ```ts
     * // Change defaults globally
     * ParticleContainer.defaultOptions = {
     *     dynamicProperties: {
     *         position: true,  // Update positions each frame
     *         rotation: true,  // Update rotations each frame
     *         vertex: false,   // Static vertices
     *         uvs: false,      // Static texture coordinates
     *         color: false     // Static colors
     *     },
     *     roundPixels: true // Enable pixel rounding for crisp rendering
     * };
     * ```
     * @property {Record<string, boolean>} dynamicProperties - Specifies which properties are dynamic.
     * @property {boolean} roundPixels - Indicates if pixels should be rounded.
     */
    _ParticleContainer.defaultOptions = {
      /** Specifies which properties are dynamic. */
      dynamicProperties: {
        /** Indicates if vertex positions are dynamic. */
        vertex: false,
        /** Indicates if particle positions are dynamic. */
        position: true,
        /** Indicates if particle rotations are dynamic. */
        rotation: false,
        /** Indicates if UV coordinates are dynamic. */
        uvs: false,
        /** Indicates if particle colors are dynamic. */
        color: false
      },
      /** Indicates if pixels should be rounded for rendering. */
      roundPixels: false
    };
    let ParticleContainer = _ParticleContainer;

    "use strict";
    var __defProp$3 = Object.defineProperty;
    var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols;
    var __hasOwnProp$4 = Object.prototype.hasOwnProperty;
    var __propIsEnum$4 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$3 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$4.call(b, prop))
          __defNormalProp$3(a, prop, b[prop]);
      if (__getOwnPropSymbols$4)
        for (var prop of __getOwnPropSymbols$4(b)) {
          if (__propIsEnum$4.call(b, prop))
            __defNormalProp$3(a, prop, b[prop]);
        }
      return a;
    };
    var __objRest$1 = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$4.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$4)
        for (var prop of __getOwnPropSymbols$4(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$4.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    const _NineSliceSprite = class _NineSliceSprite extends ViewContainer {
      constructor(options) {
        var _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
        if (options instanceof Texture) {
          options = { texture: options };
        }
        const _a = options, {
          width,
          height,
          anchor,
          leftWidth,
          rightWidth,
          topHeight,
          bottomHeight,
          texture,
          roundPixels
        } = _a, rest = __objRest$1(_a, [
          "width",
          "height",
          "anchor",
          "leftWidth",
          "rightWidth",
          "topHeight",
          "bottomHeight",
          "texture",
          "roundPixels"
        ]);
        super(__spreadValues$3({
          label: "NineSliceSprite"
        }, rest));
        /** @internal */
        this.renderPipeId = "nineSliceSprite";
        /** @internal */
        this.batched = true;
        this._leftWidth = (_c = leftWidth != null ? leftWidth : (_b = texture == null ? void 0 : texture.defaultBorders) == null ? void 0 : _b.left) != null ? _c : NineSliceGeometry.defaultOptions.leftWidth;
        this._topHeight = (_e = topHeight != null ? topHeight : (_d = texture == null ? void 0 : texture.defaultBorders) == null ? void 0 : _d.top) != null ? _e : NineSliceGeometry.defaultOptions.topHeight;
        this._rightWidth = (_g = rightWidth != null ? rightWidth : (_f = texture == null ? void 0 : texture.defaultBorders) == null ? void 0 : _f.right) != null ? _g : NineSliceGeometry.defaultOptions.rightWidth;
        this._bottomHeight = (_i = bottomHeight != null ? bottomHeight : (_h = texture == null ? void 0 : texture.defaultBorders) == null ? void 0 : _h.bottom) != null ? _i : NineSliceGeometry.defaultOptions.bottomHeight;
        this._width = (_j = width != null ? width : texture.width) != null ? _j : NineSliceGeometry.defaultOptions.width;
        this._height = (_k = height != null ? height : texture.height) != null ? _k : NineSliceGeometry.defaultOptions.height;
        this.allowChildren = false;
        this.texture = texture != null ? texture : _NineSliceSprite.defaultOptions.texture;
        this.roundPixels = roundPixels != null ? roundPixels : false;
        this._anchor = new ObservablePoint(
          {
            _onUpdate: () => {
              this.onViewUpdate();
            }
          }
        );
        if (anchor) {
          this.anchor = anchor;
        } else if (this.texture.defaultAnchor) {
          this.anchor = this.texture.defaultAnchor;
        }
      }
      /**
       * The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
       * and passed to the constructor.
       *
       * - The default is `(0,0)`, this means the sprite's origin is the top left.
       * - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
       * - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
       *
       * If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
       * @example
       * ```ts
       * // Center the anchor point
       * sprite.anchor = 0.5; // Sets both x and y to 0.5
       * sprite.position.set(400, 300); // Sprite will be centered at this position
       *
       * // Set specific x/y anchor points
       * sprite.anchor = {
       *     x: 1, // Right edge
       *     y: 0  // Top edge
       * };
       *
       * // Using individual coordinates
       * sprite.anchor.set(0.5, 1); // Center-bottom
       *
       * // For rotation around center
       * sprite.anchor.set(0.5);
       * sprite.rotation = Math.PI / 4; // 45 degrees around center
       *
       * // For scaling from center
       * sprite.anchor.set(0.5);
       * sprite.scale.set(2); // Scales from center point
       * ```
       */
      get anchor() {
        return this._anchor;
      }
      set anchor(value) {
        typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
      }
      /**
       * The width of the NineSliceSprite, setting this will actually modify the vertices and UV's of this plane.
       * The width affects how the middle sections are scaled.
       * @example
       * ```ts
       * // Create a nine-slice sprite with fixed width
       * const panel = new NineSliceSprite({
       *     texture: Texture.from('panel.png'),
       *     width: 200  // Sets initial width
       * });
       *
       * // Adjust width dynamically
       * panel.width = 300;  // Stretches middle sections
       * ```
       * @see {@link NineSliceSprite#setSize} For setting both width and height efficiently
       * @see {@link NineSliceSprite#height} For setting height
       */
      get width() {
        return this._width;
      }
      set width(value) {
        this._width = value;
        this.onViewUpdate();
      }
      /**
       * The height of the NineSliceSprite, setting this will actually modify the vertices and UV's of this plane.
       * The height affects how the middle sections are scaled.
       * @example
       * ```ts
       * // Create a nine-slice sprite with fixed height
       * const panel = new NineSliceSprite({
       *     texture: Texture.from('panel.png'),
       *     height: 150  // Sets initial height
       * });
       *
       * // Adjust height dynamically
       * panel.height = 200;  // Stretches middle sections
       *
       * // Create responsive UI element
       * const dialog = new NineSliceSprite({
       *     texture: Texture.from('dialog.png'),
       *     topHeight: 30,
       *     bottomHeight: 30,
       *     height: parent.height * 0.5  // 50% of parent height
       * });
       * ```
       * @see {@link NineSliceSprite#setSize} For setting both width and height efficiently
       * @see {@link NineSliceSprite#width} For setting width
       */
      get height() {
        return this._height;
      }
      set height(value) {
        this._height = value;
        this.onViewUpdate();
      }
      /**
       * Sets the size of the NineSliceSprite to the specified width and height.
       * This method directly modifies the vertices and UV coordinates of the sprite.
       *
       * Using this is more efficient than setting width and height separately as it only triggers one update.
       * @example
       * ```ts
       * // Set to specific dimensions
       * panel.setSize(300, 200); // Width: 300, Height: 200
       *
       * // Set uniform size
       * panel.setSize(200); // Makes a square 200x200
       *
       * // Set size using object
       * panel.setSize({
       *     width: 400,
       *     height: 300
       * });
       * ```
       * @param value - This can be either a number or a Size object with width/height properties
       * @param height - The height to set. Defaults to the value of `width` if not provided
       * @see {@link NineSliceSprite#width} For setting width only
       * @see {@link NineSliceSprite#height} For setting height only
       */
      setSize(value, height) {
        var _a;
        if (typeof value === "object") {
          height = (_a = value.height) != null ? _a : value.width;
          value = value.width;
        }
        this._width = value;
        this._height = height != null ? height : value;
        this.onViewUpdate();
      }
      /**
       * Retrieves the size of the NineSliceSprite as a [Size]{@link Size} object.
       * This method is more efficient than getting width and height separately.
       * @example
       * ```ts
       * // Get basic size
       * const size = panel.getSize();
       * console.log(`Size: ${size.width}x${size.height}`);
       *
       * // Reuse existing size object
       * const reuseSize = { width: 0, height: 0 };
       * panel.getSize(reuseSize);
       * ```
       * @param out - Optional object to store the size in, to avoid allocating a new object
       * @returns The size of the NineSliceSprite
       * @see {@link NineSliceSprite#width} For getting just the width
       * @see {@link NineSliceSprite#height} For getting just the height
       * @see {@link NineSliceSprite#setSize} For setting both width and height efficiently
       */
      getSize(out) {
        out || (out = {});
        out.width = this._width;
        out.height = this._height;
        return out;
      }
      /**
       * Width of the left vertical bar (A).
       * Controls the size of the left edge that remains unscaled
       * @example
       * ```ts
       * const sprite = new NineSliceSprite({ ..., leftWidth: 20 });
       * sprite.leftWidth = 20; // Set left border width
       * ```
       * @default 10
       */
      get leftWidth() {
        return this._leftWidth;
      }
      set leftWidth(value) {
        this._leftWidth = value;
        this.onViewUpdate();
      }
      /**
       * Height of the top horizontal bar (C).
       * Controls the size of the top edge that remains unscaled
       * @example
       * ```ts
       * const sprite = new NineSliceSprite({ ..., topHeight: 20 });
       * sprite.topHeight = 20; // Set top border height
       * ```
       * @default 10
       */
      get topHeight() {
        return this._topHeight;
      }
      set topHeight(value) {
        this._topHeight = value;
        this.onViewUpdate();
      }
      /**
       * Width of the right vertical bar (B).
       * Controls the size of the right edge that remains unscaled
       * @example
       * ```ts
       * const sprite = new NineSliceSprite({ ..., rightWidth: 20 });
       * sprite.rightWidth = 20; // Set right border width
       * ```
       * @default 10
       */
      get rightWidth() {
        return this._rightWidth;
      }
      set rightWidth(value) {
        this._rightWidth = value;
        this.onViewUpdate();
      }
      /**
       * Height of the bottom horizontal bar (D).
       * Controls the size of the bottom edge that remains unscaled
       * @example
       * ```ts
       * const sprite = new NineSliceSprite({ ..., bottomHeight: 20 });
       * sprite.bottomHeight = 20; // Set bottom border height
       * ```
       * @default 10
       */
      get bottomHeight() {
        return this._bottomHeight;
      }
      set bottomHeight(value) {
        this._bottomHeight = value;
        this.onViewUpdate();
      }
      /**
       * The texture to use on the NineSliceSprite.
       * ```ts
       * // Create a sprite with a texture
       * const sprite = new NineSliceSprite({
       *     texture: Texture.from('path/to/image.png')
       * });
       * // Update the texture later
       * sprite.texture = Texture.from('path/to/another-image.png');
       * ```
       * @default Texture.EMPTY
       */
      get texture() {
        return this._texture;
      }
      set texture(value) {
        value || (value = Texture.EMPTY);
        const currentTexture = this._texture;
        if (currentTexture === value)
          return;
        if (currentTexture && currentTexture.dynamic)
          currentTexture.off("update", this.onViewUpdate, this);
        if (value.dynamic)
          value.on("update", this.onViewUpdate, this);
        this._texture = value;
        this.onViewUpdate();
      }
      /**
       * The original width of the texture before any nine-slice scaling.
       * This is the width of the source texture used to create the nine-slice sprite.
       * @example
       * ```ts
       * // Get original dimensions
       * console.log(`Original size: ${sprite.originalWidth}x${sprite.originalHeight}`);
       *
       * // Use for relative scaling
       * sprite.width = sprite.originalWidth * 2; // Double the original width
       *
       * // Reset to original size
       * sprite.setSize(sprite.originalWidth, sprite.originalHeight);
       * ```
       * @readonly
       * @see {@link NineSliceSprite#width} For the current displayed width
       * @see {@link Texture#width} For direct texture width access
       * @returns The original width of the texture
       */
      get originalWidth() {
        return this._texture.width;
      }
      /**
       * The original height of the texture before any nine-slice scaling.
       * This is the height of the source texture used to create the nine-slice sprite.
       * @example
       * ```ts
       * // Get original dimensions
       * console.log(`Original size: ${sprite.originalWidth}x${sprite.originalHeight}`);
       *
       * // Use for relative scaling
       * sprite.height = sprite.originalHeight * 2; // Double the original height
       *
       * // Reset to original size
       * sprite.setSize(sprite.originalWidth, sprite.originalHeight);
       * ```
       * @readonly
       * @see {@link NineSliceSprite#height} For the current displayed height
       * @see {@link Texture#height} For direct texture height access
       * @returns The original height of the texture
       */
      get originalHeight() {
        return this._texture.height;
      }
      /**
       * Destroys this sprite renderable and optionally its texture.
       * @param options - Options parameter. A boolean will act as if all options
       *  have been set to that value
       * @example
       * nineSliceSprite.destroy();
       * nineSliceSprite.destroy(true);
       * nineSliceSprite.destroy({ texture: true, textureSource: true });
       */
      destroy(options) {
        super.destroy(options);
        const destroyTexture = typeof options === "boolean" ? options : options == null ? void 0 : options.texture;
        if (destroyTexture) {
          const destroyTextureSource = typeof options === "boolean" ? options : options == null ? void 0 : options.textureSource;
          this._texture.destroy(destroyTextureSource);
        }
        this._texture = null;
      }
      /** @private */
      updateBounds() {
        const bounds = this._bounds;
        const anchor = this._anchor;
        const width = this._width;
        const height = this._height;
        bounds.minX = -anchor._x * width;
        bounds.maxX = bounds.minX + width;
        bounds.minY = -anchor._y * height;
        bounds.maxY = bounds.minY + height;
      }
    };
    /**
     * The default options used to override initial values of any options passed in the constructor.
     * These values are used as fallbacks when specific options are not provided.
     * @example
     * ```ts
     * // Override default options globally
     * NineSliceSprite.defaultOptions.texture = Texture.from('defaultButton.png');
     * // Create sprite with default texture
     * const sprite = new NineSliceSprite({...});
     * // sprite will use 'defaultButton.png' as its texture
     *
     * // Reset to empty texture
     * NineSliceSprite.defaultOptions.texture = Texture.EMPTY;
     * ```
     * @type {NineSliceSpriteOptions}
     * @see {@link NineSliceSpriteOptions} For all available options
     * @see {@link Texture#defaultBorders} For texture-level border settings
     */
    _NineSliceSprite.defaultOptions = {
      /** @default Texture.EMPTY */
      texture: Texture.EMPTY
    };
    let NineSliceSprite = _NineSliceSprite;
    class NineSlicePlane extends NineSliceSprite {
      constructor(...args) {
        let options = args[0];
        if (options instanceof Texture) {
          deprecation(v8_0_0, "NineSlicePlane now uses the options object {texture, leftWidth, rightWidth, topHeight, bottomHeight}");
          options = {
            texture: options,
            leftWidth: args[1],
            topHeight: args[2],
            rightWidth: args[3],
            bottomHeight: args[4]
          };
        }
        deprecation(v8_0_0, "NineSlicePlane is deprecated. Use NineSliceSprite instead.");
        super(options);
      }
    }

    "use strict";
    function bitmapTextSplit(options) {
      const { text, style, chars: existingChars } = options;
      const textStyle = style;
      const font = BitmapFontManager.getFont(text, textStyle);
      const segments = CanvasTextMetrics.graphemeSegmenter(text);
      const layout = getBitmapTextLayout(segments, textStyle, font, true);
      const scale = layout.scale;
      const chars = [];
      const words = [];
      const lines = [];
      const lineHeight = style.lineHeight ? style.lineHeight : font.lineHeight * scale;
      let yOffset = 0;
      for (const line of layout.lines) {
        if (line.chars.length === 0)
          continue;
        const lineContainer = new Container({ label: "line" });
        lineContainer.y = yOffset;
        lines.push(lineContainer);
        let currentWordContainer = new Container({ label: "word" });
        let currentWordStartIndex = 0;
        for (let i = 0; i < line.chars.length; i++) {
          const char = line.chars[i];
          if (!char)
            continue;
          const charData = font.chars[char];
          if (!charData)
            continue;
          const isSpace = char === " ";
          const isLastChar = i === line.chars.length - 1;
          let charInstance;
          if (existingChars.length > 0) {
            charInstance = existingChars.shift();
            charInstance.text = char;
            charInstance.style = textStyle;
            charInstance.label = `char-${char}`;
            charInstance.x = line.charPositions[i] * scale - line.charPositions[currentWordStartIndex] * scale;
          } else {
            charInstance = new BitmapText({
              text: char,
              style: textStyle,
              label: `char-${char}`,
              x: line.charPositions[i] * scale - line.charPositions[currentWordStartIndex] * scale
            });
          }
          if (!isSpace) {
            chars.push(charInstance);
            currentWordContainer.addChild(charInstance);
          }
          if (isSpace || isLastChar) {
            if (currentWordContainer.children.length > 0) {
              currentWordContainer.x = line.charPositions[currentWordStartIndex] * scale;
              words.push(currentWordContainer);
              lineContainer.addChild(currentWordContainer);
              currentWordContainer = new Container({ label: "word" });
              currentWordStartIndex = i + 1;
            }
          }
        }
        yOffset += lineHeight;
      }
      return { chars, lines, words };
    }

    "use strict";
    var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
    var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
    var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
    var __objRest = (source, exclude) => {
      var target = {};
      for (var prop in source)
        if (__hasOwnProp$3.call(source, prop) && exclude.indexOf(prop) < 0)
          target[prop] = source[prop];
      if (source != null && __getOwnPropSymbols$3)
        for (var prop of __getOwnPropSymbols$3(source)) {
          if (exclude.indexOf(prop) < 0 && __propIsEnum$3.call(source, prop))
            target[prop] = source[prop];
        }
      return target;
    };
    class AbstractSplitText extends Container {
      constructor(config) {
        const _a = config, {
          text,
          style,
          autoSplit,
          lineAnchor,
          wordAnchor,
          charAnchor
        } = _a, options = __objRest(_a, [
          "text",
          "style",
          "autoSplit",
          "lineAnchor",
          "wordAnchor",
          "charAnchor"
        ]);
        super(options);
        this._dirty = false;
        this._canReuseChars = false;
        this.chars = [];
        this.words = [];
        this.lines = [];
        this._originalText = text;
        this._autoSplit = autoSplit;
        this._lineAnchor = lineAnchor;
        this._wordAnchor = wordAnchor;
        this._charAnchor = charAnchor;
        this.style = style;
      }
      /**
       * Splits the text into lines, words, and characters.
       * Call this manually when autoSplit is false.
       * @example Manual Splitting
       * ```ts
       * const text = new SplitText({
       *   text: 'Manual Update',
       *   autoSplit: false
       * });
       *
       * text.text = 'New Content';
       * text.style = { fontSize: 32 };
       * text.split(); // Apply changes
       * ```
       */
      split() {
        const res = this.splitFn();
        this.chars = res.chars;
        this.words = res.words;
        this.lines = res.lines;
        this.addChild(...this.lines);
        this.charAnchor = this._charAnchor;
        this.wordAnchor = this._wordAnchor;
        this.lineAnchor = this._lineAnchor;
        this._dirty = false;
        this._canReuseChars = true;
      }
      get text() {
        return this._originalText;
      }
      /**
       * Gets or sets the text content.
       * Setting new text triggers splitting if autoSplit is true.
       * > [!NOTE] Setting this frequently can have a performance impact, especially with large texts and canvas text.
       * @example Dynamic Text Updates
       * ```ts
       * const text = new SplitText({
       *   text: 'Original',
       *   autoSplit: true
       * });
       *
       * // Auto-splits on change
       * text.text = 'Updated Content';
       *
       * // Manual update
       * text.autoSplit = false;
       * text.text = 'Manual Update';
       * text.split();
       * ```
       */
      set text(value) {
        this._originalText = value;
        this.lines.forEach((line) => line.destroy({ children: true }));
        this.lines.length = 0;
        this.words.length = 0;
        this.chars.length = 0;
        this._canReuseChars = false;
        this.onTextUpdate();
      }
      _setOrigin(value, elements, property) {
        let originPoint;
        if (typeof value === "number") {
          originPoint = { x: value, y: value };
        } else {
          originPoint = { x: value.x, y: value.y };
        }
        elements.forEach((element) => {
          const localBounds = element.getLocalBounds();
          const originX = localBounds.minX + localBounds.width * originPoint.x;
          const originY = localBounds.minY + localBounds.height * originPoint.y;
          element.origin.set(originX, originY);
        });
        this[property] = value;
      }
      /**
       * Gets or sets the transform anchor for line segments.
       * The anchor point determines the center of rotation and scaling for each line.
       * @example Setting Line Anchors
       * ```ts
       * // Center rotation/scaling
       * text.lineAnchor = 0.5;
       *
       * // Rotate/scale from top-right corner
       * text.lineAnchor = { x: 1, y: 0 };
       *
       * // Custom anchor point
       * text.lineAnchor = {
       *   x: 0.2, // 20% from left
       *   y: 0.8  // 80% from top
       * };
       * ```
       */
      get lineAnchor() {
        return this._lineAnchor;
      }
      set lineAnchor(value) {
        this._setOrigin(value, this.lines, "_lineAnchor");
      }
      /**
       * Gets or sets the transform anchor for word segments.
       * The anchor point determines the center of rotation and scaling for each word.
       * @example
       * ```ts
       * // Center each word
       * text.wordAnchor = 0.5;
       *
       * // Scale from bottom-left
       * text.wordAnchor = { x: 0, y: 1 };
       *
       * // Rotate around custom point
       * text.wordAnchor = {
       *   x: 0.75,  // 75% from left
       *   y: 0.5    // Middle vertically
       * };
       * ```
       */
      get wordAnchor() {
        return this._wordAnchor;
      }
      set wordAnchor(value) {
        this._setOrigin(value, this.words, "_wordAnchor");
      }
      /**
       * Gets or sets the transform anchor for character segments.
       * The anchor point determines the center of rotation and scaling for each character.
       * @example Setting Character Anchors
       * ```ts
       * // Center each character
       * text.charAnchor = 0.5;
       *
       * // Rotate from top-center
       * text.charAnchor = { x: 0.5, y: 0 };
       *
       * // Scale from bottom-right
       * text.charAnchor = { x: 1, y: 1 };
       * ```
       * @example Animation with Anchors
       * ```ts
       * // Rotate characters around their centers
       * text.charAnchor = 0.5;
       * text.chars.forEach((char, i) => {
       *   gsap.to(char, {
       *     rotation: Math.PI * 2,
       *     duration: 1,
       *     delay: i * 0.1,
       *     repeat: -1
       *   });
       * });
       * ```
       */
      get charAnchor() {
        return this._charAnchor;
      }
      set charAnchor(value) {
        this._setOrigin(value, this.chars, "_charAnchor");
      }
      get style() {
        return this._style;
      }
      /**
       * The style configuration for the text.
       * Can be a TextStyle instance or a configuration object.
       * @example
       * ```ts
       * const text = new Text({
       *     text: 'Styled Text',
       *     style: {
       *         fontSize: 24,
       *         fill: 0xff1010, // Red color
       *         fontFamily: 'Arial',
       *         align: 'center', // Center alignment
       *         stroke: { color: '#4a1850', width: 5 }, // Purple stroke
       *         dropShadow: {
       *             color: '#000000', // Black shadow
       *             blur: 4, // Shadow blur
       *             distance: 6 // Shadow distance
       *         }
       *     }
       * });
       * // Update style dynamically
       * text.style = {
       *     fontSize: 30, // Change font size
       *     fill: 0x00ff00, // Change color to green
       *     align: 'right', // Change alignment to right
       *     stroke: { color: '#000000', width: 2 }, // Add black stroke
       * }
       */
      set style(style) {
        style || (style = {});
        this._style = new TextStyle(style);
        this.words.forEach((word) => word.destroy());
        this.words.length = 0;
        this.lines.forEach((line) => line.destroy());
        this.lines.length = 0;
        this._canReuseChars = true;
        this.onTextUpdate();
      }
      onTextUpdate() {
        this._dirty = true;
        if (this._autoSplit) {
          this.split();
        }
      }
      /**
       * Destroys the SplitText instance and all its resources.
       * Cleans up all segment arrays, event listeners, and optionally the text style.
       * @param options - Destroy configuration options
       * @example
       * ```ts
       * // Clean up everything
       * text.destroy({ children: true, texture: true, style: true });
       *
       * // Remove from parent but keep style
       * text.destroy({ children: true, style: false });
       * ```
       */
      destroy(options) {
        super.destroy(options);
        this.chars = [];
        this.words = [];
        this.lines = [];
        if (typeof options === "boolean" ? options : options == null ? void 0 : options.style) {
          this._style.destroy(options);
        }
        this._style = null;
        this._originalText = "";
      }
    }

    "use strict";
    var __defProp$2 = Object.defineProperty;
    var __defProps$2 = Object.defineProperties;
    var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
    var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
    var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$2 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$2.call(b, prop))
          __defNormalProp$2(a, prop, b[prop]);
      if (__getOwnPropSymbols$2)
        for (var prop of __getOwnPropSymbols$2(b)) {
          if (__propIsEnum$2.call(b, prop))
            __defNormalProp$2(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
    const _SplitBitmapText = class _SplitBitmapText extends AbstractSplitText {
      constructor(config) {
        const completeOptions = __spreadValues$2(__spreadValues$2({}, _SplitBitmapText.defaultOptions), config);
        super(completeOptions);
      }
      /**
       * Creates a SplitBitmapText instance from an existing text object.
       * Useful for converting standard Text or BitmapText objects into segmented versions.
       * @param text - The source text object to convert
       * @param options - Additional splitting options
       * @returns A new SplitBitmapText instance
       * @example
       * ```ts
       * const bitmapText = new BitmapText({
       *   text: 'Bitmap Text',
       *   style: { fontFamily: 'Arial' }
       * });
       *
       * const segmented = SplitBitmapText.from(bitmapText);
       *
       * // with additional options
       * const segmentedWithOptions = SplitBitmapText.from(bitmapText, {
       *   autoSplit: false,
       *   lineAnchor: 0.5,
       *   wordAnchor: { x: 0, y: 0.5 },
       * })
       * ```
       */
      static from(text, options) {
        const completeOptions = __spreadProps$2(__spreadValues$2(__spreadValues$2({}, _SplitBitmapText.defaultOptions), options), {
          text: text.text,
          style: new TextStyle(text.style)
        });
        return new _SplitBitmapText(__spreadValues$2({}, completeOptions));
      }
      splitFn() {
        return bitmapTextSplit({
          text: this._originalText,
          style: this._style,
          chars: this._canReuseChars ? this.chars : []
        });
      }
    };
    /**
     * Default configuration options for SplitBitmapText instances.
     * @example
     * ```ts
     * // Override defaults globally
     * SplitBitmapText.defaultOptions = {
     *   autoSplit: false,
     *   lineAnchor: 0.5,  // Center alignment
     *   wordAnchor: { x: 0, y: 0.5 },  // Left-center
     *   charAnchor: { x: 0.5, y: 1 }   // Bottom-center
     * };
     * ```
     */
    _SplitBitmapText.defaultOptions = {
      autoSplit: true,
      // Auto-update on text/style changes
      lineAnchor: 0,
      // Top-left alignment
      wordAnchor: 0,
      // Top-left alignment
      charAnchor: 0
      // Top-left alignment
    };
    let SplitBitmapText = _SplitBitmapText;

    "use strict";
    function getAlignmentOffset(alignment, lineWidth, largestLine) {
      switch (alignment) {
        case "center":
          return (largestLine - lineWidth) / 2;
        case "right":
          return largestLine - lineWidth;
        case "left":
        default:
          return 0;
      }
    }
    function isNewlineCharacter(char) {
      return char === "\r" || char === "\n" || char === "\r\n";
    }
    function groupTextSegments(segments, measuredText, textStyle) {
      const groupedSegments = [];
      let currentLine = measuredText.lines[0];
      let matchedLine = "";
      let chars = [];
      let lineCount = 0;
      textStyle.wordWrap = false;
      segments.forEach((segment) => {
        const isWhitespace = /^\s*$/.test(segment);
        const isNewline = isNewlineCharacter(segment);
        const isSpaceAtStart = matchedLine.length === 0 && isWhitespace;
        if (isWhitespace && !isNewline && isSpaceAtStart) {
          return;
        }
        if (!isNewline)
          matchedLine += segment;
        const metric = CanvasTextMetrics.measureText(segment, textStyle);
        chars.push({ char: segment, metric });
        if (matchedLine.length >= currentLine.length) {
          groupedSegments.push({
            line: matchedLine,
            chars,
            width: chars.reduce((acc, seg) => acc + seg.metric.width, 0)
          });
          chars = [];
          matchedLine = "";
          lineCount++;
          currentLine = measuredText.lines[lineCount];
        }
      });
      return groupedSegments;
    }
    function canvasTextSplit(options) {
      var _a, _b;
      const { text, style, chars: existingChars } = options;
      const textStyle = style;
      const measuredText = CanvasTextMetrics.measureText(text, textStyle);
      const segments = CanvasTextMetrics.graphemeSegmenter(text);
      const groupedSegments = groupTextSegments(segments, measuredText, textStyle.clone());
      const alignment = textStyle.align;
      const largestLine = measuredText.lineWidths.reduce((max, line) => Math.max(max, line), 0);
      const chars = [];
      const lineContainers = [];
      const wordContainers = [];
      let yOffset = 0;
      const strokeWidth = ((_a = textStyle.stroke) == null ? void 0 : _a.width) || 0;
      const dropShadowDistance = ((_b = textStyle.dropShadow) == null ? void 0 : _b.distance) || 0;
      groupedSegments.forEach((group, i) => {
        const lineContainer = new Container({ label: `line-${i}` });
        lineContainer.y = yOffset;
        lineContainers.push(lineContainer);
        const lineWidth = measuredText.lineWidths[i];
        let xOffset = getAlignmentOffset(alignment, lineWidth, largestLine);
        let currentWordContainer = new Container({ label: "word" });
        currentWordContainer.x = xOffset;
        group.chars.forEach((segment, i2) => {
          if (segment.metric.width === 0) {
            return;
          }
          if (isNewlineCharacter(segment.char)) {
            xOffset += segment.metric.width - strokeWidth;
            return;
          }
          if (segment.char === " ") {
            if (currentWordContainer.children.length > 0) {
              wordContainers.push(currentWordContainer);
              lineContainer.addChild(currentWordContainer);
            }
            xOffset += segment.metric.width + textStyle.letterSpacing - strokeWidth;
            currentWordContainer = new Container({ label: "word" });
            currentWordContainer.x = xOffset;
          } else {
            let char;
            if (existingChars.length > 0) {
              char = existingChars.shift();
              char.text = segment.char;
              char.style = textStyle;
              char.setFromMatrix(Matrix.IDENTITY);
              char.x = xOffset - currentWordContainer.x - dropShadowDistance * i2;
            } else {
              char = new Text({
                text: segment.char,
                style: textStyle,
                x: xOffset - currentWordContainer.x - dropShadowDistance * i2
              });
            }
            chars.push(char);
            currentWordContainer.addChild(char);
            xOffset += segment.metric.width + textStyle.letterSpacing - strokeWidth;
          }
        });
        if (currentWordContainer.children.length > 0) {
          wordContainers.push(currentWordContainer);
          lineContainer.addChild(currentWordContainer);
        }
        yOffset += measuredText.lineHeight;
      });
      return { chars, lines: lineContainers, words: wordContainers };
    }

    "use strict";
    var __defProp$1 = Object.defineProperty;
    var __defProps$1 = Object.defineProperties;
    var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
    var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
    var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
    var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues$1 = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp$1.call(b, prop))
          __defNormalProp$1(a, prop, b[prop]);
      if (__getOwnPropSymbols$1)
        for (var prop of __getOwnPropSymbols$1(b)) {
          if (__propIsEnum$1.call(b, prop))
            __defNormalProp$1(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
    const _SplitText = class _SplitText extends AbstractSplitText {
      constructor(config) {
        const completeOptions = __spreadValues$1(__spreadValues$1({}, _SplitText.defaultOptions), config);
        super(completeOptions);
      }
      /**
       * Creates a SplitText instance from an existing text object.
       * Useful for converting standard Text or Text objects into segmented versions.
       * @param text - The source text object to convert
       * @param options - Additional splitting options
       * @returns A new SplitText instance
       * @example
       * ```ts
       * const text = new Text({
       *   text: 'Bitmap Text',
       *   style: { fontFamily: 'Arial' }
       * });
       *
       * const segmented = SplitText.from(text);
       *
       * // with additional options
       * const segmentedWithOptions = SplitText.from(text, {
       *   autoSplit: false,
       *   lineAnchor: 0.5,
       *   wordAnchor: { x: 0, y: 0.5 },
       * })
       * ```
       */
      static from(text, options) {
        const completeOptions = __spreadProps$1(__spreadValues$1(__spreadValues$1({}, _SplitText.defaultOptions), options), {
          text: text.text,
          style: new TextStyle(text.style)
        });
        return new _SplitText(__spreadValues$1({}, completeOptions));
      }
      splitFn() {
        return canvasTextSplit({
          text: this._originalText,
          style: this._style,
          chars: this._canReuseChars ? this.chars : []
        });
      }
    };
    /**
     * Default configuration options for SplitText instances.
     * @example
     * ```ts
     * // Override defaults globally
     * SplitText.defaultOptions = {
     *   autoSplit: false,
     *   lineAnchor: 0.5,  // Center alignment
     *   wordAnchor: { x: 0, y: 0.5 },  // Left-center
     *   charAnchor: { x: 0.5, y: 1 }   // Bottom-center
     * };
     * ```
     */
    _SplitText.defaultOptions = {
      autoSplit: true,
      // Auto-update on text/style changes
      lineAnchor: 0,
      // Top-left alignment
      wordAnchor: 0,
      // Top-left alignment
      charAnchor: 0
      // Top-left alignment
    };
    let SplitText = _SplitText;

    "use strict";

    "use strict";
    const valuesToIterateForKeys = [
      "align",
      "breakWords",
      "cssOverrides",
      "fontVariant",
      "fontWeight",
      "leading",
      "letterSpacing",
      "lineHeight",
      "padding",
      "textBaseline",
      "trim",
      "whiteSpace",
      "wordWrap",
      "wordWrapWidth",
      "fontFamily",
      "fontStyle",
      "fontSize"
    ];
    function generateTextStyleKey(style) {
      const key = [];
      let index = 0;
      for (let i = 0; i < valuesToIterateForKeys.length; i++) {
        const prop = `_${valuesToIterateForKeys[i]}`;
        key[index++] = style[prop];
      }
      index = addFillStyleKey(style._fill, key, index);
      index = addStokeStyleKey(style._stroke, key, index);
      index = addDropShadowKey(style.dropShadow, key, index);
      index = addFiltersKey(style.filters, key, index);
      return key.join("-");
    }
    function addFiltersKey(filters, key, index) {
      if (!filters)
        return index;
      for (const filter of filters) {
        key[index++] = filter.uid;
      }
      return index;
    }
    function addFillStyleKey(fillStyle, key, index) {
      var _a;
      if (!fillStyle)
        return index;
      key[index++] = fillStyle.color;
      key[index++] = fillStyle.alpha;
      key[index++] = (_a = fillStyle.fill) == null ? void 0 : _a.styleKey;
      return index;
    }
    function addStokeStyleKey(strokeStyle, key, index) {
      if (!strokeStyle)
        return index;
      index = addFillStyleKey(strokeStyle, key, index);
      key[index++] = strokeStyle.width;
      key[index++] = strokeStyle.alignment;
      key[index++] = strokeStyle.cap;
      key[index++] = strokeStyle.join;
      key[index++] = strokeStyle.miterLimit;
      return index;
    }
    function addDropShadowKey(dropShadow, key, index) {
      if (!dropShadow)
        return index;
      key[index++] = dropShadow.alpha;
      key[index++] = dropShadow.angle;
      key[index++] = dropShadow.blur;
      key[index++] = dropShadow.distance;
      key[index++] = Color.shared.setValue(dropShadow.color).toNumber();
      return index;
    }

    "use strict";

    "use strict";

    "use strict";

    var appleIphone = /iPhone/i;
    var appleIpod = /iPod/i;
    var appleTablet = /iPad/i;
    var appleUniversal = /\biOS-universal(?:.+)Mac\b/i;
    var androidPhone = /\bAndroid(?:.+)Mobile\b/i;
    var androidTablet = /Android/i;
    var amazonPhone = /(?:SD4930UR|\bSilk(?:.+)Mobile\b)/i;
    var amazonTablet = /Silk/i;
    var windowsPhone = /Windows Phone/i;
    var windowsTablet = /\bWindows(?:.+)ARM\b/i;
    var otherBlackBerry = /BlackBerry/i;
    var otherBlackBerry10 = /BB10/i;
    var otherOpera = /Opera Mini/i;
    var otherChrome = /\b(CriOS|Chrome)(?:.+)Mobile/i;
    var otherFirefox = /Mobile(?:.+)Firefox\b/i;
    var isAppleTabletOnIos13 = function (navigator) {
        return (typeof navigator !== 'undefined' &&
            navigator.platform === 'MacIntel' &&
            typeof navigator.maxTouchPoints === 'number' &&
            navigator.maxTouchPoints > 1 &&
            typeof MSStream === 'undefined');
    };
    function createMatch(userAgent) {
        return function (regex) { return regex.test(userAgent); };
    }
    function isMobile$1(param) {
        var nav = {
            userAgent: '',
            platform: '',
            maxTouchPoints: 0
        };
        if (!param && typeof navigator !== 'undefined') {
            nav = {
                userAgent: navigator.userAgent,
                platform: navigator.platform,
                maxTouchPoints: navigator.maxTouchPoints || 0
            };
        }
        else if (typeof param === 'string') {
            nav.userAgent = param;
        }
        else if (param && param.userAgent) {
            nav = {
                userAgent: param.userAgent,
                platform: param.platform,
                maxTouchPoints: param.maxTouchPoints || 0
            };
        }
        var userAgent = nav.userAgent;
        var tmp = userAgent.split('[FBAN');
        if (typeof tmp[1] !== 'undefined') {
            userAgent = tmp[0];
        }
        tmp = userAgent.split('Twitter');
        if (typeof tmp[1] !== 'undefined') {
            userAgent = tmp[0];
        }
        var match = createMatch(userAgent);
        var result = {
            apple: {
                phone: match(appleIphone) && !match(windowsPhone),
                ipod: match(appleIpod),
                tablet: !match(appleIphone) &&
                    (match(appleTablet) || isAppleTabletOnIos13(nav)) &&
                    !match(windowsPhone),
                universal: match(appleUniversal),
                device: (match(appleIphone) ||
                    match(appleIpod) ||
                    match(appleTablet) ||
                    match(appleUniversal) ||
                    isAppleTabletOnIos13(nav)) &&
                    !match(windowsPhone)
            },
            amazon: {
                phone: match(amazonPhone),
                tablet: !match(amazonPhone) && match(amazonTablet),
                device: match(amazonPhone) || match(amazonTablet)
            },
            android: {
                phone: (!match(windowsPhone) && match(amazonPhone)) ||
                    (!match(windowsPhone) && match(androidPhone)),
                tablet: !match(windowsPhone) &&
                    !match(amazonPhone) &&
                    !match(androidPhone) &&
                    (match(amazonTablet) || match(androidTablet)),
                device: (!match(windowsPhone) &&
                    (match(amazonPhone) ||
                        match(amazonTablet) ||
                        match(androidPhone) ||
                        match(androidTablet))) ||
                    match(/\bokhttp\b/i)
            },
            windows: {
                phone: match(windowsPhone),
                tablet: match(windowsTablet),
                device: match(windowsPhone) || match(windowsTablet)
            },
            other: {
                blackberry: match(otherBlackBerry),
                blackberry10: match(otherBlackBerry10),
                opera: match(otherOpera),
                firefox: match(otherFirefox),
                chrome: match(otherChrome),
                device: match(otherBlackBerry) ||
                    match(otherBlackBerry10) ||
                    match(otherOpera) ||
                    match(otherFirefox) ||
                    match(otherChrome)
            },
            any: false,
            phone: false,
            tablet: false
        };
        result.any =
            result.apple.device ||
                result.android.device ||
                result.windows.device ||
                result.other.device;
        result.phone =
            result.apple.phone || result.android.phone || result.windows.phone;
        result.tablet =
            result.apple.tablet || result.android.tablet || result.windows.tablet;
        return result;
    }

    "use strict";
    var _a;
    const isMobileCall = (_a = isMobile$1.default) != null ? _a : isMobile$1;
    const isMobile = isMobileCall(globalThis.navigator);

    "use strict";
    async function logDebugTexture(texture, renderer, size = 200) {
      const base64 = await renderer.extract.base64(texture);
      await renderer.encoder.commandFinished;
      const width = size;
      console.log(`logging texture ${texture.source.width}px ${texture.source.height}px`);
      const style = [
        "font-size: 1px;",
        `padding: ${width}px ${300}px;`,
        `background: url(${base64}) no-repeat;`,
        "background-size: contain;"
      ].join(" ");
      console.log("%c ", style);
    }

    "use strict";
    var __defProp = Object.defineProperty;
    var __defProps = Object.defineProperties;
    var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols = Object.getOwnPropertySymbols;
    var __hasOwnProp = Object.prototype.hasOwnProperty;
    var __propIsEnum = Object.prototype.propertyIsEnumerable;
    var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
    var __spreadValues = (a, b) => {
      for (var prop in b || (b = {}))
        if (__hasOwnProp.call(b, prop))
          __defNormalProp(a, prop, b[prop]);
      if (__getOwnPropSymbols)
        for (var prop of __getOwnPropSymbols(b)) {
          if (__propIsEnum.call(b, prop))
            __defNormalProp(a, prop, b[prop]);
        }
      return a;
    };
    var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
    const colors = [
      "#000080",
      // Navy Blue
      "#228B22",
      // Forest Green
      "#8B0000",
      // Dark Red
      "#4169E1",
      // Royal Blue
      "#008080",
      // Teal
      "#800000",
      // Maroon
      "#9400D3",
      // Dark Violet
      "#FF8C00",
      // Dark Orange
      "#556B2F",
      // Olive Green
      "#8B008B"
      // Dark Magenta
    ];
    let colorTick = 0;
    function logScene(container, depth = 0, data = { color: "#000000" }) {
      if (container.renderGroup) {
        data.color = colors[colorTick++];
      }
      let spaces = "";
      for (let i = 0; i < depth; i++) {
        spaces += "    ";
      }
      let label = container.label;
      if (!label && container instanceof Sprite) {
        label = `sprite:${container.texture.label}`;
      }
      let output = `%c ${spaces}|- ${label} (worldX:${container.worldTransform.tx}, relativeRenderX:${container.relativeGroupTransform.tx}, renderX:${container.groupTransform.tx}, localX:${container.x})`;
      if (container.renderGroup) {
        output += " (RenderGroup)";
      }
      if (container.filters) {
        output += "(*filters)";
      }
      console.log(output, `color:${data.color}; font-weight:bold;`);
      depth++;
      for (let i = 0; i < container.children.length; i++) {
        const child = container.children[i];
        logScene(child, depth, __spreadValues({}, data));
      }
    }
    function logRenderGroupScene(renderGroup, depth = 0, data = { index: 0, color: "#000000" }) {
      let spaces = "";
      for (let i = 0; i < depth; i++) {
        spaces += "    ";
      }
      const output = `%c ${spaces}- ${data.index}: ${renderGroup.root.label} worldX:${renderGroup.worldTransform.tx}`;
      console.log(output, `color:${data.color}; font-weight:bold;`);
      depth++;
      for (let i = 0; i < renderGroup.renderGroupChildren.length; i++) {
        const child = renderGroup.renderGroupChildren[i];
        logRenderGroupScene(child, depth, __spreadProps(__spreadValues({}, data), { index: i }));
      }
    }

    "use strict";

    "use strict";

    "use strict";
    DOMAdapter.set(WebWorkerAdapter);

    exports.AbstractBitmapFont = AbstractBitmapFont;
    exports.AbstractRenderer = AbstractRenderer;
    exports.AbstractSplitText = AbstractSplitText;
    exports.AbstractText = AbstractText;
    exports.AlphaFilter = AlphaFilter;
    exports.AlphaMask = AlphaMask;
    exports.AlphaMaskPipe = AlphaMaskPipe;
    exports.AnimatedSprite = AnimatedSprite;
    exports.Application = Application;
    exports.ApplicationInitHook = ApplicationInitHook;
    exports.Assets = Assets;
    exports.AssetsClass = AssetsClass;
    exports.BLEND_TO_NPM = BLEND_TO_NPM;
    exports.BUFFER_TYPE = BUFFER_TYPE;
    exports.BackgroundLoader = BackgroundLoader;
    exports.BackgroundSystem = BackgroundSystem;
    exports.Batch = Batch;
    exports.BatchGeometry = BatchGeometry;
    exports.BatchTextureArray = BatchTextureArray;
    exports.BatchableGraphics = BatchableGraphics;
    exports.BatchableHTMLText = BatchableHTMLText;
    exports.BatchableMesh = BatchableMesh;
    exports.BatchableSprite = BatchableSprite;
    exports.BatchableText = BatchableText;
    exports.Batcher = Batcher;
    exports.BatcherPipe = BatcherPipe;
    exports.BigPool = BigPool;
    exports.BindGroup = BindGroup;
    exports.BindGroupSystem = BindGroupSystem;
    exports.BitmapFont = BitmapFont;
    exports.BitmapFontManager = BitmapFontManager;
    exports.BitmapText = BitmapText;
    exports.BitmapTextGraphics = BitmapTextGraphics;
    exports.BitmapTextPipe = BitmapTextPipe;
    exports.BlendModeFilter = BlendModeFilter;
    exports.BlendModePipe = BlendModePipe;
    exports.BlurFilter = BlurFilter;
    exports.BlurFilterPass = BlurFilterPass;
    exports.Bounds = Bounds;
    exports.Buffer = Buffer;
    exports.BufferImageSource = BufferImageSource;
    exports.BufferResource = BufferResource;
    exports.BufferUsage = BufferUsage;
    exports.CLEAR = CLEAR;
    exports.Cache = Cache;
    exports.CanvasPool = CanvasPool;
    exports.CanvasPoolClass = CanvasPoolClass;
    exports.CanvasSource = CanvasSource;
    exports.CanvasTextGenerator = CanvasTextGenerator;
    exports.CanvasTextMetrics = CanvasTextMetrics;
    exports.CanvasTextPipe = CanvasTextPipe;
    exports.CanvasTextSystem = CanvasTextSystem;
    exports.Circle = Circle;
    exports.Color = Color;
    exports.ColorMask = ColorMask;
    exports.ColorMaskPipe = ColorMaskPipe;
    exports.ColorMatrixFilter = ColorMatrixFilter;
    exports.CompressedSource = CompressedSource;
    exports.Container = Container;
    exports.Culler = Culler;
    exports.CullerPlugin = CullerPlugin;
    exports.CustomRenderPipe = CustomRenderPipe;
    exports.D3D10_RESOURCE_DIMENSION = D3D10_RESOURCE_DIMENSION;
    exports.D3DFMT = D3DFMT;
    exports.DATA_URI = DATA_URI;
    exports.DDS = DDS;
    exports.DEG_TO_RAD = DEG_TO_RAD;
    exports.DEPRECATED_SCALE_MODES = DEPRECATED_SCALE_MODES;
    exports.DEPRECATED_WRAP_MODES = DEPRECATED_WRAP_MODES;
    exports.DOMAdapter = DOMAdapter;
    exports.DRAW_MODES = DRAW_MODES;
    exports.DXGI_FORMAT = DXGI_FORMAT;
    exports.DXGI_TO_TEXTURE_FORMAT = DXGI_TO_TEXTURE_FORMAT;
    exports.DefaultBatcher = DefaultBatcher;
    exports.DefaultShader = DefaultShader;
    exports.DisplacementFilter = DisplacementFilter;
    exports.DynamicBitmapFont = DynamicBitmapFont;
    exports.Ellipse = Ellipse;
    exports.EventEmitter = EventEmitter;
    exports.ExtensionType = ExtensionType;
    exports.ExtractSystem = ExtractSystem;
    exports.FOURCC_TO_TEXTURE_FORMAT = FOURCC_TO_TEXTURE_FORMAT;
    exports.FillGradient = FillGradient;
    exports.FillPattern = FillPattern;
    exports.Filter = Filter;
    exports.FilterEffect = FilterEffect;
    exports.FilterPipe = FilterPipe;
    exports.FilterSystem = FilterSystem;
    exports.FontStylePromiseCache = FontStylePromiseCache;
    exports.GAUSSIAN_VALUES = GAUSSIAN_VALUES;
    exports.GCManagedHash = GCManagedHash;
    exports.GCSystem = GCSystem;
    exports.GL_FORMATS = GL_FORMATS;
    exports.GL_INTERNAL_FORMAT = GL_INTERNAL_FORMAT;
    exports.GL_TARGETS = GL_TARGETS;
    exports.GL_TYPES = GL_TYPES;
    exports.GL_WRAP_MODES = GL_WRAP_MODES;
    exports.GPUTextureGpuData = GPUTextureGpuData;
    exports.GenerateTextureSystem = GenerateTextureSystem;
    exports.Geometry = Geometry;
    exports.GlBackBufferSystem = GlBackBufferSystem;
    exports.GlBatchAdaptor = GlBatchAdaptor;
    exports.GlBuffer = GlBuffer;
    exports.GlBufferSystem = GlBufferSystem;
    exports.GlColorMaskSystem = GlColorMaskSystem;
    exports.GlContextSystem = GlContextSystem;
    exports.GlEncoderSystem = GlEncoderSystem;
    exports.GlGeometryGpuData = GlGeometryGpuData;
    exports.GlGeometrySystem = GlGeometrySystem;
    exports.GlGraphicsAdaptor = GlGraphicsAdaptor;
    exports.GlLimitsSystem = GlLimitsSystem;
    exports.GlMeshAdaptor = GlMeshAdaptor;
    exports.GlParticleContainerAdaptor = GlParticleContainerAdaptor;
    exports.GlParticleContainerPipe = GlParticleContainerPipe;
    exports.GlProgram = GlProgram;
    exports.GlProgramData = GlProgramData;
    exports.GlRenderTarget = GlRenderTarget;
    exports.GlRenderTargetAdaptor = GlRenderTargetAdaptor;
    exports.GlRenderTargetSystem = GlRenderTargetSystem;
    exports.GlShaderSystem = GlShaderSystem;
    exports.GlStateSystem = GlStateSystem;
    exports.GlStencilSystem = GlStencilSystem;
    exports.GlTexture = GlTexture;
    exports.GlTextureSystem = GlTextureSystem;
    exports.GlUboSystem = GlUboSystem;
    exports.GlUniformGroupSystem = GlUniformGroupSystem;
    exports.GlobalResourceRegistry = GlobalResourceRegistry;
    exports.GlobalUniformSystem = GlobalUniformSystem;
    exports.GpuBatchAdaptor = GpuBatchAdaptor;
    exports.GpuBlendModesToPixi = GpuBlendModesToPixi;
    exports.GpuBufferData = GpuBufferData;
    exports.GpuBufferSystem = GpuBufferSystem;
    exports.GpuColorMaskSystem = GpuColorMaskSystem;
    exports.GpuDeviceSystem = GpuDeviceSystem;
    exports.GpuEncoderSystem = GpuEncoderSystem;
    exports.GpuGraphicsAdaptor = GpuGraphicsAdaptor;
    exports.GpuGraphicsContext = GpuGraphicsContext;
    exports.GpuLimitsSystem = GpuLimitsSystem;
    exports.GpuMeshAdapter = GpuMeshAdapter;
    exports.GpuMipmapGenerator = GpuMipmapGenerator;
    exports.GpuParticleContainerAdaptor = GpuParticleContainerAdaptor;
    exports.GpuParticleContainerPipe = GpuParticleContainerPipe;
    exports.GpuProgram = GpuProgram;
    exports.GpuRenderTarget = GpuRenderTarget;
    exports.GpuRenderTargetAdaptor = GpuRenderTargetAdaptor;
    exports.GpuRenderTargetSystem = GpuRenderTargetSystem;
    exports.GpuShaderSystem = GpuShaderSystem;
    exports.GpuStateSystem = GpuStateSystem;
    exports.GpuStencilModesToPixi = GpuStencilModesToPixi;
    exports.GpuStencilSystem = GpuStencilSystem;
    exports.GpuTextureSystem = GpuTextureSystem;
    exports.GpuUboSystem = GpuUboSystem;
    exports.GpuUniformBatchPipe = GpuUniformBatchPipe;
    exports.Graphics = Graphics;
    exports.GraphicsContext = GraphicsContext;
    exports.GraphicsContextRenderData = GraphicsContextRenderData;
    exports.GraphicsContextSystem = GraphicsContextSystem;
    exports.GraphicsGpuData = GraphicsGpuData;
    exports.GraphicsPath = GraphicsPath;
    exports.GraphicsPipe = GraphicsPipe;
    exports.HTMLText = HTMLText;
    exports.HTMLTextPipe = HTMLTextPipe;
    exports.HTMLTextRenderData = HTMLTextRenderData;
    exports.HTMLTextStyle = HTMLTextStyle;
    exports.HTMLTextSystem = HTMLTextSystem;
    exports.HelloSystem = HelloSystem;
    exports.IGLUniformData = IGLUniformData;
    exports.ImageSource = ImageSource;
    exports.InstructionSet = InstructionSet;
    exports.KTX = KTX;
    exports.Loader = Loader;
    exports.LoaderParserPriority = LoaderParserPriority;
    exports.MaskEffectManager = MaskEffectManager;
    exports.MaskEffectManagerClass = MaskEffectManagerClass;
    exports.MaskFilter = MaskFilter;
    exports.Matrix = Matrix;
    exports.Mesh = Mesh;
    exports.MeshGeometry = MeshGeometry;
    exports.MeshGpuData = MeshGpuData;
    exports.MeshPipe = MeshPipe;
    exports.MeshPlane = MeshPlane;
    exports.MeshRope = MeshRope;
    exports.MeshSimple = MeshSimple;
    exports.NOOP = NOOP;
    exports.NineSliceGeometry = NineSliceGeometry;
    exports.NineSlicePlane = NineSlicePlane;
    exports.NineSliceSprite = NineSliceSprite;
    exports.NineSliceSpriteGpuData = NineSliceSpriteGpuData;
    exports.NineSliceSpritePipe = NineSliceSpritePipe;
    exports.NoiseFilter = NoiseFilter;
    exports.ObservablePoint = ObservablePoint;
    exports.PI_2 = PI_2;
    exports.Particle = Particle;
    exports.ParticleBuffer = ParticleBuffer;
    exports.ParticleContainer = ParticleContainer;
    exports.ParticleContainerPipe = ParticleContainerPipe;
    exports.ParticleShader = ParticleShader;
    exports.PassthroughFilter = PassthroughFilter;
    exports.PerspectiveMesh = PerspectiveMesh;
    exports.PerspectivePlaneGeometry = PerspectivePlaneGeometry;
    exports.PipelineSystem = PipelineSystem;
    exports.PlaneGeometry = PlaneGeometry;
    exports.Point = Point;
    exports.Polygon = Polygon;
    exports.Pool = Pool;
    exports.PoolGroupClass = PoolGroupClass;
    exports.PrepareBase = PrepareBase;
    exports.PrepareQueue = PrepareQueue;
    exports.PrepareSystem = PrepareSystem;
    exports.PrepareUpload = PrepareUpload;
    exports.QuadGeometry = QuadGeometry;
    exports.RAD_TO_DEG = RAD_TO_DEG;
    exports.Rectangle = Rectangle;
    exports.RenderContainer = RenderContainer;
    exports.RenderGroup = RenderGroup;
    exports.RenderGroupPipe = RenderGroupPipe;
    exports.RenderGroupSystem = RenderGroupSystem;
    exports.RenderLayer = RenderLayer;
    exports.RenderTarget = RenderTarget;
    exports.RenderTargetSystem = RenderTargetSystem;
    exports.RenderTexture = RenderTexture;
    exports.RenderableGCSystem = RenderableGCSystem;
    exports.RendererInitHook = RendererInitHook;
    exports.RendererType = RendererType;
    exports.ResizePlugin = ResizePlugin;
    exports.Resolver = Resolver;
    exports.RopeGeometry = RopeGeometry;
    exports.RoundedRectangle = RoundedRectangle;
    exports.SCALE_MODES = SCALE_MODES;
    exports.STENCIL_MODES = STENCIL_MODES;
    exports.SVGParser = SVGParser;
    exports.SchedulerSystem = SchedulerSystem;
    exports.ScissorMask = ScissorMask;
    exports.SdfShader = SdfShader;
    exports.Shader = Shader;
    exports.ShaderStage = ShaderStage;
    exports.ShapePath = ShapePath;
    exports.SharedRenderPipes = SharedRenderPipes;
    exports.SharedSystems = SharedSystems;
    exports.SplitBitmapText = SplitBitmapText;
    exports.SplitText = SplitText;
    exports.Sprite = Sprite;
    exports.SpritePipe = SpritePipe;
    exports.Spritesheet = Spritesheet;
    exports.State = State;
    exports.StencilMask = StencilMask;
    exports.StencilMaskPipe = StencilMaskPipe;
    exports.SystemRunner = SystemRunner;
    exports.TEXTURE_FORMAT_BLOCK_SIZE = TEXTURE_FORMAT_BLOCK_SIZE;
    exports.Text = Text;
    exports.TextStyle = TextStyle;
    exports.Texture = Texture;
    exports.TextureGCSystem = TextureGCSystem;
    exports.TextureMatrix = TextureMatrix;
    exports.TexturePool = TexturePool;
    exports.TexturePoolClass = TexturePoolClass;
    exports.TextureSource = TextureSource;
    exports.TextureStyle = TextureStyle;
    exports.TextureUvs = TextureUvs;
    exports.Ticker = Ticker;
    exports.TickerListener = TickerListener;
    exports.TickerPlugin = TickerPlugin;
    exports.TilingSprite = TilingSprite;
    exports.TilingSpriteGpuData = TilingSpriteGpuData;
    exports.TilingSpritePipe = TilingSpritePipe;
    exports.TilingSpriteShader = TilingSpriteShader;
    exports.Transform = Transform;
    exports.Triangle = Triangle;
    exports.UNIFORM_TO_ARRAY_SETTERS = UNIFORM_TO_ARRAY_SETTERS;
    exports.UNIFORM_TO_SINGLE_SETTERS = UNIFORM_TO_SINGLE_SETTERS;
    exports.UNIFORM_TYPES_MAP = UNIFORM_TYPES_MAP;
    exports.UNIFORM_TYPES_VALUES = UNIFORM_TYPES_VALUES;
    exports.UPDATE_BLEND = UPDATE_BLEND;
    exports.UPDATE_COLOR = UPDATE_COLOR;
    exports.UPDATE_PRIORITY = UPDATE_PRIORITY;
    exports.UPDATE_TRANSFORM = UPDATE_TRANSFORM;
    exports.UPDATE_VISIBLE = UPDATE_VISIBLE;
    exports.UboBatch = UboBatch;
    exports.UboSystem = UboSystem;
    exports.UniformGroup = UniformGroup;
    exports.VERSION = VERSION;
    exports.VideoSource = VideoSource;
    exports.ViewContainer = ViewContainer;
    exports.ViewSystem = ViewSystem;
    exports.ViewableBuffer = ViewableBuffer;
    exports.WGSL_ALIGN_SIZE_DATA = WGSL_ALIGN_SIZE_DATA;
    exports.WGSL_TO_STD40_SIZE = WGSL_TO_STD40_SIZE;
    exports.WRAP_MODES = WRAP_MODES;
    exports.WebGLRenderer = WebGLRenderer;
    exports.WebGPURenderer = WebGPURenderer;
    exports.WebWorkerAdapter = WebWorkerAdapter;
    exports.WorkerManager = WorkerManager;
    exports.addBits = addBits;
    exports.addMaskBounds = addMaskBounds;
    exports.addMaskLocalBounds = addMaskLocalBounds;
    exports.addProgramDefines = addProgramDefines;
    exports.alphaFrag = fragment$4;
    exports.alphaWgsl = source$5;
    exports.appendSVGPath = appendSVGPath;
    exports.applyMatrix = applyMatrix;
    exports.applyProjectiveTransformationToPlane = applyProjectiveTransformationToPlane;
    exports.applyStyleParams = applyStyleParams;
    exports.assignWithIgnore = assignWithIgnore;
    exports.autoDetectEnvironment = autoDetectEnvironment;
    exports.autoDetectRenderer = autoDetectRenderer;
    exports.autoDetectSource = autoDetectSource;
    exports.basisTranscoderUrls = basisTranscoderUrls;
    exports.bgr2rgb = bgr2rgb;
    exports.bitmapFontCachePlugin = bitmapFontCachePlugin;
    exports.bitmapFontTextParser = bitmapFontTextParser;
    exports.bitmapFontXMLParser = bitmapFontXMLParser;
    exports.bitmapFontXMLStringParser = bitmapFontXMLStringParser;
    exports.bitmapTextSplit = bitmapTextSplit;
    exports.blendTemplateFrag = blendTemplateFrag;
    exports.blendTemplateVert = blendTemplateVert;
    exports.blendTemplateWgsl = blendTemplate;
    exports.blockDataMap = blockDataMap;
    exports.blurTemplateWgsl = source$4;
    exports.boundsPool = boundsPool;
    exports.buildAdaptiveBezier = buildAdaptiveBezier;
    exports.buildAdaptiveQuadratic = buildAdaptiveQuadratic;
    exports.buildArc = buildArc;
    exports.buildArcTo = buildArcTo;
    exports.buildArcToSvg = buildArcToSvg;
    exports.buildCircle = buildCircle;
    exports.buildContextBatches = buildContextBatches;
    exports.buildEllipse = buildEllipse;
    exports.buildGeometryFromPath = buildGeometryFromPath;
    exports.buildLine = buildLine;
    exports.buildPixelLine = buildPixelLine;
    exports.buildPolygon = buildPolygon;
    exports.buildRectangle = buildRectangle;
    exports.buildRoundedRectangle = buildRoundedRectangle;
    exports.buildSimpleUvs = buildSimpleUvs;
    exports.buildTriangle = buildTriangle;
    exports.buildUvs = buildUvs;
    exports.cacheAsTextureMixin = cacheAsTextureMixin;
    exports.cacheTextureArray = cacheTextureArray;
    exports.calculatePathArea = calculatePathArea;
    exports.calculateProjection = calculateProjection;
    exports.canvasTextSplit = canvasTextSplit;
    exports.checkChildrenDidChange = checkChildrenDidChange;
    exports.checkDataUrl = checkDataUrl;
    exports.checkExtension = checkExtension;
    exports.checkForNestedPattern = checkForNestedPattern;
    exports.checkMaxIfStatementsInShader = checkMaxIfStatementsInShader;
    exports.childrenHelperMixin = childrenHelperMixin;
    exports.cleanArray = cleanArray;
    exports.cleanHash = cleanHash;
    exports.clearList = clearList;
    exports.closePointEps = closePointEps;
    exports.collectAllRenderables = collectAllRenderables;
    exports.collectRenderablesMixin = collectRenderablesMixin;
    exports.color32BitToUniform = color32BitToUniform;
    exports.colorBit = colorBit;
    exports.colorBitGl = colorBitGl;
    exports.colorMatrixFilterFrag = fragment$3;
    exports.colorMatrixFilterWgsl = source$3;
    exports.colorToUniform = colorToUniform;
    exports.compareModeToGlCompare = compareModeToGlCompare;
    exports.compileHighShader = compileHighShader;
    exports.compileHighShaderGl = compileHighShaderGl;
    exports.compileHighShaderGlProgram = compileHighShaderGlProgram;
    exports.compileHighShaderGpuProgram = compileHighShaderGpuProgram;
    exports.compileHooks = compileHooks;
    exports.compileInputs = compileInputs;
    exports.compileOutputs = compileOutputs;
    exports.compileShader = compileShader;
    exports.compute2DProjection = compute2DProjection;
    exports.convertFormatIfRequired = convertFormatIfRequired;
    exports.convertToList = convertToList;
    exports.copySearchParams = copySearchParams;
    exports.createIdFromString = createIdFromString;
    exports.createIndicesForQuads = createIndicesForQuads;
    exports.createLevelBuffers = createLevelBuffers;
    exports.createLevelBuffersFromKTX = createLevelBuffersFromKTX;
    exports.createStringVariations = createStringVariations;
    exports.createTexture = createTexture;
    exports.createUboElementsSTD40 = createUboElementsSTD40;
    exports.createUboElementsWGSL = createUboElementsWGSL;
    exports.createUboSyncFunction = createUboSyncFunction;
    exports.createUboSyncFunctionSTD40 = createUboSyncFunctionSTD40;
    exports.createUboSyncFunctionWGSL = createUboSyncFunctionWGSL;
    exports.crossOrigin = crossOrigin;
    exports.cullingMixin = cullingMixin;
    exports.curveEps = curveEps;
    exports.defaultFilterVert = vertex$2;
    exports.defaultValue = defaultValue;
    exports.definedProps = definedProps;
    exports.deprecation = deprecation;
    exports.detectAvif = detectAvif;
    exports.detectBasis = detectBasis;
    exports.detectCompressed = detectCompressed;
    exports.detectDefaults = detectDefaults;
    exports.detectMp4 = detectMp4;
    exports.detectOgv = detectOgv;
    exports.detectVideoAlphaMode = detectVideoAlphaMode;
    exports.detectWebm = detectWebm;
    exports.detectWebp = detectWebp;
    exports.determineCrossOrigin = determineCrossOrigin;
    exports.displacementFrag = fragment$2;
    exports.displacementVert = vertex$1;
    exports.displacementWgsl = source$2;
    exports.earcut = earcut;
    exports.effectsMixin = effectsMixin;
    exports.ensureAttributes = ensureAttributes;
    exports.ensureIsBuffer = ensureIsBuffer;
    exports.ensurePrecision = ensurePrecision;
    exports.ensureTextOptions = ensureTextOptions;
    exports.executeInstructions = executeInstructions;
    exports.extensions = extensions;
    exports.extractAttributesFromGlProgram = extractAttributesFromGlProgram;
    exports.extractAttributesFromGpuProgram = extractAttributesFromGpuProgram;
    exports.extractFontFamilies = extractFontFamilies;
    exports.extractStructAndGroups = extractStructAndGroups;
    exports.extractSubpaths = extractSubpaths;
    exports.extractSvgUrlId = extractSvgUrlId;
    exports.fastCopy = fastCopy;
    exports.findMixin = findMixin;
    exports.fontStringFromTextStyle = fontStringFromTextStyle;
    exports.formatShader = formatShader;
    exports.fragmentGPUTemplate = fragmentGPUTemplate;
    exports.fragmentGlTemplate = fragmentGlTemplate;
    exports.generateArraySyncSTD40 = generateArraySyncSTD40;
    exports.generateArraySyncWGSL = generateArraySyncWGSL;
    exports.generateBlurFragSource = generateBlurFragSource;
    exports.generateBlurGlProgram = generateBlurGlProgram;
    exports.generateBlurProgram = generateBlurProgram;
    exports.generateBlurVertSource = generateBlurVertSource;
    exports.generateGPULayout = generateGPULayout;
    exports.generateGpuLayoutGroups = generateGpuLayoutGroups;
    exports.generateLayout = generateLayout;
    exports.generateLayoutHash = generateLayoutHash;
    exports.generateParticleUpdateFunction = generateParticleUpdateFunction;
    exports.generateProgram = generateProgram;
    exports.generateShaderSyncCode = generateShaderSyncCode;
    exports.generateTextStyleKey = generateTextStyleKey;
    exports.generateTextureBatchBit = generateTextureBatchBit;
    exports.generateTextureBatchBitGl = generateTextureBatchBitGl;
    exports.generateTextureMatrix = generateTextureMatrix;
    exports.generateUniformsSync = generateUniformsSync;
    exports.getAdjustedBlendModeBlend = getAdjustedBlendModeBlend;
    exports.getAttributeInfoFromFormat = getAttributeInfoFromFormat;
    exports.getBatchSamplersUniformGroup = getBatchSamplersUniformGroup;
    exports.getBitmapTextLayout = getBitmapTextLayout;
    exports.getCanvasBoundingBox = getCanvasBoundingBox;
    exports.getCanvasFillStyle = getCanvasFillStyle;
    exports.getCanvasTexture = getCanvasTexture;
    exports.getDefaultUniformValue = getDefaultUniformValue;
    exports.getFastGlobalBounds = getFastGlobalBounds;
    exports.getFastGlobalBoundsMixin = getFastGlobalBoundsMixin;
    exports.getFillInstructionData = getFillInstructionData;
    exports.getFontCss = getFontCss;
    exports.getFontFamilyName = getFontFamilyName;
    exports.getGeometryBounds = getGeometryBounds;
    exports.getGlTypeFromFormat = getGlTypeFromFormat;
    exports.getGlobalBounds = getGlobalBounds;
    exports.getGlobalMixin = getGlobalMixin;
    exports.getGlobalRenderableBounds = getGlobalRenderableBounds;
    exports.getLocalBounds = getLocalBounds;
    exports.getMaxFragmentPrecision = getMaxFragmentPrecision;
    exports.getMaxTexturesPerBatch = getMaxTexturesPerBatch;
    exports.getOrientationOfPoints = getOrientationOfPoints;
    exports.getPo2TextureFromSource = getPo2TextureFromSource;
    exports.getResolutionOfUrl = getResolutionOfUrl;
    exports.getSVGUrl = getSVGUrl;
    exports.getSupportedCompressedTextureFormats = getSupportedCompressedTextureFormats;
    exports.getSupportedGPUCompressedTextureFormats = getSupportedGPUCompressedTextureFormats;
    exports.getSupportedGlCompressedTextureFormats = getSupportedGlCompressedTextureFormats;
    exports.getSupportedTextureFormats = getSupportedTextureFormats;
    exports.getTemporaryCanvasFromImage = getTemporaryCanvasFromImage;
    exports.getTestContext = getTestContext;
    exports.getTextureBatchBindGroup = getTextureBatchBindGroup;
    exports.getTextureDefaultMatrix = getTextureDefaultMatrix;
    exports.getTextureFormatFromKTXTexture = getTextureFormatFromKTXTexture;
    exports.getUboData = getUboData;
    exports.getUniformData = getUniformData;
    exports.getUrlExtension = getUrlExtension;
    exports.glFormatToGPUFormat = glFormatToGPUFormat;
    exports.glUploadBufferImageResource = glUploadBufferImageResource;
    exports.glUploadCompressedTextureResource = glUploadCompressedTextureResource;
    exports.glUploadImageResource = glUploadImageResource;
    exports.glUploadVideoResource = glUploadVideoResource;
    exports.globalUniformsBit = globalUniformsBit;
    exports.globalUniformsBitGl = globalUniformsBitGl;
    exports.globalUniformsUBOBitGl = globalUniformsUBOBitGl;
    exports.gpuFormatToBasisTranscoderFormat = gpuFormatToBasisTranscoderFormat;
    exports.gpuFormatToKTXBasisTranscoderFormat = gpuFormatToKTXBasisTranscoderFormat;
    exports.gpuUploadBufferImageResource = gpuUploadBufferImageResource;
    exports.gpuUploadCompressedTextureResource = gpuUploadCompressedTextureResource;
    exports.gpuUploadImageResource = gpuUploadImageResource;
    exports.gpuUploadVideoResource = gpuUploadVideoResource;
    exports.groupD8 = groupD8;
    exports.hasCachedCanvasTexture = hasCachedCanvasTexture;
    exports.hslWgsl = hsl;
    exports.hslgl = hslgl;
    exports.hslgpu = hslgpu;
    exports.injectBits = injectBits;
    exports.insertVersion = insertVersion;
    exports.isMobile = isMobile;
    exports.isPow2 = isPow2;
    exports.isRenderingToScreen = isRenderingToScreen;
    exports.isSafari = isSafari;
    exports.isSingleItem = isSingleItem;
    exports.isWebGLSupported = isWebGLSupported;
    exports.isWebGPUSupported = isWebGPUSupported;
    exports.ktxTranscoderUrls = ktxTranscoderUrls;
    exports.loadBasis = loadBasis;
    exports.loadBasisOnWorker = loadBasisOnWorker;
    exports.loadBitmapFont = loadBitmapFont;
    exports.loadDDS = loadDDS;
    exports.loadEnvironmentExtensions = loadEnvironmentExtensions;
    exports.loadFontAsBase64 = loadFontAsBase64;
    exports.loadFontCSS = loadFontCSS;
    exports.loadImageBitmap = loadImageBitmap;
    exports.loadJson = loadJson;
    exports.loadKTX = loadKTX;
    exports.loadKTX2 = loadKTX2;
    exports.loadKTX2onWorker = loadKTX2onWorker;
    exports.loadSVGImage = loadSVGImage;
    exports.loadSvg = loadSvg;
    exports.loadTextures = loadTextures;
    exports.loadTxt = loadTxt;
    exports.loadVideoTextures = loadVideoTextures;
    exports.loadWebFont = loadWebFont;
    exports.localUniformBit = localUniformBit;
    exports.localUniformBitGl = localUniformBitGl;
    exports.localUniformBitGroup2 = localUniformBitGroup2;
    exports.localUniformMSDFBit = localUniformMSDFBit;
    exports.localUniformMSDFBitGl = localUniformMSDFBitGl;
    exports.log2 = log2;
    exports.logDebugTexture = logDebugTexture;
    exports.logProgramError = logProgramError;
    exports.logRenderGroupScene = logRenderGroupScene;
    exports.logScene = logScene;
    exports.mSDFBit = mSDFBit;
    exports.mSDFBitGl = mSDFBitGl;
    exports.mapFormatToGlFormat = mapFormatToGlFormat;
    exports.mapFormatToGlInternalFormat = mapFormatToGlInternalFormat;
    exports.mapFormatToGlType = mapFormatToGlType;
    exports.mapGlToVertexFormat = mapGlToVertexFormat;
    exports.mapSize = mapSize;
    exports.mapType = mapType;
    exports.mapWebGLBlendModesToPixi = mapWebGLBlendModesToPixi;
    exports.maskFrag = fragment;
    exports.maskVert = vertex;
    exports.maskWgsl = source;
    exports.matrixPool = matrixPool;
    exports.measureHtmlText = measureHtmlText;
    exports.measureMixin = measureMixin;
    exports.migrateFragmentFromV7toV8 = migrateFragmentFromV7toV8;
    exports.mipmapScaleModeToGlFilter = mipmapScaleModeToGlFilter;
    exports.multiplyColors = multiplyColors;
    exports.multiplyHexColors = multiplyHexColors;
    exports.nextPow2 = nextPow2;
    exports.noiseFrag = fragment$1;
    exports.noiseWgsl = source$1;
    exports.nonCompressedFormats = nonCompressedFormats;
    exports.normalizeExtensionPriority = normalizeExtensionPriority;
    exports.onRenderMixin = onRenderMixin;
    exports.parseDDS = parseDDS;
    exports.parseFunctionBody = parseFunctionBody;
    exports.parseKTX = parseKTX;
    exports.parseSVGDefinitions = parseSVGDefinitions;
    exports.parseSVGFloatAttribute = parseSVGFloatAttribute;
    exports.parseSVGPath = parseSVGPath;
    exports.parseSVGStyle = parseSVGStyle;
    exports.particleData = particleData;
    exports.particlesFrag = fragment$6;
    exports.particlesVert = vertex$3;
    exports.particlesWgsl = wgsl;
    exports.passthroughFrag = fragment$5;
    exports.passthroughWgsl = source$6;
    exports.path = path;
    exports.pointInTriangle = pointInTriangle;
    exports.preloadVideo = preloadVideo;
    exports.removeItems = removeItems;
    exports.removeStructAndGroupDuplicates = removeStructAndGroupDuplicates;
    exports.resetUids = resetUids;
    exports.resolveCharacters = resolveCharacters;
    exports.resolveCompressedTextureUrl = resolveCompressedTextureUrl;
    exports.resolveJsonUrl = resolveJsonUrl;
    exports.resolveTextureUrl = resolveTextureUrl;
    exports.resourceToTexture = resourceToTexture;
    exports.roundPixelsBit = roundPixelsBit;
    exports.roundPixelsBitGl = roundPixelsBitGl;
    exports.roundedShapeArc = roundedShapeArc;
    exports.roundedShapeQuadraticCurve = roundedShapeQuadraticCurve;
    exports.sayHello = sayHello;
    exports.scaleModeToGlFilter = scaleModeToGlFilter;
    exports.setBasisTranscoderPath = setBasisTranscoderPath;
    exports.setKTXTranscoderPath = setKTXTranscoderPath;
    exports.setPositions = setPositions;
    exports.setProgramName = setProgramName;
    exports.setUvs = setUvs;
    exports.shapeBuilders = shapeBuilders;
    exports.sortMixin = sortMixin;
    exports.spritesheetAsset = spritesheetAsset;
    exports.squaredDistanceToLineSegment = squaredDistanceToLineSegment;
    exports.stripVersion = stripVersion;
    exports.styleAttributes = styleAttributes;
    exports.testImageFormat = testImageFormat;
    exports.testVideoFormat = testVideoFormat;
    exports.textStyleToCSS = textStyleToCSS;
    exports.textureBit = textureBit;
    exports.textureBitGl = textureBitGl;
    exports.textureFrom = textureFrom;
    exports.tilingBit = tilingBit;
    exports.tilingBitGl = tilingBitGl;
    exports.toFillStyle = toFillStyle;
    exports.toLocalGlobalMixin = toLocalGlobalMixin;
    exports.toStrokeStyle = toStrokeStyle;
    exports.transformVertices = transformVertices;
    exports.triangulateWithHoles = triangulateWithHoles;
    exports.uboSyncFunctionsSTD40 = uboSyncFunctionsSTD40;
    exports.uboSyncFunctionsWGSL = uboSyncFunctionsWGSL;
    exports.uid = uid$1;
    exports.uniformParsers = uniformParsers;
    exports.unpremultiplyAlpha = unpremultiplyAlpha$1;
    exports.unsafeEvalSupported = unsafeEvalSupported;
    exports.updateLocalTransform = updateLocalTransform;
    exports.updateQuadBounds = updateQuadBounds;
    exports.updateRenderGroupTransform = updateRenderGroupTransform;
    exports.updateRenderGroupTransforms = updateRenderGroupTransforms;
    exports.updateTextBounds = updateTextBounds;
    exports.updateTransformAndChildren = updateTransformAndChildren;
    exports.updateTransformBackwards = updateTransformBackwards;
    exports.updateWorldTransform = updateWorldTransform;
    exports.v8_0_0 = v8_0_0;
    exports.v8_3_4 = v8_3_4;
    exports.validFormats = validFormats;
    exports.validateRenderables = validateRenderables;
    exports.vertexGPUTemplate = vertexGPUTemplate;
    exports.vertexGlTemplate = vertexGlTemplate;
    exports.vkFormatToGPUFormat = vkFormatToGPUFormat;
    exports.warn = warn;
    exports.webworkerExt = webworkerExt;
    exports.wrapModeToGlAddress = wrapModeToGlAddress;

    return exports;

})({});
//# sourceMappingURL=webworker.js.map
