diff --git "a/src/backend/gradio_polygonannotator/templates/component/Index-Ct_1BCRd.js" "b/src/backend/gradio_polygonannotator/templates/component/Index-Ct_1BCRd.js" new file mode 100644--- /dev/null +++ "b/src/backend/gradio_polygonannotator/templates/component/Index-Ct_1BCRd.js" @@ -0,0 +1,24285 @@ +var Gl = Object.defineProperty; +var Us = (i) => { + throw TypeError(i); +}; +var zl = (i, e, t) => e in i ? Gl(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t; +var ee = (i, e, t) => zl(i, typeof e != "symbol" ? e + "" : e, t), ql = (i, e, t) => e.has(i) || Us("Cannot " + t); +var Hs = (i, e, t) => e.has(i) ? Us("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(i) : e.set(i, t); +var Cn = (i, e, t) => (ql(i, e, "access private method"), t); +var X = /* @__PURE__ */ ((i) => (i.Application = "application", i.WebGLPipes = "webgl-pipes", i.WebGLPipesAdaptor = "webgl-pipes-adaptor", i.WebGLSystem = "webgl-system", i.WebGPUPipes = "webgpu-pipes", i.WebGPUPipesAdaptor = "webgpu-pipes-adaptor", i.WebGPUSystem = "webgpu-system", i.CanvasSystem = "canvas-system", i.CanvasPipesAdaptor = "canvas-pipes-adaptor", i.CanvasPipes = "canvas-pipes", i.Asset = "asset", i.LoadParser = "load-parser", i.ResolveParser = "resolve-parser", i.CacheParser = "cache-parser", i.DetectionParser = "detection-parser", i.MaskEffect = "mask-effect", i.BlendMode = "blend-mode", i.TextureSource = "texture-source", i.Environment = "environment", i.ShapeBuilder = "shape-builder", i.Batcher = "batcher", i))(X || {}); +const Vi = (i) => { + if (typeof i == "function" || typeof i == "object" && i.extension) { + if (!i.extension) + throw new Error("Extension class must have an extension object"); + i = { ...typeof i.extension != "object" ? { type: i.extension } : i.extension, ref: i }; + } + if (typeof i == "object") + i = { ...i }; + else + throw new Error("Invalid extension type"); + return typeof i.type == "string" && (i.type = [i.type]), i; +}, An = (i, e) => Vi(i).priority ?? e, Ve = { + /** @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(...i) { + return i.map(Vi).forEach((e) => { + e.type.forEach((t) => { + var n, s; + return (s = (n = this._removeHandlers)[t]) == null ? void 0 : s.call(n, e); + }); + }), 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(...i) { + return i.map(Vi).forEach((e) => { + e.type.forEach((t) => { + var r, a; + const n = this._addHandlers, s = this._queue; + n[t] ? (a = n[t]) == null || a.call(n, e) : (s[t] = s[t] || [], (r = s[t]) == null || r.push(e)); + }); + }), 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(i, e, t) { + var a; + const n = this._addHandlers, s = this._removeHandlers; + if (n[i] || s[i]) + throw new Error(`Extension type ${i} already has a handler`); + n[i] = e, s[i] = t; + const r = this._queue; + return r[i] && ((a = r[i]) == null || a.forEach((o) => e(o)), delete r[i]), 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(i, e) { + return this.handle( + i, + (t) => { + t.name && (e[t.name] = t.ref); + }, + (t) => { + t.name && delete e[t.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(i, e, t = -1) { + return this.handle( + i, + (n) => { + e.findIndex((r) => r.name === n.name) >= 0 || (e.push({ name: n.name, value: n.ref }), e.sort((r, a) => An(a.value, t) - An(r.value, t))); + }, + (n) => { + const s = e.findIndex((r) => r.name === n.name); + s !== -1 && e.splice(s, 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(i, e, t = -1) { + return this.handle( + i, + (n) => { + e.includes(n.ref) || (e.push(n.ref), e.sort((s, r) => An(r, t) - An(s, t))); + }, + (n) => { + const s = e.indexOf(n.ref); + s !== -1 && e.splice(s, 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(i, ...e) { + for (const t of e) + Object.defineProperties(i.prototype, Object.getOwnPropertyDescriptors(t)); + } +}, Ul = { + extension: { + type: X.Environment, + name: "browser", + priority: -1 + }, + test: () => !0, + load: async () => { + await import("./browserAll-CBYXns0T.js"); + } +}, Hl = { + extension: { + type: X.Environment, + name: "webworker", + priority: 0 + }, + test: () => typeof self < "u" && self.WorkerGlobalScope !== void 0, + load: async () => { + await import("./webworkerAll-FY7_jo4S.js"); + } +}; +class me { + /** + * 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(e, t, n) { + this._x = t || 0, this._y = n || 0, this._observer = e; + } + /** + * 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(e) { + return new me(e ?? 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(e = 0, t = e) { + return (this._x !== e || this._y !== t) && (this._x = e, this._y = t, this._observer._onUpdate(this)), 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(e) { + return (this._x !== e.x || this._y !== e.y) && (this._x = e.x, this._y = e.y, this._observer._onUpdate(this)), 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(e) { + return e.set(this._x, this._y), e; + } + /** + * 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(e) { + return e.x === this._x && e.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(e) { + this._x !== e && (this._x = e, 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(e) { + this._y !== e && (this._y = e, this._observer._onUpdate(this)); + } +} +var Vs = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; +function Ha(i) { + return i && i.__esModule && Object.prototype.hasOwnProperty.call(i, "default") ? i.default : i; +} +var Va = { exports: {} }; +(function(i) { + var e = Object.prototype.hasOwnProperty, t = "~"; + function n() { + } + Object.create && (n.prototype = /* @__PURE__ */ Object.create(null), new n().__proto__ || (t = !1)); + function s(l, u, h) { + this.fn = l, this.context = u, this.once = h || !1; + } + function r(l, u, h, c, f) { + if (typeof h != "function") + throw new TypeError("The listener must be a function"); + var d = new s(h, c || l, f), p = t ? t + u : u; + return l._events[p] ? l._events[p].fn ? l._events[p] = [l._events[p], d] : l._events[p].push(d) : (l._events[p] = d, l._eventsCount++), l; + } + function a(l, u) { + --l._eventsCount === 0 ? l._events = new n() : delete l._events[u]; + } + function o() { + this._events = new n(), this._eventsCount = 0; + } + o.prototype.eventNames = function() { + var u = [], h, c; + if (this._eventsCount === 0) return u; + for (c in h = this._events) + e.call(h, c) && u.push(t ? c.slice(1) : c); + return Object.getOwnPropertySymbols ? u.concat(Object.getOwnPropertySymbols(h)) : u; + }, o.prototype.listeners = function(u) { + var h = t ? t + u : u, c = this._events[h]; + if (!c) return []; + if (c.fn) return [c.fn]; + for (var f = 0, d = c.length, p = new Array(d); f < d; f++) + p[f] = c[f].fn; + return p; + }, o.prototype.listenerCount = function(u) { + var h = t ? t + u : u, c = this._events[h]; + return c ? c.fn ? 1 : c.length : 0; + }, o.prototype.emit = function(u, h, c, f, d, p) { + var b = t ? t + u : u; + if (!this._events[b]) return !1; + var m = this._events[b], x = arguments.length, g, _; + if (m.fn) { + switch (m.once && this.removeListener(u, m.fn, void 0, !0), x) { + case 1: + return m.fn.call(m.context), !0; + case 2: + return m.fn.call(m.context, h), !0; + case 3: + return m.fn.call(m.context, h, c), !0; + case 4: + return m.fn.call(m.context, h, c, f), !0; + case 5: + return m.fn.call(m.context, h, c, f, d), !0; + case 6: + return m.fn.call(m.context, h, c, f, d, p), !0; + } + for (_ = 1, g = new Array(x - 1); _ < x; _++) + g[_ - 1] = arguments[_]; + m.fn.apply(m.context, g); + } else { + var y = m.length, C; + for (_ = 0; _ < y; _++) + switch (m[_].once && this.removeListener(u, m[_].fn, void 0, !0), x) { + case 1: + m[_].fn.call(m[_].context); + break; + case 2: + m[_].fn.call(m[_].context, h); + break; + case 3: + m[_].fn.call(m[_].context, h, c); + break; + case 4: + m[_].fn.call(m[_].context, h, c, f); + break; + default: + if (!g) for (C = 1, g = new Array(x - 1); C < x; C++) + g[C - 1] = arguments[C]; + m[_].fn.apply(m[_].context, g); + } + } + return !0; + }, o.prototype.on = function(u, h, c) { + return r(this, u, h, c, !1); + }, o.prototype.once = function(u, h, c) { + return r(this, u, h, c, !0); + }, o.prototype.removeListener = function(u, h, c, f) { + var d = t ? t + u : u; + if (!this._events[d]) return this; + if (!h) + return a(this, d), this; + var p = this._events[d]; + if (p.fn) + p.fn === h && (!f || p.once) && (!c || p.context === c) && a(this, d); + else { + for (var b = 0, m = [], x = p.length; b < x; b++) + (p[b].fn !== h || f && !p[b].once || c && p[b].context !== c) && m.push(p[b]); + m.length ? this._events[d] = m.length === 1 ? m[0] : m : a(this, d); + } + return this; + }, o.prototype.removeAllListeners = function(u) { + var h; + return u ? (h = t ? t + u : u, this._events[h] && a(this, h)) : (this._events = new n(), this._eventsCount = 0), this; + }, o.prototype.off = o.prototype.removeListener, o.prototype.addListener = o.prototype.on, o.prefixed = t, o.EventEmitter = o, i.exports = o; +})(Va); +var Vl = Va.exports; +const dt = /* @__PURE__ */ Ha(Vl), Yl = Math.PI * 2, Xl = 180 / Math.PI, jl = Math.PI / 180; +class ge { + /** + * 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(e = 0, t = 0) { + this.x = 0, this.y = 0, this.x = e, this.y = t; + } + /** + * 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 ge(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(e) { + return this.set(e.x, e.y), 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(e) { + return e.set(this.x, this.y), e; + } + /** + * 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(e) { + return e.x === this.x && e.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(e = 0, t = e) { + return this.x = e, this.y = t, 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() { + return di.x = 0, di.y = 0, di; + } +} +const di = new ge(); +class q { + /** + * @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(e = 1, t = 0, n = 0, s = 1, r = 0, a = 0) { + this.array = null, this.a = e, this.b = t, this.c = n, this.d = s, this.tx = r, this.ty = a; + } + /** + * 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(e) { + this.a = e[0], this.b = e[1], this.c = e[3], this.d = e[4], this.tx = e[2], this.ty = e[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(e, t, n, s, r, a) { + return this.a = e, this.b = t, this.c = n, this.d = s, this.tx = r, this.ty = a, 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(e, t) { + this.array || (this.array = new Float32Array(9)); + const n = t || this.array; + return e ? (n[0] = this.a, n[1] = this.b, n[2] = 0, n[3] = this.c, n[4] = this.d, n[5] = 0, n[6] = this.tx, n[7] = this.ty, n[8] = 1) : (n[0] = this.a, n[1] = this.c, n[2] = this.tx, n[3] = this.b, n[4] = this.d, n[5] = this.ty, n[6] = 0, n[7] = 0, n[8] = 1), n; + } + /** + * 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(e, t) { + t = t || new ge(); + const n = e.x, s = e.y; + return t.x = this.a * n + this.c * s + this.tx, t.y = this.b * n + this.d * s + this.ty, t; + } + /** + * 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(e, t) { + t = t || new ge(); + const n = this.a, s = this.b, r = this.c, a = this.d, o = this.tx, l = this.ty, u = 1 / (n * a + r * -s), h = e.x, c = e.y; + return t.x = a * u * h + -r * u * c + (l * r - o * a) * u, t.y = n * u * c + -s * u * h + (-l * n + o * s) * u, t; + } + /** + * 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(e, t) { + return this.tx += e, this.ty += t, 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(e, t) { + return this.a *= e, this.d *= t, this.c *= e, this.b *= t, this.tx *= e, this.ty *= t, 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(e) { + const t = Math.cos(e), n = Math.sin(e), s = this.a, r = this.c, a = this.tx; + return this.a = s * t - this.b * n, this.b = s * n + this.b * t, this.c = r * t - this.d * n, this.d = r * n + this.d * t, this.tx = a * t - this.ty * n, this.ty = a * n + this.ty * t, 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(e) { + const t = this.a, n = this.b, s = this.c, r = this.d; + return this.a = e.a * t + e.b * s, this.b = e.a * n + e.b * r, this.c = e.c * t + e.d * s, this.d = e.c * n + e.d * r, this.tx = e.tx * t + e.ty * s + this.tx, this.ty = e.tx * n + e.ty * r + this.ty, 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(e, t) { + const n = e.a, s = e.b, r = e.c, a = e.d, o = e.tx, l = e.ty, u = t.a, h = t.b, c = t.c, f = t.d; + return this.a = n * u + s * c, this.b = n * h + s * f, this.c = r * u + a * c, this.d = r * h + a * f, this.tx = o * u + l * c + t.tx, this.ty = o * h + l * f + t.ty, 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(e, t, n, s, r, a, o, l, u) { + return this.a = Math.cos(o + u) * r, this.b = Math.sin(o + u) * r, this.c = -Math.sin(o - l) * a, this.d = Math.cos(o - l) * a, this.tx = e - (n * this.a + s * this.c), this.ty = t - (n * this.b + s * this.d), 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(e) { + const t = this.tx; + if (e.a !== 1 || e.b !== 0 || e.c !== 0 || e.d !== 1) { + const n = this.a, s = this.c; + this.a = n * e.a + this.b * e.c, this.b = n * e.b + this.b * e.d, this.c = s * e.a + this.d * e.c, this.d = s * e.b + this.d * e.d; + } + return this.tx = t * e.a + this.ty * e.c + e.tx, this.ty = t * e.b + this.ty * e.d + e.ty, 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(e) { + const t = this.a, n = this.b, s = this.c, r = this.d, a = e.pivot, o = -Math.atan2(-s, r), l = Math.atan2(n, t), u = Math.abs(o + l); + return u < 1e-5 || Math.abs(Yl - u) < 1e-5 ? (e.rotation = l, e.skew.x = e.skew.y = 0) : (e.rotation = 0, e.skew.x = o, e.skew.y = l), e.scale.x = Math.sqrt(t * t + n * n), e.scale.y = Math.sqrt(s * s + r * r), e.position.x = this.tx + (a.x * t + a.y * s), e.position.y = this.ty + (a.x * n + a.y * r), e; + } + /** + * 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 e = this.a, t = this.b, n = this.c, s = this.d, r = this.tx, a = e * s - t * n; + return this.a = s / a, this.b = -t / a, this.c = -n / a, this.d = e / a, this.tx = (n * this.ty - s * r) / a, this.ty = -(e * this.ty - t * r) / a, 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() { + return this.a = 1, this.b = 0, this.c = 0, this.d = 1, this.tx = 0, this.ty = 0, 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 e = new q(); + return e.a = this.a, e.b = this.b, e.c = this.c, e.d = this.d, e.tx = this.tx, e.ty = this.ty, e; + } + /** + * 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(e) { + return e.a = this.a, e.b = this.b, e.c = this.c, e.d = this.d, e.tx = this.tx, e.ty = this.ty, e; + } + /** + * 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(e) { + return this.a = e.a, this.b = e.b, this.c = e.c, this.d = e.d, this.tx = e.tx, this.ty = e.ty, 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(e) { + return e.a === this.a && e.b === this.b && e.c === this.c && e.d === this.d && e.tx === this.tx && e.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 Zl.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 Wl.identity(); + } +} +const Wl = new q(), Zl = new q(), bt = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1], xt = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1], vt = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1], wt = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1], Yi = [], Ya = [], kn = Math.sign; +function Kl() { + for (let i = 0; i < 16; i++) { + const e = []; + Yi.push(e); + for (let t = 0; t < 16; t++) { + const n = kn(bt[i] * bt[t] + vt[i] * xt[t]), s = kn(xt[i] * bt[t] + wt[i] * xt[t]), r = kn(bt[i] * vt[t] + vt[i] * wt[t]), a = kn(xt[i] * vt[t] + wt[i] * wt[t]); + for (let o = 0; o < 16; o++) + if (bt[o] === n && xt[o] === s && vt[o] === r && wt[o] === a) { + e.push(o); + break; + } + } + } + for (let i = 0; i < 16; i++) { + const e = new q(); + e.set(bt[i], xt[i], vt[i], wt[i], 0, 0), Ya.push(e); + } +} +Kl(); +const J = { + /** + * | 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: (i) => bt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The Y-component of the U-axis + * after rotating the axes. + */ + uY: (i) => xt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The X-component of the V-axis + * after rotating the axes. + */ + vX: (i) => vt[i], + /** + * @group groupD8 + * @param {GD8Symmetry} ind - sprite rotation angle. + * @returns {GD8Symmetry} The Y-component of the V-axis + * after rotating the axes. + */ + vY: (i) => wt[i], + /** + * @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: (i) => i & 8 ? i & 15 : -i & 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: (i, e) => Yi[i][e], + /** + * Reverse of `add`. + * @group groupD8 + * @param {GD8Symmetry} rotationSecond - Second operation + * @param {GD8Symmetry} rotationFirst - First operation + * @returns {GD8Symmetry} Result + */ + sub: (i, e) => Yi[i][J.inv(e)], + /** + * Adds 180 degrees to rotation, which is a commutative + * operation. + * @group groupD8 + * @param {number} rotation - The number to rotate. + * @returns {number} Rotated number + */ + rotate180: (i) => i ^ 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: (i) => (i & 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: (i, e) => Math.abs(i) * 2 <= Math.abs(e) ? e >= 0 ? J.S : J.N : Math.abs(e) * 2 <= Math.abs(i) ? i > 0 ? J.E : J.W : e > 0 ? i > 0 ? J.SE : J.SW : i > 0 ? J.NE : J.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: (i, e, t = 0, n = 0) => { + const s = Ya[J.inv(e)]; + s.tx = t, s.ty = n, i.append(s); + }, + /** + * 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: (i, e, t, n) => { + const { x: s, y: r, width: a, height: o } = i, { x: l, y: u, width: h, height: c } = e; + return t === J.E ? (n.set(s + l, r + u, a, o), n) : t === J.S ? n.set( + h - r - o + l, + s + u, + o, + a + ) : t === J.W ? n.set( + h - s - a + l, + c - r - o + u, + a, + o + ) : t === J.N ? n.set( + r + l, + c - s - a + u, + o, + a + ) : n.set(s + l, r + u, a, o); + } +}, Dn = [new ge(), new ge(), new ge(), new ge()]; +class ce { + /** + * @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(e = 0, t = 0, n = 0, s = 0) { + this.type = "rectangle", this.x = Number(e), this.y = Number(t), this.width = Number(n), this.height = Number(s); + } + /** + * 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 ce(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 ce(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(e) { + return this.x = e.minX, this.y = e.minY, this.width = e.maxX - e.minX, this.height = e.maxY - e.minY, 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(e) { + return this.x = e.x, this.y = e.y, this.width = e.width, this.height = e.height, 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(e) { + return e.copyFrom(this), e; + } + /** + * 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(e, t) { + return this.width <= 0 || this.height <= 0 ? !1 : e >= this.x && e < this.x + this.width && t >= this.y && t < this.y + this.height; + } + /** + * 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(e, t, n, s = 0.5) { + const { width: r, height: a } = this; + if (r <= 0 || a <= 0) + return !1; + const o = this.x, l = this.y, u = n * (1 - s), h = n - u, c = o - u, f = o + r + u, d = l - u, p = l + a + u, b = o + h, m = o + r - h, x = l + h, g = l + a - h; + return e >= c && e <= f && t >= d && t <= p && !(e > b && e < m && t > x && t < g); + } + /** + * 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(e, t) { + if (!t) { + const $ = this.x < e.x ? e.x : this.x; + if ((this.right > e.right ? e.right : this.right) <= $) + return !1; + const k = this.y < e.y ? e.y : this.y; + return (this.bottom > e.bottom ? e.bottom : this.bottom) > k; + } + const n = this.left, s = this.right, r = this.top, a = this.bottom; + if (s <= n || a <= r) + return !1; + const o = Dn[0].set(e.left, e.top), l = Dn[1].set(e.left, e.bottom), u = Dn[2].set(e.right, e.top), h = Dn[3].set(e.right, e.bottom); + if (u.x <= o.x || l.y <= o.y) + return !1; + const c = Math.sign(t.a * t.d - t.b * t.c); + if (c === 0 || (t.apply(o, o), t.apply(l, l), t.apply(u, u), t.apply(h, h), Math.max(o.x, l.x, u.x, h.x) <= n || Math.min(o.x, l.x, u.x, h.x) >= s || Math.max(o.y, l.y, u.y, h.y) <= r || Math.min(o.y, l.y, u.y, h.y) >= a)) + return !1; + const f = c * (l.y - o.y), d = c * (o.x - l.x), p = f * n + d * r, b = f * s + d * r, m = f * n + d * a, x = f * s + d * a; + if (Math.max(p, b, m, x) <= f * o.x + d * o.y || Math.min(p, b, m, x) >= f * h.x + d * h.y) + return !1; + const g = c * (o.y - u.y), _ = c * (u.x - o.x), y = g * n + _ * r, C = g * s + _ * r, v = g * n + _ * a, w = g * s + _ * a; + return !(Math.max(y, C, v, w) <= g * o.x + _ * o.y || Math.min(y, C, v, w) >= g * h.x + _ * h.y); + } + /** + * 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(e = 0, t = e) { + return this.x -= e, this.y -= t, this.width += e * 2, this.height += t * 2, 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(e) { + const t = Math.max(this.x, e.x), n = Math.min(this.x + this.width, e.x + e.width), s = Math.max(this.y, e.y), r = Math.min(this.y + this.height, e.y + e.height); + return this.x = t, this.width = Math.max(n - t, 0), this.y = s, this.height = Math.max(r - s, 0), 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(e = 1, t = 1e-3) { + const n = Math.ceil((this.x + this.width - t) * e) / e, s = Math.ceil((this.y + this.height - t) * e) / e; + return this.x = Math.floor((this.x + t) * e) / e, this.y = Math.floor((this.y + t) * e) / e, this.width = n - this.x, this.height = s - this.y, 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(e, t = e) { + return this.x *= e, this.y *= t, this.width *= e, this.height *= t, 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(e) { + const t = Math.min(this.x, e.x), n = Math.max(this.x + this.width, e.x + e.width), s = Math.min(this.y, e.y), r = Math.max(this.y + this.height, e.y + e.height); + return this.x = t, this.width = n - t, this.y = s, this.height = r - s, 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(e) { + return e || (e = new ce()), e.copyFrom(this), e; + } + /** + * 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(e) { + if (this.width <= 0 || this.height <= 0) + return !1; + const t = e.x, n = e.y, s = e.x + e.width, r = e.y + e.height; + return t >= this.x && t < this.x + this.width && n >= this.y && n < this.y + this.height && s >= this.x && s < this.x + this.width && r >= this.y && r < 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(e, t, n, s) { + return this.x = e, this.y = t, this.width = n, this.height = s, this; + } + toString() { + return `[pixi.js/math:Rectangle x=${this.x} y=${this.y} width=${this.width} height=${this.height}]`; + } +} +const fi = { + default: -1 +}; +function re(i = "default") { + return fi[i] === void 0 && (fi[i] = -1), ++fi[i]; +} +const Ys = /* @__PURE__ */ new Set(), le = "8.0.0", Ql = "8.3.4", Rt = { + quiet: !1, + noColor: !1 +}, j = (i, e, t = 3) => { + if (Rt.quiet || Ys.has(e)) + return; + let n = new Error().stack; + const s = `${e} +Deprecated since v${i}`, r = typeof console.groupCollapsed == "function" && !Rt.noColor; + typeof n > "u" ? console.warn("PixiJS Deprecation Warning: ", s) : (n = n.split(` +`).splice(t).join(` +`), r ? (console.groupCollapsed( + "%cPixiJS Deprecation Warning: %c%s", + "color:#614108;background:#fffbe6", + "font-weight:normal;color:#614108;background:#fffbe6", + s + ), console.warn(n), console.groupEnd()) : (console.warn("PixiJS Deprecation Warning: ", s), console.warn(n))), Ys.add(e); +}; +Object.defineProperties(j, { + quiet: { + get: () => Rt.quiet, + set: (i) => { + Rt.quiet = i; + }, + enumerable: !0, + configurable: !1 + }, + noColor: { + get: () => Rt.noColor, + set: (i) => { + Rt.noColor = i; + }, + enumerable: !0, + configurable: !1 + } +}); +const Xa = () => { +}; +function Xs(i) { + return i += i === 0 ? 1 : 0, --i, i |= i >>> 1, i |= i >>> 2, i |= i >>> 4, i |= i >>> 8, i |= i >>> 16, i + 1; +} +function js(i) { + return !(i & i - 1) && !!i; +} +function ja(i) { + const e = {}; + for (const t in i) + i[t] !== void 0 && (e[t] = i[t]); + return e; +} +const Ws = /* @__PURE__ */ Object.create(null); +function Jl(i) { + const e = Ws[i]; + return e === void 0 && (Ws[i] = re("resource")), e; +} +const Wa = class Za extends dt { + /** + * @param options - options for the style + */ + constructor(e = {}) { + super(), this._resourceType = "textureSampler", this._touched = 0, this._maxAnisotropy = 1, this.destroyed = !1, e = { ...Za.defaultOptions, ...e }, this.addressMode = e.addressMode, this.addressModeU = e.addressModeU ?? this.addressModeU, this.addressModeV = e.addressModeV ?? this.addressModeV, this.addressModeW = e.addressModeW ?? this.addressModeW, this.scaleMode = e.scaleMode, this.magFilter = e.magFilter ?? this.magFilter, this.minFilter = e.minFilter ?? this.minFilter, this.mipmapFilter = e.mipmapFilter ?? this.mipmapFilter, this.lodMinClamp = e.lodMinClamp, this.lodMaxClamp = e.lodMaxClamp, this.compare = e.compare, this.maxAnisotropy = e.maxAnisotropy ?? 1; + } + set addressMode(e) { + this.addressModeU = e, this.addressModeV = e, this.addressModeW = e; + } + /** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */ + get addressMode() { + return this.addressModeU; + } + set wrapMode(e) { + j(le, "TextureStyle.wrapMode is now TextureStyle.addressMode"), this.addressMode = e; + } + get wrapMode() { + return this.addressMode; + } + set scaleMode(e) { + this.magFilter = e, this.minFilter = e, this.mipmapFilter = e; + } + /** 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(e) { + this._maxAnisotropy = Math.min(e, 16), 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.emit("change", this), this._sharedResourceId = null; + } + _generateResourceId() { + const e = `${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`; + return this._sharedResourceId = Jl(e), this._resourceId; + } + /** Destroys the style */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this.removeAllListeners(); + } +}; +Wa.defaultOptions = { + addressMode: "clamp-to-edge", + scaleMode: "linear" +}; +let Ka = Wa; +const Qa = class Ja extends dt { + /** + * @param options - options for creating a new TextureSource + */ + constructor(e = {}) { + super(), this.options = e, this.uid = re("textureSource"), this._resourceType = "textureSource", this._resourceId = re("resource"), this.uploadMethodId = "unknown", this._resolution = 1, this.pixelWidth = 1, this.pixelHeight = 1, this.width = 1, this.height = 1, this.sampleCount = 1, this.mipLevelCount = 1, this.autoGenerateMipmaps = !1, this.format = "rgba8unorm", this.dimension = "2d", this.antialias = !1, this._touched = 0, this._batchTick = -1, this._textureBindLocation = -1, e = { ...Ja.defaultOptions, ...e }, this.label = e.label ?? "", this.resource = e.resource, this.autoGarbageCollect = e.autoGarbageCollect, this._resolution = e.resolution, e.width ? this.pixelWidth = e.width * this._resolution : this.pixelWidth = this.resource ? this.resourceWidth ?? 1 : 1, e.height ? this.pixelHeight = e.height * this._resolution : this.pixelHeight = this.resource ? this.resourceHeight ?? 1 : 1, this.width = this.pixelWidth / this._resolution, this.height = this.pixelHeight / this._resolution, this.format = e.format, this.dimension = e.dimensions, this.mipLevelCount = e.mipLevelCount, this.autoGenerateMipmaps = e.autoGenerateMipmaps, this.sampleCount = e.sampleCount, this.antialias = e.antialias, this.alphaMode = e.alphaMode, this.style = new Ka(ja(e)), this.destroyed = !1, this._refreshPOT(); + } + /** returns itself */ + get source() { + return this; + } + /** the style of the texture */ + get style() { + return this._style; + } + set style(e) { + var t, n; + this.style !== e && ((t = this._style) == null || t.off("change", this._onStyleChange, this), this._style = e, (n = this._style) == null || n.on("change", this._onStyleChange, this), this._onStyleChange()); + } + /** Specifies the maximum anisotropy value clamp used by the sampler. */ + set maxAnisotropy(e) { + this._style.maxAnisotropy = e; + } + 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(e) { + this._style.addressMode = e; + } + /** setting this will set wrapModeU, wrapModeV and wrapModeW all at once! */ + get repeatMode() { + return this._style.addressMode; + } + set repeatMode(e) { + this._style.addressMode = e; + } + /** Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel. */ + get magFilter() { + return this._style.magFilter; + } + set magFilter(e) { + this._style.magFilter = e; + } + /** Specifies the sampling behavior when the sample footprint is larger than one texel. */ + get minFilter() { + return this._style.minFilter; + } + set minFilter(e) { + this._style.minFilter = e; + } + /** Specifies behavior for sampling between mipmap levels. */ + get mipmapFilter() { + return this._style.mipmapFilter; + } + set mipmapFilter(e) { + this._style.mipmapFilter = e; + } + /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */ + get lodMinClamp() { + return this._style.lodMinClamp; + } + set lodMinClamp(e) { + this._style.lodMinClamp = e; + } + /** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */ + get lodMaxClamp() { + return this._style.lodMaxClamp; + } + set lodMaxClamp(e) { + this._style.lodMaxClamp = e; + } + _onStyleChange() { + this.emit("styleChange", this); + } + /** call this if you have modified the texture outside of the constructor */ + update() { + if (this.resource) { + const e = this._resolution; + if (this.resize(this.resourceWidth / e, this.resourceHeight / e)) + return; + } + this.emit("update", this); + } + /** Destroys this texture source */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), 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() { + this._resourceId = re("resource"), this.emit("change", this), this.emit("unload", this); + } + /** the width of the resource. This is the REAL pure number, not accounting resolution */ + get resourceWidth() { + const { resource: e } = this; + return e.naturalWidth || e.videoWidth || e.displayWidth || e.width; + } + /** the height of the resource. This is the REAL pure number, not accounting resolution */ + get resourceHeight() { + const { resource: e } = this; + return e.naturalHeight || e.videoHeight || e.displayHeight || e.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(e) { + this._resolution !== e && (this._resolution = e, this.width = this.pixelWidth / e, this.height = this.pixelHeight / e); + } + /** + * 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(e, t, n) { + n || (n = this._resolution), e || (e = this.width), t || (t = this.height); + const s = Math.round(e * n), r = Math.round(t * n); + return this.width = s / n, this.height = r / n, this._resolution = n, this.pixelWidth === s && this.pixelHeight === r ? !1 : (this._refreshPOT(), this.pixelWidth = s, this.pixelHeight = r, this.emit("resize", this), this._resourceId = re("resource"), this.emit("change", this), !0); + } + /** + * 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() { + this.autoGenerateMipmaps && this.mipLevelCount > 1 && this.emit("updateMipmaps", this); + } + set wrapMode(e) { + this._style.wrapMode = e; + } + get wrapMode() { + return this._style.wrapMode; + } + set scaleMode(e) { + this._style.scaleMode = e; + } + /** 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 = js(this.pixelWidth) && js(this.pixelHeight); + } + static test(e) { + throw new Error("Unimplemented"); + } +}; +Qa.defaultOptions = { + resolution: 1, + format: "bgra8unorm", + alphaMode: "premultiply-alpha-on-upload", + dimensions: "2d", + mipLevelCount: 1, + autoGenerateMipmaps: !1, + sampleCount: 1, + antialias: !1, + autoGarbageCollect: !1 +}; +let et = Qa; +class ws extends et { + constructor(e) { + const t = e.resource || new Float32Array(e.width * e.height * 4); + let n = e.format; + n || (t instanceof Float32Array ? n = "rgba32float" : t instanceof Int32Array || t instanceof Uint32Array ? n = "rgba32uint" : t instanceof Int16Array || t instanceof Uint16Array ? n = "rgba16uint" : (t instanceof Int8Array, n = "bgra8unorm")), super({ + ...e, + resource: t, + format: n + }), this.uploadMethodId = "buffer"; + } + static test(e) { + return e instanceof Int8Array || e instanceof Uint8Array || e instanceof Uint8ClampedArray || e instanceof Int16Array || e instanceof Uint16Array || e instanceof Int32Array || e instanceof Uint32Array || e instanceof Float32Array; + } +} +ws.extension = X.TextureSource; +const Zs = new q(); +class eu { + /** + * @param texture - observed texture + * @param clampMargin - Changes frame clamping, 0.5 by default. Use -0.5 for extra border. + */ + constructor(e, t) { + this.mapCoord = new q(), this.uClampFrame = new Float32Array(4), this.uClampOffset = new Float32Array(2), this._textureID = -1, this._updateID = 0, this.clampOffset = 0, typeof t > "u" ? this.clampMargin = e.width < 10 ? 0 : 0.5 : this.clampMargin = t, this.isSimple = !1, this.texture = e; + } + /** Texture property. */ + get texture() { + return this._texture; + } + set texture(e) { + var t; + this.texture !== e && ((t = this._texture) == null || t.removeListener("update", this.update, this), this._texture = e, 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(e, t) { + t === void 0 && (t = e); + const n = this.mapCoord; + for (let s = 0; s < e.length; s += 2) { + const r = e[s], a = e[s + 1]; + t[s] = r * n.a + a * n.c + n.tx, t[s + 1] = r * n.b + a * n.d + n.ty; + } + return t; + } + /** + * Updates matrices if texture was changed + * @returns - whether or not it was updated + */ + update() { + const e = this._texture; + this._updateID++; + const t = e.uvs; + this.mapCoord.set(t.x1 - t.x0, t.y1 - t.y0, t.x3 - t.x0, t.y3 - t.y0, t.x0, t.y0); + const n = e.orig, s = e.trim; + s && (Zs.set( + n.width / s.width, + 0, + 0, + n.height / s.height, + -s.x / s.width, + -s.y / s.height + ), this.mapCoord.append(Zs)); + const r = e.source, a = this.uClampFrame, o = this.clampMargin / r._resolution, l = this.clampOffset / r._resolution; + return a[0] = (e.frame.x + o + l) / r.width, a[1] = (e.frame.y + o + l) / r.height, a[2] = (e.frame.x + e.frame.width - o + l) / r.width, a[3] = (e.frame.y + e.frame.height - o + l) / r.height, this.uClampOffset[0] = this.clampOffset / r.pixelWidth, this.uClampOffset[1] = this.clampOffset / r.pixelHeight, this.isSimple = e.frame.width === r.width && e.frame.height === r.height && e.rotate === 0, !0; + } +} +class W extends dt { + /** + * @param {TextureOptions} options - Options for the texture + */ + constructor({ + source: e, + label: t, + frame: n, + orig: s, + trim: r, + defaultAnchor: a, + defaultBorders: o, + rotate: l, + dynamic: u + } = {}) { + if (super(), this.uid = re("texture"), this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 }, this.frame = new ce(), this.noFrame = !1, this.dynamic = !1, this.isTexture = !0, this.label = t, this.source = (e == null ? void 0 : e.source) ?? new et(), this.noFrame = !n, n) + this.frame.copyFrom(n); + else { + const { width: h, height: c } = this._source; + this.frame.width = h, this.frame.height = c; + } + this.orig = s || this.frame, this.trim = r, this.rotate = l ?? 0, this.defaultAnchor = a, this.defaultBorders = o, this.destroyed = !1, this.dynamic = u || !1, this.updateUvs(); + } + set source(e) { + this._source && this._source.off("resize", this.update, this), this._source = e, e.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() { + return this._textureMatrix || (this._textureMatrix = new eu(this)), 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: e, frame: t } = this, { width: n, height: s } = this._source, r = t.x / n, a = t.y / s, o = t.width / n, l = t.height / s; + let u = this.rotate; + if (u) { + const h = o / 2, c = l / 2, f = r + h, d = a + c; + u = J.add(u, J.NW), e.x0 = f + h * J.uX(u), e.y0 = d + c * J.uY(u), u = J.add(u, 2), e.x1 = f + h * J.uX(u), e.y1 = d + c * J.uY(u), u = J.add(u, 2), e.x2 = f + h * J.uX(u), e.y2 = d + c * J.uY(u), u = J.add(u, 2), e.x3 = f + h * J.uX(u), e.y3 = d + c * J.uY(u); + } else + e.x0 = r, e.y0 = a, e.x1 = r + o, e.y1 = a, e.x2 = r + o, e.y2 = a + l, e.x3 = r, e.y3 = a + l; + } + /** + * Destroys this texture + * @param destroySource - Destroy the source when the texture is destroyed. + */ + destroy(e = !1) { + this._source && e && (this._source.destroy(), this._source = null), this._textureMatrix = null, this.destroyed = !0, 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() { + 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() { + return j(le, "Texture.baseTexture is now Texture.source"), this._source; + } +} +W.EMPTY = new W({ + label: "EMPTY", + source: new et({ + label: "EMPTY" + }) +}); +W.EMPTY.destroy = Xa; +W.WHITE = new W({ + source: new ws({ + resource: new Uint8Array([255, 255, 255, 255]), + width: 1, + height: 1, + alphaMode: "premultiply-alpha-on-upload", + label: "WHITE" + }), + label: "WHITE" +}); +W.WHITE.destroy = Xa; +function tu(i, e, t) { + const { width: n, height: s } = t.orig, r = t.trim; + if (r) { + const a = r.width, o = r.height; + i.minX = r.x - e._x * n, i.maxX = i.minX + a, i.minY = r.y - e._y * s, i.maxY = i.minY + o; + } else + i.minX = -e._x * n, i.maxX = i.minX + n, i.minY = -e._y * s, i.maxY = i.minY + s; +} +const Ks = new q(); +class Je { + /** + * 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(e = 1 / 0, t = 1 / 0, n = -1 / 0, s = -1 / 0) { + this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Ks, this.minX = e, this.minY = t, this.maxX = n, this.maxY = s; + } + /** + * 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() { + this._rectangle || (this._rectangle = new ce()); + const e = this._rectangle; + return this.minX > this.maxX || this.minY > this.maxY ? (e.x = 0, e.y = 0, e.width = 0, e.height = 0) : e.copyFromBounds(this), e; + } + /** + * 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() { + return this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Ks, 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(e, t, n, s) { + this.minX = e, this.minY = t, this.maxX = n, this.maxY = s; + } + /** + * 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(e, t, n, s, r) { + r || (r = this.matrix); + const a = r.a, o = r.b, l = r.c, u = r.d, h = r.tx, c = r.ty; + let f = this.minX, d = this.minY, p = this.maxX, b = this.maxY, m = a * e + l * t + h, x = o * e + u * t + c; + m < f && (f = m), x < d && (d = x), m > p && (p = m), x > b && (b = x), m = a * n + l * t + h, x = o * n + u * t + c, m < f && (f = m), x < d && (d = x), m > p && (p = m), x > b && (b = x), m = a * e + l * s + h, x = o * e + u * s + c, m < f && (f = m), x < d && (d = x), m > p && (p = m), x > b && (b = x), m = a * n + l * s + h, x = o * n + u * s + c, m < f && (f = m), x < d && (d = x), m > p && (p = m), x > b && (b = x), this.minX = f, this.minY = d, this.maxX = p, this.maxY = b; + } + /** + * 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(e, t) { + this.addFrame(e.x, e.y, e.x + e.width, e.y + e.height, t); + } + /** + * 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(e, t) { + this.addFrame(e.minX, e.minY, e.maxX, e.maxY, t); + } + /** + * 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(e) { + this.minX = this.minX > e.minX ? this.minX : e.minX, this.minY = this.minY > e.minY ? this.minY : e.minY, this.maxX = this.maxX < e.maxX ? this.maxX : e.maxX, this.maxY = this.maxY < e.maxY ? this.maxY : e.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(e) { + const t = this.minX, n = this.minY, s = this.maxX, r = this.maxY, { a, b: o, c: l, d: u, tx: h, ty: c } = e; + let f = a * t + l * n + h, d = o * t + u * n + c; + this.minX = f, this.minY = d, this.maxX = f, this.maxY = d, f = a * s + l * n + h, d = o * s + u * n + c, this.minX = f < this.minX ? f : this.minX, this.minY = d < this.minY ? d : this.minY, this.maxX = f > this.maxX ? f : this.maxX, this.maxY = d > this.maxY ? d : this.maxY, f = a * t + l * r + h, d = o * t + u * r + c, this.minX = f < this.minX ? f : this.minX, this.minY = d < this.minY ? d : this.minY, this.maxX = f > this.maxX ? f : this.maxX, this.maxY = d > this.maxY ? d : this.maxY, f = a * s + l * r + h, d = o * s + u * r + c, this.minX = f < this.minX ? f : this.minX, this.minY = d < this.minY ? d : this.minY, this.maxX = f > this.maxX ? f : this.maxX, this.maxY = d > this.maxY ? d : 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(e) { + return this.minX < e.left && (this.minX = e.left), this.maxX > e.right && (this.maxX = e.right), this.minY < e.top && (this.minY = e.top), this.maxY > e.bottom && (this.maxY = e.bottom), 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(e, t, n, s) { + return this.minX < e && (this.minX = e), this.maxX > t && (this.maxX = t), this.minY < n && (this.minY = n), this.maxY > s && (this.maxY = s), 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(e, t = e) { + return this.minX -= e, this.maxX += e, this.minY -= t, this.maxY += t, 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() { + return this.minX = Math.floor(this.minX), this.minY = Math.floor(this.minY), this.maxX = Math.ceil(this.maxX), this.maxY = Math.ceil(this.maxY), 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 Je(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(e, t = e) { + return this.minX *= e, this.minY *= t, this.maxX *= e, this.maxY *= t, 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(e) { + const t = this.maxX - this.minX; + this.minX = e, this.maxX = e + t; + } + /** + * 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(e) { + const t = this.maxY - this.minY; + this.minY = e, this.maxY = e + t; + } + /** + * 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(e) { + this.maxX = this.minX + e; + } + /** + * 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(e) { + this.maxY = this.minY + e; + } + /** + * 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 !== 1 / 0; + } + /** + * 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(e, t, n, s) { + let r = this.minX, a = this.minY, o = this.maxX, l = this.maxY; + s || (s = this.matrix); + const u = s.a, h = s.b, c = s.c, f = s.d, d = s.tx, p = s.ty; + for (let b = t; b < n; b += 2) { + const m = e[b], x = e[b + 1], g = u * m + c * x + d, _ = h * m + f * x + p; + r = g < r ? g : r, a = _ < a ? _ : a, o = g > o ? g : o, l = _ > l ? _ : l; + } + this.minX = r, this.minY = a, this.maxX = o, this.maxY = l; + } + /** + * 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(e, t) { + return this.minX <= e && this.minY <= t && this.maxX >= e && this.maxY >= t; + } + /** + * 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(e) { + return this.minX = e.minX, this.minY = e.minY, this.maxX = e.maxX, this.maxY = e.maxY, this; + } +} +var nu = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, lt = function(i) { + return typeof i == "string" ? i.length > 0 : typeof i == "number"; +}, he = function(i, e, t) { + return e === void 0 && (e = 0), t === void 0 && (t = Math.pow(10, e)), Math.round(t * i) / t + 0; +}, Le = function(i, e, t) { + return e === void 0 && (e = 0), t === void 0 && (t = 1), i > t ? t : i > e ? i : e; +}, eo = function(i) { + return (i = isFinite(i) ? i % 360 : 0) > 0 ? i : i + 360; +}, Qs = function(i) { + return { r: Le(i.r, 0, 255), g: Le(i.g, 0, 255), b: Le(i.b, 0, 255), a: Le(i.a) }; +}, _i = function(i) { + return { r: he(i.r), g: he(i.g), b: he(i.b), a: he(i.a, 3) }; +}, iu = /^#([0-9a-f]{3,8})$/i, Sn = function(i) { + var e = i.toString(16); + return e.length < 2 ? "0" + e : e; +}, to = function(i) { + var e = i.r, t = i.g, n = i.b, s = i.a, r = Math.max(e, t, n), a = r - Math.min(e, t, n), o = a ? r === e ? (t - n) / a : r === t ? 2 + (n - e) / a : 4 + (e - t) / a : 0; + return { h: 60 * (o < 0 ? o + 6 : o), s: r ? a / r * 100 : 0, v: r / 255 * 100, a: s }; +}, no = function(i) { + var e = i.h, t = i.s, n = i.v, s = i.a; + e = e / 360 * 6, t /= 100, n /= 100; + var r = Math.floor(e), a = n * (1 - t), o = n * (1 - (e - r) * t), l = n * (1 - (1 - e + r) * t), u = r % 6; + return { r: 255 * [n, o, a, a, l, n][u], g: 255 * [l, n, n, o, a, a][u], b: 255 * [a, a, l, n, n, o][u], a: s }; +}, Js = function(i) { + return { h: eo(i.h), s: Le(i.s, 0, 100), l: Le(i.l, 0, 100), a: Le(i.a) }; +}, er = function(i) { + return { h: he(i.h), s: he(i.s), l: he(i.l), a: he(i.a, 3) }; +}, tr = function(i) { + return no((t = (e = i).s, { h: e.h, s: (t *= ((n = e.l) < 50 ? n : 100 - n) / 100) > 0 ? 2 * t / (n + t) * 100 : 0, v: n + t, a: e.a })); + var e, t, n; +}, rn = function(i) { + return { h: (e = to(i)).h, s: (s = (200 - (t = e.s)) * (n = e.v) / 100) > 0 && s < 200 ? t * n / 100 / (s <= 100 ? s : 200 - s) * 100 : 0, l: s / 2, a: e.a }; + var e, t, n, s; +}, su = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, ru = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, au = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, ou = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Xi = { string: [[function(i) { + var e = iu.exec(i); + return e ? (i = e[1]).length <= 4 ? { r: parseInt(i[0] + i[0], 16), g: parseInt(i[1] + i[1], 16), b: parseInt(i[2] + i[2], 16), a: i.length === 4 ? he(parseInt(i[3] + i[3], 16) / 255, 2) : 1 } : i.length === 6 || i.length === 8 ? { r: parseInt(i.substr(0, 2), 16), g: parseInt(i.substr(2, 2), 16), b: parseInt(i.substr(4, 2), 16), a: i.length === 8 ? he(parseInt(i.substr(6, 2), 16) / 255, 2) : 1 } : null : null; +}, "hex"], [function(i) { + var e = au.exec(i) || ou.exec(i); + return e ? e[2] !== e[4] || e[4] !== e[6] ? null : Qs({ r: Number(e[1]) / (e[2] ? 100 / 255 : 1), g: Number(e[3]) / (e[4] ? 100 / 255 : 1), b: Number(e[5]) / (e[6] ? 100 / 255 : 1), a: e[7] === void 0 ? 1 : Number(e[7]) / (e[8] ? 100 : 1) }) : null; +}, "rgb"], [function(i) { + var e = su.exec(i) || ru.exec(i); + if (!e) return null; + var t, n, s = Js({ h: (t = e[1], n = e[2], n === void 0 && (n = "deg"), Number(t) * (nu[n] || 1)), s: Number(e[3]), l: Number(e[4]), a: e[5] === void 0 ? 1 : Number(e[5]) / (e[6] ? 100 : 1) }); + return tr(s); +}, "hsl"]], object: [[function(i) { + var e = i.r, t = i.g, n = i.b, s = i.a, r = s === void 0 ? 1 : s; + return lt(e) && lt(t) && lt(n) ? Qs({ r: Number(e), g: Number(t), b: Number(n), a: Number(r) }) : null; +}, "rgb"], [function(i) { + var e = i.h, t = i.s, n = i.l, s = i.a, r = s === void 0 ? 1 : s; + if (!lt(e) || !lt(t) || !lt(n)) return null; + var a = Js({ h: Number(e), s: Number(t), l: Number(n), a: Number(r) }); + return tr(a); +}, "hsl"], [function(i) { + var e = i.h, t = i.s, n = i.v, s = i.a, r = s === void 0 ? 1 : s; + if (!lt(e) || !lt(t) || !lt(n)) return null; + var a = function(o) { + return { h: eo(o.h), s: Le(o.s, 0, 100), v: Le(o.v, 0, 100), a: Le(o.a) }; + }({ h: Number(e), s: Number(t), v: Number(n), a: Number(r) }); + return no(a); +}, "hsv"]] }, nr = function(i, e) { + for (var t = 0; t < e.length; t++) { + var n = e[t][0](i); + if (n) return [n, e[t][1]]; + } + return [null, void 0]; +}, lu = function(i) { + return typeof i == "string" ? nr(i.trim(), Xi.string) : typeof i == "object" && i !== null ? nr(i, Xi.object) : [null, void 0]; +}, pi = function(i, e) { + var t = rn(i); + return { h: t.h, s: Le(t.s + 100 * e, 0, 100), l: t.l, a: t.a }; +}, mi = function(i) { + return (299 * i.r + 587 * i.g + 114 * i.b) / 1e3 / 255; +}, ir = function(i, e) { + var t = rn(i); + return { h: t.h, s: t.s, l: Le(t.l + 100 * e, 0, 100), a: t.a }; +}, ji = function() { + function i(e) { + this.parsed = lu(e)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 }; + } + return i.prototype.isValid = function() { + return this.parsed !== null; + }, i.prototype.brightness = function() { + return he(mi(this.rgba), 2); + }, i.prototype.isDark = function() { + return mi(this.rgba) < 0.5; + }, i.prototype.isLight = function() { + return mi(this.rgba) >= 0.5; + }, i.prototype.toHex = function() { + return e = _i(this.rgba), t = e.r, n = e.g, s = e.b, a = (r = e.a) < 1 ? Sn(he(255 * r)) : "", "#" + Sn(t) + Sn(n) + Sn(s) + a; + var e, t, n, s, r, a; + }, i.prototype.toRgb = function() { + return _i(this.rgba); + }, i.prototype.toRgbString = function() { + return e = _i(this.rgba), t = e.r, n = e.g, s = e.b, (r = e.a) < 1 ? "rgba(" + t + ", " + n + ", " + s + ", " + r + ")" : "rgb(" + t + ", " + n + ", " + s + ")"; + var e, t, n, s, r; + }, i.prototype.toHsl = function() { + return er(rn(this.rgba)); + }, i.prototype.toHslString = function() { + return e = er(rn(this.rgba)), t = e.h, n = e.s, s = e.l, (r = e.a) < 1 ? "hsla(" + t + ", " + n + "%, " + s + "%, " + r + ")" : "hsl(" + t + ", " + n + "%, " + s + "%)"; + var e, t, n, s, r; + }, i.prototype.toHsv = function() { + return e = to(this.rgba), { h: he(e.h), s: he(e.s), v: he(e.v), a: he(e.a, 3) }; + var e; + }, i.prototype.invert = function() { + return it({ r: 255 - (e = this.rgba).r, g: 255 - e.g, b: 255 - e.b, a: e.a }); + var e; + }, i.prototype.saturate = function(e) { + return e === void 0 && (e = 0.1), it(pi(this.rgba, e)); + }, i.prototype.desaturate = function(e) { + return e === void 0 && (e = 0.1), it(pi(this.rgba, -e)); + }, i.prototype.grayscale = function() { + return it(pi(this.rgba, -1)); + }, i.prototype.lighten = function(e) { + return e === void 0 && (e = 0.1), it(ir(this.rgba, e)); + }, i.prototype.darken = function(e) { + return e === void 0 && (e = 0.1), it(ir(this.rgba, -e)); + }, i.prototype.rotate = function(e) { + return e === void 0 && (e = 15), this.hue(this.hue() + e); + }, i.prototype.alpha = function(e) { + return typeof e == "number" ? it({ r: (t = this.rgba).r, g: t.g, b: t.b, a: e }) : he(this.rgba.a, 3); + var t; + }, i.prototype.hue = function(e) { + var t = rn(this.rgba); + return typeof e == "number" ? it({ h: e, s: t.s, l: t.l, a: t.a }) : he(t.h); + }, i.prototype.isEqual = function(e) { + return this.toHex() === it(e).toHex(); + }, i; +}(), it = function(i) { + return i instanceof ji ? i : new ji(i); +}, sr = [], uu = function(i) { + i.forEach(function(e) { + sr.indexOf(e) < 0 && (e(ji, Xi), sr.push(e)); + }); +}; +function hu(i, e) { + var t = { 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" }, n = {}; + for (var s in t) n[t[s]] = s; + var r = {}; + i.prototype.toName = function(a) { + if (!(this.rgba.a || this.rgba.r || this.rgba.g || this.rgba.b)) return "transparent"; + var o, l, u = n[this.toHex()]; + if (u) return u; + if (a != null && a.closest) { + var h = this.toRgb(), c = 1 / 0, f = "black"; + if (!r.length) for (var d in t) r[d] = new i(t[d]).toRgb(); + for (var p in t) { + var b = (o = h, l = r[p], Math.pow(o.r - l.r, 2) + Math.pow(o.g - l.g, 2) + Math.pow(o.b - l.b, 2)); + b < c && (c = b, f = p); + } + return f; + } + }, e.string.push([function(a) { + var o = a.toLowerCase(), l = o === "transparent" ? "#0000" : t[o]; + return l ? new i(l).toRgb() : null; + }, "name"]); +} +uu([hu]); +const Nt = class Jt { + /** + * @param {ColorSource} value - Optional value to use, if not provided, white is used. + */ + constructor(e = 16777215) { + this._value = null, this._components = new Float32Array(4), this._components.fill(1), this._int = 16777215, this.value = e; + } + /** + * 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(e) { + return this.value = e, 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(e) { + if (e instanceof Jt) + this._value = this._cloneSource(e._value), this._int = e._int, this._components.set(e._components); + else { + if (e === null) + throw new Error("Cannot set Color#value to null"); + (this._value === null || !this._isSourceEqual(this._value, e)) && (this._value = this._cloneSource(e), this._normalize(this._value)); + } + } + get value() { + return this._value; + } + /** + * Copy a color source internally. + * @param value - Color source + */ + _cloneSource(e) { + return typeof e == "string" || typeof e == "number" || e instanceof Number || e === null ? e : Array.isArray(e) || ArrayBuffer.isView(e) ? e.slice(0) : typeof e == "object" && e !== null ? { ...e } : e; + } + /** + * 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(e, t) { + const n = typeof e; + if (n !== typeof t) + return !1; + if (n === "number" || n === "string" || e instanceof Number) + return e === t; + if (Array.isArray(e) && Array.isArray(t) || ArrayBuffer.isView(e) && ArrayBuffer.isView(t)) + return e.length !== t.length ? !1 : e.every((r, a) => r === t[a]); + if (e !== null && t !== null) { + const r = Object.keys(e), a = Object.keys(t); + return r.length !== a.length ? !1 : r.every((o) => e[o] === t[o]); + } + return e === t; + } + /** + * 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 [e, t, n, s] = this._components; + return { r: e, g: t, b: n, a: s }; + } + /** + * 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 [e, t, n] = this._components; + return { r: e, g: t, b: n }; + } + /** + * 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 [e, t, n] = this.toUint8RgbArray(); + return `rgba(${e},${t},${n},${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(e) { + const [t, n, s] = this._components; + return this._arrayRgb || (this._arrayRgb = []), e || (e = this._arrayRgb), e[0] = Math.round(t * 255), e[1] = Math.round(n * 255), e[2] = Math.round(s * 255), e; + } + /** + * 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(e) { + this._arrayRgba || (this._arrayRgba = []), e || (e = this._arrayRgba); + const [t, n, s, r] = this._components; + return e[0] = t, e[1] = n, e[2] = s, e[3] = r, e; + } + /** + * 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(e) { + this._arrayRgb || (this._arrayRgb = []), e || (e = this._arrayRgb); + const [t, n, s] = this._components; + return e[0] = t, e[1] = n, e[2] = s, e; + } + /** + * 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 [e, t, n] = this.toUint8RgbArray(); + return (n << 16) + (t << 8) + e; + } + /** + * 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 e = this._int; + return (e >> 16) + (e & 65280) + ((e & 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(e) { + const [t, n, s, r] = Jt._temp.setValue(e)._components; + return this._components[0] *= t, this._components[1] *= n, this._components[2] *= s, this._components[3] *= r, this._refreshInt(), this._value = null, 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(e, t = !0) { + return t && (this._components[0] *= e, this._components[1] *= e, this._components[2] *= e), this._components[3] = e, this._refreshInt(), this._value = null, 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(e, t = !0) { + if (e === 1) + return (255 << 24) + this._int; + if (e === 0) + return t ? 0 : this._int; + let n = this._int >> 16 & 255, s = this._int >> 8 & 255, r = this._int & 255; + return t && (n = n * e + 0.5 | 0, s = s * e + 0.5 | 0, r = r * e + 0.5 | 0), (e * 255 << 24) + (n << 16) + (s << 8) + r; + } + /** + * 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 e = this._int.toString(16); + return `#${"000000".substring(0, 6 - e.length) + e}`; + } + /** + * 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 t = Math.round(this._components[3] * 255).toString(16); + return this.toHex() + "00".substring(0, 2 - t.length) + t; + } + /** + * 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(e) { + return this._components[3] = this._clamp(e), this; + } + /** + * Normalize the input value into rgba + * @param value - Input value + */ + _normalize(e) { + let t, n, s, r; + if ((typeof e == "number" || e instanceof Number) && e >= 0 && e <= 16777215) { + const a = e; + t = (a >> 16 & 255) / 255, n = (a >> 8 & 255) / 255, s = (a & 255) / 255, r = 1; + } else if ((Array.isArray(e) || e instanceof Float32Array) && e.length >= 3 && e.length <= 4) + e = this._clamp(e), [t, n, s, r = 1] = e; + else if ((e instanceof Uint8Array || e instanceof Uint8ClampedArray) && e.length >= 3 && e.length <= 4) + e = this._clamp(e, 0, 255), [t, n, s, r = 255] = e, t /= 255, n /= 255, s /= 255, r /= 255; + else if (typeof e == "string" || typeof e == "object") { + if (typeof e == "string") { + const o = Jt.HEX_PATTERN.exec(e); + o && (e = `#${o[2]}`); + } + const a = it(e); + a.isValid() && ({ r: t, g: n, b: s, a: r } = a.rgba, t /= 255, n /= 255, s /= 255); + } + if (t !== void 0) + this._components[0] = t, this._components[1] = n, this._components[2] = s, this._components[3] = r, this._refreshInt(); + else + throw new Error(`Unable to convert color ${e}`); + } + /** Refresh the internal color rgb number */ + _refreshInt() { + this._clamp(this._components); + const [e, t, n] = this._components; + this._int = (e * 255 << 16) + (t * 255 << 8) + (n * 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(e, t = 0, n = 1) { + return typeof e == "number" ? Math.min(Math.max(e, t), n) : (e.forEach((s, r) => { + e[r] = Math.min(Math.max(s, t), n); + }), e); + } + /** + * 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(e) { + return typeof e == "number" || typeof e == "string" || e instanceof Number || e instanceof Jt || Array.isArray(e) || e instanceof Uint8Array || e instanceof Uint8ClampedArray || e instanceof Float32Array || e.r !== void 0 && e.g !== void 0 && e.b !== void 0 || e.r !== void 0 && e.g !== void 0 && e.b !== void 0 && e.a !== void 0 || e.h !== void 0 && e.s !== void 0 && e.l !== void 0 || e.h !== void 0 && e.s !== void 0 && e.l !== void 0 && e.a !== void 0 || e.h !== void 0 && e.s !== void 0 && e.v !== void 0 || e.h !== void 0 && e.s !== void 0 && e.v !== void 0 && e.a !== void 0; + } +}; +Nt.shared = new Nt(); +Nt._temp = new Nt(); +Nt.HEX_PATTERN = /^(#|0x)?(([a-f0-9]{3}){1,2}([a-f0-9]{2})?)$/i; +let qe = Nt; +const cu = { + cullArea: null, + cullable: !1, + cullableChildren: !0 +}; +let gi = 0; +const rr = 500; +function Fe(...i) { + gi !== rr && (gi++, gi === rr ? console.warn("PixiJS Warning: too many warnings, no more warnings will be reported to the console by PixiJS.") : console.warn("PixiJS Warning: ", ...i)); +} +const oi = { + /** + * 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(i) { + this._registeredResources.add(i); + }, + /** + * Unregisters a pool or cleanable object from cleanup. + * @param {Cleanable} pool - The pool or object to unregister. + */ + unregister(i) { + this._registeredResources.delete(i); + }, + /** Clears all registered pools and cleanable objects. This will call clear() on each registered item. */ + release() { + this._registeredResources.forEach((i) => i.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(i) { + return this._registeredResources.has(i); + }, + /** + * Removes all registrations without clearing the pools. + * Useful if you want to reset the collector without affecting the pools. + */ + reset() { + this._registeredResources.clear(); + } +}; +class du { + /** + * Constructs a new Pool. + * @param ClassType - The constructor of the items in the pool. + * @param {number} [initialSize] - The initial size of the pool. + */ + constructor(e, t) { + this._pool = [], this._count = 0, this._index = 0, this._classType = e, t && this.prepopulate(t); + } + /** + * Prepopulates the pool with a given number of items. + * @param total - The number of items to add to the pool. + */ + prepopulate(e) { + for (let t = 0; t < e; t++) + this._pool[this._index++] = new this._classType(); + this._count += e; + } + /** + * 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(e) { + var n; + let t; + return this._index > 0 ? t = this._pool[--this._index] : t = new this._classType(), (n = t.init) == null || n.call(t, e), t; + } + /** + * 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(e) { + var t; + (t = e.reset) == null || t.call(e), this._pool[this._index++] = e; + } + /** + * 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 e = 0; e < this._index; e++) + this._pool[e].destroy(); + this._pool.length = 0, this._count = 0, this._index = 0; + } +} +class fu { + constructor() { + 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} Class - The constructor of the items in the pool. + * @param {number} total - The number of items to add to the pool. + */ + prepopulate(e, t) { + this.getPool(e).prepopulate(t); + } + /** + * Gets an item from a specific pool. + * @template T The type of items in the pool. Must extend PoolItem. + * @param {PoolItemConstructor} 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(e, t) { + return this.getPool(e).get(t); + } + /** + * Returns an item to its respective pool. + * @param {PoolItem} item - The item to return to the pool. + */ + return(e) { + this.getPool(e.constructor).return(e); + } + /** + * Gets a specific pool based on the class type. + * @template T The type of items in the pool. Must extend PoolItem. + * @param {PoolItemConstructor} ClassType - The constructor of the items in the pool. + * @returns {Pool} The pool of the given class type. + */ + getPool(e) { + return this._poolsByClass.has(e) || this._poolsByClass.set(e, new du(e)), this._poolsByClass.get(e); + } + /** gets the usage stats of each pool in the system */ + stats() { + const e = {}; + return this._poolsByClass.forEach((t) => { + const n = e[t._classType.name] ? t._classType.name + t._classType.ID : t._classType.name; + e[n] = { + free: t.totalFree, + used: t.totalUsed, + size: t.totalSize + }; + }), e; + } + /** Clears all pools in the group. This will reset all pools and free their resources. */ + clear() { + this._poolsByClass.forEach((e) => e.clear()), this._poolsByClass.clear(); + } +} +const Ue = new fu(); +oi.register(Ue); +const _u = { + get isCachedAsTexture() { + var i; + return !!((i = this.renderGroup) != null && i.isCachedAsTexture); + }, + cacheAsTexture(i) { + typeof i == "boolean" && i === !1 ? this.disableRenderGroup() : (this.enableRenderGroup(), this.renderGroup.enableCacheAsTexture(i === !0 ? {} : i)); + }, + updateCacheTexture() { + var i; + (i = this.renderGroup) == null || i.updateCacheTexture(); + }, + get cacheAsBitmap() { + return this.isCachedAsTexture; + }, + set cacheAsBitmap(i) { + j("v8.6.0", "cacheAsBitmap is deprecated, use cacheAsTexture instead."), this.cacheAsTexture(i); + } +}; +function pu(i, e, t) { + const n = i.length; + let s; + if (e >= n || t === 0) + return; + t = e + t > n ? n - e : t; + const r = n - t; + for (s = e; s < r; ++s) + i[s] = i[s + t]; + i.length = r; +} +const mu = { + allowChildren: !0, + removeChildren(i = 0, e) { + var r; + const t = e ?? this.children.length, n = t - i, s = []; + if (n > 0 && n <= t) { + for (let o = t - 1; o >= i; o--) { + const l = this.children[o]; + l && (s.push(l), l.parent = null); + } + pu(this.children, i, t); + const a = this.renderGroup || this.parentRenderGroup; + a && a.removeChildren(s); + for (let o = 0; o < s.length; ++o) { + const l = s[o]; + (r = l.parentRenderLayer) == null || r.detach(l), this.emit("childRemoved", l, this, o), s[o].emit("removed", this); + } + return s.length > 0 && this._didViewChangeTick++, s; + } else if (n === 0 && this.children.length === 0) + return s; + throw new RangeError("removeChildren: numeric values are outside the acceptable range."); + }, + removeChildAt(i) { + const e = this.getChildAt(i); + return this.removeChild(e); + }, + getChildAt(i) { + if (i < 0 || i >= this.children.length) + throw new Error(`getChildAt: Index (${i}) does not exist.`); + return this.children[i]; + }, + setChildIndex(i, e) { + if (e < 0 || e >= this.children.length) + throw new Error(`The index ${e} supplied is out of bounds ${this.children.length}`); + this.getChildIndex(i), this.addChildAt(i, e); + }, + getChildIndex(i) { + const e = this.children.indexOf(i); + if (e === -1) + throw new Error("The supplied Container must be a child of the caller"); + return e; + }, + addChildAt(i, e) { + this.allowChildren || j(le, "addChildAt: Only Containers will be allowed to add children in v8.0.0"); + const { children: t } = this; + if (e < 0 || e > t.length) + throw new Error(`${i}addChildAt: The index ${e} supplied is out of bounds ${t.length}`); + if (i.parent) { + const s = i.parent.children.indexOf(i); + if (i.parent === this && s === e) + return i; + s !== -1 && i.parent.children.splice(s, 1); + } + e === t.length ? t.push(i) : t.splice(e, 0, i), i.parent = this, i.didChange = !0, i._updateFlags = 15; + const n = this.renderGroup || this.parentRenderGroup; + return n && n.addChild(i), this.sortableChildren && (this.sortDirty = !0), this.emit("childAdded", i, this, e), i.emit("added", this), i; + }, + swapChildren(i, e) { + if (i === e) + return; + const t = this.getChildIndex(i), n = this.getChildIndex(e); + this.children[t] = e, this.children[n] = i; + const s = this.renderGroup || this.parentRenderGroup; + s && (s.structureDidChange = !0), this._didContainerChangeTick++; + }, + removeFromParent() { + var i; + (i = this.parent) == null || i.removeChild(this); + }, + reparentChild(...i) { + return i.length === 1 ? this.reparentChildAt(i[0], this.children.length) : (i.forEach((e) => this.reparentChildAt(e, this.children.length)), i[0]); + }, + reparentChildAt(i, e) { + if (i.parent === this) + return this.setChildIndex(i, e), i; + const t = i.worldTransform.clone(); + i.removeFromParent(), this.addChildAt(i, e); + const n = this.worldTransform.clone(); + return n.invert(), t.prepend(n), i.setFromMatrix(t), i; + }, + replaceChild(i, e) { + i.updateLocalTransform(), this.addChildAt(e, this.getChildIndex(i)), e.setFromMatrix(i.localTransform), e.updateLocalTransform(), this.removeChild(i); + } +}, gu = { + collectRenderables(i, e, t) { + this.parentRenderLayer && this.parentRenderLayer !== t || this.globalDisplayStatus < 7 || !this.includeInBuild || (this.sortableChildren && this.sortChildren(), this.isSimple ? this.collectRenderablesSimple(i, e, t) : this.renderGroup ? e.renderPipes.renderGroup.addRenderGroup(this.renderGroup, i) : this.collectRenderablesWithEffects(i, e, t)); + }, + collectRenderablesSimple(i, e, t) { + const n = this.children, s = n.length; + for (let r = 0; r < s; r++) + n[r].collectRenderables(i, e, t); + }, + collectRenderablesWithEffects(i, e, t) { + const { renderPipes: n } = e; + for (let s = 0; s < this.effects.length; s++) { + const r = this.effects[s]; + n[r.pipe].push(r, this, i); + } + this.collectRenderablesSimple(i, e, t); + for (let s = this.effects.length - 1; s >= 0; s--) { + const r = this.effects[s]; + n[r.pipe].pop(r, this, i); + } + } +}; +class ar { + constructor() { + this.pipe = "filter", this.priority = 1; + } + destroy() { + for (let e = 0; e < this.filters.length; e++) + this.filters[e].destroy(); + this.filters = null, this.filterArea = null; + } +} +class yu { + constructor() { + this._effectClasses = [], this._tests = [], this._initialized = !1; + } + init() { + this._initialized || (this._initialized = !0, this._effectClasses.forEach((e) => { + this.add({ + test: e.test, + maskClass: e + }); + })); + } + add(e) { + this._tests.push(e); + } + getMaskEffect(e) { + this._initialized || this.init(); + for (let t = 0; t < this._tests.length; t++) { + const n = this._tests[t]; + if (n.test(e)) + return Ue.get(n.maskClass, e); + } + return e; + } + returnMaskEffect(e) { + Ue.return(e); + } +} +const Wi = new yu(); +Ve.handleByList(X.MaskEffect, Wi._effectClasses); +const bu = { + _maskEffect: null, + _maskOptions: { + inverse: !1 + }, + _filterEffect: null, + effects: [], + _markStructureAsChanged() { + const i = this.renderGroup || this.parentRenderGroup; + i && (i.structureDidChange = !0); + }, + addEffect(i) { + this.effects.indexOf(i) === -1 && (this.effects.push(i), this.effects.sort((t, n) => t.priority - n.priority), this._markStructureAsChanged(), this._updateIsSimple()); + }, + removeEffect(i) { + const e = this.effects.indexOf(i); + e !== -1 && (this.effects.splice(e, 1), this._markStructureAsChanged(), this._updateIsSimple()); + }, + set mask(i) { + const e = this._maskEffect; + (e == null ? void 0 : e.mask) !== i && (e && (this.removeEffect(e), Wi.returnMaskEffect(e), this._maskEffect = null), i != null && (this._maskEffect = Wi.getMaskEffect(i), this.addEffect(this._maskEffect))); + }, + get mask() { + var i; + return (i = this._maskEffect) == null ? void 0 : i.mask; + }, + setMask(i) { + this._maskOptions = { + ...this._maskOptions, + ...i + }, i.mask && (this.mask = i.mask), this._markStructureAsChanged(); + }, + set filters(i) { + var r; + !Array.isArray(i) && i && (i = [i]); + const e = this._filterEffect || (this._filterEffect = new ar()); + i = i; + const t = (i == null ? void 0 : i.length) > 0, n = ((r = e.filters) == null ? void 0 : r.length) > 0, s = t !== n; + i = Array.isArray(i) ? i.slice(0) : i, e.filters = Object.freeze(i), s && (t ? this.addEffect(e) : (this.removeEffect(e), e.filters = i ?? null)); + }, + get filters() { + var i; + return (i = this._filterEffect) == null ? void 0 : i.filters; + }, + set filterArea(i) { + this._filterEffect || (this._filterEffect = new ar()), this._filterEffect.filterArea = i; + }, + get filterArea() { + var i; + return (i = this._filterEffect) == null ? void 0 : i.filterArea; + } +}, xu = { + label: null, + get name() { + return j(le, "Container.name property has been removed, use Container.label instead"), this.label; + }, + set name(i) { + j(le, "Container.name property has been removed, use Container.label instead"), this.label = i; + }, + getChildByName(i, e = !1) { + return this.getChildByLabel(i, e); + }, + getChildByLabel(i, e = !1) { + const t = this.children; + for (let n = 0; n < t.length; n++) { + const s = t[n]; + if (s.label === i || i instanceof RegExp && i.test(s.label)) + return s; + } + if (e) + for (let n = 0; n < t.length; n++) { + const r = t[n].getChildByLabel(i, !0); + if (r) + return r; + } + return null; + }, + getChildrenByLabel(i, e = !1, t = []) { + const n = this.children; + for (let s = 0; s < n.length; s++) { + const r = n[s]; + (r.label === i || i instanceof RegExp && i.test(r.label)) && t.push(r); + } + if (e) + for (let s = 0; s < n.length; s++) + n[s].getChildrenByLabel(i, !0, t); + return t; + } +}, be = Ue.getPool(q), ht = Ue.getPool(Je), vu = new q(), wu = { + getFastGlobalBounds(i, e) { + e || (e = new Je()), e.clear(), this._getGlobalBoundsRecursive(!!i, e, this.parentRenderLayer), e.isValid || e.set(0, 0, 0, 0); + const t = this.renderGroup || this.parentRenderGroup; + return e.applyMatrix(t.worldTransform), e; + }, + _getGlobalBoundsRecursive(i, e, t) { + let n = e; + if (i && this.parentRenderLayer && this.parentRenderLayer !== t || this.localDisplayStatus !== 7 || !this.measurable) + return; + const s = !!this.effects.length; + if ((this.renderGroup || s) && (n = ht.get().clear()), this.boundsArea) + e.addRect(this.boundsArea, this.worldTransform); + else { + if (this.renderPipeId) { + const a = this.bounds; + n.addFrame( + a.minX, + a.minY, + a.maxX, + a.maxY, + this.groupTransform + ); + } + const r = this.children; + for (let a = 0; a < r.length; a++) + r[a]._getGlobalBoundsRecursive(i, n, t); + } + if (s) { + let r = !1; + const a = this.renderGroup || this.parentRenderGroup; + for (let o = 0; o < this.effects.length; o++) + this.effects[o].addBounds && (r || (r = !0, n.applyMatrix(a.worldTransform)), this.effects[o].addBounds(n, !0)); + r && n.applyMatrix(a.worldTransform.copyTo(vu).invert()), e.addBounds(n), ht.return(n); + } else this.renderGroup && (e.addBounds(n, this.relativeGroupTransform), ht.return(n)); + } +}; +function io(i, e, t) { + t.clear(); + let n, s; + return i.parent ? e ? n = i.parent.worldTransform : (s = be.get().identity(), n = Cs(i, s)) : n = q.IDENTITY, so(i, t, n, e), s && be.return(s), t.isValid || t.set(0, 0, 0, 0), t; +} +function so(i, e, t, n) { + var o, l; + if (!i.visible || !i.measurable) + return; + let s; + n ? s = i.worldTransform : (i.updateLocalTransform(), s = be.get(), s.appendFrom(i.localTransform, t)); + const r = e, a = !!i.effects.length; + if (a && (e = ht.get().clear()), i.boundsArea) + e.addRect(i.boundsArea, s); + else { + const u = i.bounds; + u && !u.isEmpty() && (e.matrix = s, e.addBounds(u)); + for (let h = 0; h < i.children.length; h++) + so(i.children[h], e, s, n); + } + if (a) { + for (let u = 0; u < i.effects.length; u++) + (l = (o = i.effects[u]).addBounds) == null || l.call(o, e); + r.addBounds(e, q.IDENTITY), ht.return(e); + } + n || be.return(s); +} +function Cs(i, e) { + const t = i.parent; + return t && (Cs(t, e), t.updateLocalTransform(), e.append(t.localTransform)), e; +} +function ro(i, e) { + if (i === 16777215 || !e) + return e; + if (e === 16777215 || !i) + return i; + const t = i >> 16 & 255, n = i >> 8 & 255, s = i & 255, r = e >> 16 & 255, a = e >> 8 & 255, o = e & 255, l = t * r / 255 | 0, u = n * a / 255 | 0, h = s * o / 255 | 0; + return (l << 16) + (u << 8) + h; +} +const or = 16777215; +function lr(i, e) { + return i === or ? e : e === or ? i : ro(i, e); +} +function jn(i) { + return ((i & 255) << 16) + (i & 65280) + (i >> 16 & 255); +} +const Cu = { + getGlobalAlpha(i) { + if (i) + return this.renderGroup ? this.renderGroup.worldAlpha : this.parentRenderGroup ? this.parentRenderGroup.worldAlpha * this.alpha : this.alpha; + let e = this.alpha, t = this.parent; + for (; t; ) + e *= t.alpha, t = t.parent; + return e; + }, + getGlobalTransform(i = new q(), e) { + if (e) + return i.copyFrom(this.worldTransform); + this.updateLocalTransform(); + const t = Cs(this, be.get().identity()); + return i.appendFrom(this.localTransform, t), be.return(t), i; + }, + getGlobalTint(i) { + if (i) + return this.renderGroup ? jn(this.renderGroup.worldColor) : this.parentRenderGroup ? jn( + lr(this.localColor, this.parentRenderGroup.worldColor) + ) : this.tint; + let e = this.localColor, t = this.parent; + for (; t; ) + e = lr(e, t.localColor), t = t.parent; + return jn(e); + } +}; +function ao(i, e, t) { + return e.clear(), t || (t = q.IDENTITY), oo(i, e, t, i, !0), e.isValid || e.set(0, 0, 0, 0), e; +} +function oo(i, e, t, n, s) { + var l, u; + let r; + if (s) + r = be.get(), r = t.copyTo(r); + else { + if (!i.visible || !i.measurable) + return; + i.updateLocalTransform(); + const h = i.localTransform; + r = be.get(), r.appendFrom(h, t); + } + const a = e, o = !!i.effects.length; + if (o && (e = ht.get().clear()), i.boundsArea) + e.addRect(i.boundsArea, r); + else { + i.renderPipeId && (e.matrix = r, e.addBounds(i.bounds)); + const h = i.children; + for (let c = 0; c < h.length; c++) + oo(h[c], e, r, n, !1); + } + if (o) { + for (let h = 0; h < i.effects.length; h++) + (u = (l = i.effects[h]).addLocalBounds) == null || u.call(l, e, n); + a.addBounds(e, q.IDENTITY), ht.return(e); + } + be.return(r); +} +function lo(i, e) { + const t = i.children; + for (let n = 0; n < t.length; n++) { + const s = t[n], r = s.uid, a = (s._didViewChangeTick & 65535) << 16 | s._didContainerChangeTick & 65535, o = e.index; + (e.data[o] !== r || e.data[o + 1] !== a) && (e.data[e.index] = r, e.data[e.index + 1] = a, e.didChange = !0), e.index = o + 2, s.children.length && lo(s, e); + } + return e.didChange; +} +const Au = new q(), ku = { + _localBoundsCacheId: -1, + _localBoundsCacheData: null, + _setWidth(i, e) { + const t = Math.sign(this.scale.x) || 1; + e !== 0 ? this.scale.x = i / e * t : this.scale.x = t; + }, + _setHeight(i, e) { + const t = Math.sign(this.scale.y) || 1; + e !== 0 ? this.scale.y = i / e * t : this.scale.y = t; + }, + getLocalBounds() { + this._localBoundsCacheData || (this._localBoundsCacheData = { + data: [], + index: 1, + didChange: !1, + localBounds: new Je() + }); + const i = this._localBoundsCacheData; + return i.index = 1, i.didChange = !1, i.data[0] !== this._didViewChangeTick && (i.didChange = !0, i.data[0] = this._didViewChangeTick), lo(this, i), i.didChange && ao(this, i.localBounds, Au), i.localBounds; + }, + getBounds(i, e) { + return io(this, i, e || new Je()); + } +}, Du = { + _onRender: null, + set onRender(i) { + const e = this.renderGroup || this.parentRenderGroup; + if (!i) { + this._onRender && (e == null || e.removeOnRender(this)), this._onRender = null; + return; + } + this._onRender || e == null || e.addOnRender(this), this._onRender = i; + }, + get onRender() { + return this._onRender; + } +}, Su = { + _zIndex: 0, + sortDirty: !1, + sortableChildren: !1, + get zIndex() { + return this._zIndex; + }, + set zIndex(i) { + this._zIndex !== i && (this._zIndex = i, this.depthOfChildModified()); + }, + depthOfChildModified() { + this.parent && (this.parent.sortableChildren = !0, this.parent.sortDirty = !0), this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0); + }, + sortChildren() { + this.sortDirty && (this.sortDirty = !1, this.children.sort(Eu)); + } +}; +function Eu(i, e) { + return i._zIndex - e._zIndex; +} +const Fu = { + getGlobalPosition(i = new ge(), e = !1) { + return this.parent ? this.parent.toGlobal(this._position, i, e) : (i.x = this._position.x, i.y = this._position.y), i; + }, + toGlobal(i, e, t = !1) { + const n = this.getGlobalTransform(be.get(), t); + return e = n.apply(i, e), be.return(n), e; + }, + toLocal(i, e, t, n) { + e && (i = e.toGlobal(i, t, n)); + const s = this.getGlobalTransform(be.get(), n); + return t = s.applyInverse(i, t), be.return(s), t; + } +}; +class uo { + constructor() { + this.uid = re("instructionSet"), this.instructions = [], this.instructionSize = 0, this.renderables = [], 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(e) { + this.instructions[this.instructionSize++] = e; + } + /** + * Log the instructions to the console (for debugging) + * @internal + */ + log() { + this.instructions.length = this.instructionSize, console.table(this.instructions, ["type", "action"]); + } +} +let $u = 0; +class Tu { + /** + * @param textureOptions - options that will be passed to BaseRenderTexture constructor + * @param {SCALE_MODE} [textureOptions.scaleMode] - See {@link SCALE_MODE} for possible values. + */ + constructor(e) { + this._poolKeyHash = /* @__PURE__ */ Object.create(null), this._texturePool = {}, this.textureOptions = e || {}, this.enableFullScreen = !1, this.textureStyle = new Ka(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(e, t, n) { + const s = new et({ + ...this.textureOptions, + width: e, + height: t, + resolution: 1, + antialias: n, + autoGarbageCollect: !1 + }); + return new W({ + source: s, + label: `texturePool_${$u++}` + }); + } + /** + * 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(e, t, n = 1, s) { + let r = Math.ceil(e * n - 1e-6), a = Math.ceil(t * n - 1e-6); + r = Xs(r), a = Xs(a); + const o = (r << 17) + (a << 1) + (s ? 1 : 0); + this._texturePool[o] || (this._texturePool[o] = []); + let l = this._texturePool[o].pop(); + return l || (l = this.createTexture(r, a, s)), l.source._resolution = n, l.source.width = r / n, l.source.height = a / n, l.source.pixelWidth = r, l.source.pixelHeight = a, l.frame.x = 0, l.frame.y = 0, l.frame.width = e, l.frame.height = t, l.updateUvs(), this._poolKeyHash[l.uid] = o, l; + } + /** + * 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(e, t = !1) { + const n = e.source; + return this.getOptimalTexture(e.width, e.height, n._resolution, t); + } + /** + * 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(e, t = !1) { + const n = this._poolKeyHash[e.uid]; + t && (e.source.style = this.textureStyle), this._texturePool[n].push(e); + } + /** + * Clears the pool. + * @param destroyTextures - Destroy all stored textures. + */ + clear(e) { + if (e = e !== !1, e) + for (const t in this._texturePool) { + const n = this._texturePool[t]; + if (n) + for (let s = 0; s < n.length; s++) + n[s].destroy(!0); + } + this._texturePool = {}; + } +} +const ho = new Tu(); +oi.register(ho); +class Mu { + constructor() { + this.renderPipeId = "renderGroup", this.root = null, this.canBundle = !1, this.renderGroupParent = null, this.renderGroupChildren = [], this.worldTransform = new q(), this.worldColorAlpha = 4294967295, this.worldColor = 16777215, this.worldAlpha = 1, this.childrenToUpdate = /* @__PURE__ */ Object.create(null), this.updateTick = 0, this.gcTick = 0, this.childrenRenderablesToUpdate = { list: [], index: 0 }, this.structureDidChange = !0, this.instructionSet = new uo(), this._onRenderContainers = [], this.textureNeedsUpdate = !0, this.isCachedAsTexture = !1, this._matrixDirty = 7; + } + init(e) { + this.root = e, e._onRender && this.addOnRender(e), e.didChange = !0; + const t = e.children; + for (let n = 0; n < t.length; n++) { + const s = t[n]; + s._updateFlags = 15, this.addChild(s); + } + } + enableCacheAsTexture(e = {}) { + this.textureOptions = e, this.isCachedAsTexture = !0, this.textureNeedsUpdate = !0; + } + disableCacheAsTexture() { + this.isCachedAsTexture = !1, this.texture && (ho.returnTexture(this.texture, !0), this.texture = null); + } + updateCacheTexture() { + this.textureNeedsUpdate = !0; + const e = this._parentCacheAsTextureRenderGroup; + e && !e.textureNeedsUpdate && e.updateCacheTexture(); + } + reset() { + this.renderGroupChildren.length = 0; + for (const e in this.childrenToUpdate) { + const t = this.childrenToUpdate[e]; + t.list.fill(null), t.index = 0; + } + this.childrenRenderablesToUpdate.index = 0, this.childrenRenderablesToUpdate.list.fill(null), this.root = null, this.updateTick = 0, this.structureDidChange = !0, this._onRenderContainers.length = 0, this.renderGroupParent = null, this.disableCacheAsTexture(); + } + get localTransform() { + return this.root.localTransform; + } + addRenderGroupChild(e) { + e.renderGroupParent && e.renderGroupParent._removeRenderGroupChild(e), e.renderGroupParent = this, this.renderGroupChildren.push(e); + } + _removeRenderGroupChild(e) { + const t = this.renderGroupChildren.indexOf(e); + t > -1 && this.renderGroupChildren.splice(t, 1), e.renderGroupParent = null; + } + addChild(e) { + if (this.structureDidChange = !0, e.parentRenderGroup = this, e.updateTick = -1, e.parent === this.root ? e.relativeRenderGroupDepth = 1 : e.relativeRenderGroupDepth = e.parent.relativeRenderGroupDepth + 1, e.didChange = !0, this.onChildUpdate(e), e.renderGroup) { + this.addRenderGroupChild(e.renderGroup); + return; + } + e._onRender && this.addOnRender(e); + const t = e.children; + for (let n = 0; n < t.length; n++) + this.addChild(t[n]); + } + removeChild(e) { + if (this.structureDidChange = !0, e._onRender && (e.renderGroup || this.removeOnRender(e)), e.parentRenderGroup = null, e.renderGroup) { + this._removeRenderGroupChild(e.renderGroup); + return; + } + const t = e.children; + for (let n = 0; n < t.length; n++) + this.removeChild(t[n]); + } + removeChildren(e) { + for (let t = 0; t < e.length; t++) + this.removeChild(e[t]); + } + onChildUpdate(e) { + let t = this.childrenToUpdate[e.relativeRenderGroupDepth]; + t || (t = this.childrenToUpdate[e.relativeRenderGroupDepth] = { + index: 0, + list: [] + }), t.list[t.index++] = e; + } + updateRenderable(e) { + e.globalDisplayStatus < 7 || (this.instructionSet.renderPipes[e.renderPipeId].updateRenderable(e), e.didViewUpdate = !1); + } + onChildViewUpdate(e) { + this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = e; + } + 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(e) { + this._onRenderContainers.push(e); + } + removeOnRender(e) { + this._onRenderContainers.splice(this._onRenderContainers.indexOf(e), 1); + } + runOnRender(e) { + for (let t = 0; t < this._onRenderContainers.length; t++) + this._onRenderContainers[t]._onRender(e); + } + 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(e = []) { + const t = this.root.children; + for (let n = 0; n < t.length; n++) + this._getChildren(t[n], e); + return e; + } + _getChildren(e, t = []) { + if (t.push(e), e.renderGroup) + return t; + const n = e.children; + for (let s = 0; s < n.length; s++) + this._getChildren(n[s], t); + return t; + } + invalidateMatrices() { + this._matrixDirty = 7; + } + /** + * Returns the inverse of the world transform matrix. + * @returns {Matrix} The inverse of the world transform matrix. + */ + get inverseWorldTransform() { + return this._matrixDirty & 1 ? (this._matrixDirty &= -2, this._inverseWorldTransform || (this._inverseWorldTransform = new q()), this._inverseWorldTransform.copyFrom(this.worldTransform).invert()) : this._inverseWorldTransform; + } + /** + * Returns the inverse of the texture offset transform matrix. + * @returns {Matrix} The inverse of the texture offset transform matrix. + */ + get textureOffsetInverseTransform() { + return this._matrixDirty & 2 ? (this._matrixDirty &= -3, this._textureOffsetInverseTransform || (this._textureOffsetInverseTransform = new q()), this._textureOffsetInverseTransform.copyFrom(this.inverseWorldTransform).translate( + -this._textureBounds.x, + -this._textureBounds.y + )) : this._textureOffsetInverseTransform; + } + /** + * 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)) + return this._inverseParentTextureTransform; + this._matrixDirty &= -5; + const e = this._parentCacheAsTextureRenderGroup; + return e ? (this._inverseParentTextureTransform || (this._inverseParentTextureTransform = new q()), this._inverseParentTextureTransform.copyFrom(this.worldTransform).prepend(e.inverseWorldTransform).translate( + -e._textureBounds.x, + -e._textureBounds.y + )) : 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() { + return this.isCachedAsTexture ? this.textureOffsetInverseTransform : this._parentCacheAsTextureRenderGroup ? this._parentCacheAsTextureRenderGroup.textureOffsetInverseTransform : null; + } +} +function Pu(i, e, t = {}) { + for (const n in e) + !t[n] && e[n] !== void 0 && (i[n] = e[n]); +} +const yi = new me(null), En = new me(null), bi = new me(null, 1, 1), Fn = new me(null), ur = 1, Iu = 2, xi = 4; +class Dt extends dt { + constructor(e = {}) { + var t, n; + super(), this.uid = re("renderable"), this._updateFlags = 15, this.renderGroup = null, this.parentRenderGroup = null, this.parentRenderGroupIndex = 0, this.didChange = !1, this.didViewUpdate = !1, this.relativeRenderGroupDepth = 0, this.children = [], this.parent = null, this.includeInBuild = !0, this.measurable = !0, this.isSimple = !0, this.updateTick = -1, this.localTransform = new q(), this.relativeGroupTransform = new q(), this.groupTransform = this.relativeGroupTransform, this.destroyed = !1, this._position = new me(this, 0, 0), this._scale = bi, this._pivot = En, this._origin = Fn, this._skew = yi, this._cx = 1, this._sx = 0, this._cy = 0, this._sy = 1, this._rotation = 0, this.localColor = 16777215, this.localAlpha = 1, this.groupAlpha = 1, this.groupColor = 16777215, this.groupColorAlpha = 4294967295, this.localBlendMode = "inherit", this.groupBlendMode = "normal", this.localDisplayStatus = 7, this.globalDisplayStatus = 7, this._didContainerChangeTick = 0, this._didViewChangeTick = 0, this._didLocalTransformChangeId = -1, this.effects = [], Pu(this, e, { + children: !0, + parent: !0, + effects: !0 + }), (t = e.children) == null || t.forEach((s) => this.addChild(s)), (n = e.parent) == null || n.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(e) { + j("8.8.0", "Container.mixin is deprecated, please use extensions.mixin instead."), Ve.mixin(Dt, e); + } + // = 'default'; + /** + * We now use the _didContainerChangeTick and _didViewChangeTick to track changes + * @deprecated since 8.2.6 + * @ignore + */ + set _didChangeId(e) { + this._didViewChangeTick = e >> 12 & 4095, this._didContainerChangeTick = e & 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(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(...e) { + if (this.allowChildren || j(le, "addChild: Only Containers will be allowed to add children in v8.0.0"), e.length > 1) { + for (let s = 0; s < e.length; s++) + this.addChild(e[s]); + return e[0]; + } + const t = e[0], n = this.renderGroup || this.parentRenderGroup; + return t.parent === this ? (this.children.splice(this.children.indexOf(t), 1), this.children.push(t), n && (n.structureDidChange = !0), t) : (t.parent && t.parent.removeChild(t), this.children.push(t), this.sortableChildren && (this.sortDirty = !0), t.parent = this, t.didChange = !0, t._updateFlags = 15, n && n.addChild(t), this.emit("childAdded", t, this, this.children.length - 1), t.emit("added", this), this._didViewChangeTick++, t._zIndex !== 0 && t.depthOfChildModified(), t); + } + /** + * 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(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(...e) { + if (e.length > 1) { + for (let s = 0; s < e.length; s++) + this.removeChild(e[s]); + return e[0]; + } + const t = e[0], n = this.children.indexOf(t); + return n > -1 && (this._didViewChangeTick++, this.children.splice(n, 1), this.renderGroup ? this.renderGroup.removeChild(t) : this.parentRenderGroup && this.parentRenderGroup.removeChild(t), t.parentRenderLayer && t.parentRenderLayer.detach(t), t.parent = null, this.emit("childRemoved", t, this, n), t.emit("removed", this)), t; + } + /** @ignore */ + _onUpdate(e) { + e && e === this._skew && this._updateSkew(), this._didContainerChangeTick++, !this.didChange && (this.didChange = !0, this.parentRenderGroup && this.parentRenderGroup.onChildUpdate(this)); + } + set isRenderGroup(e) { + !!this.renderGroup !== e && (e ? this.enableRenderGroup() : 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 e = this.parentRenderGroup; + e == null || e.removeChild(this), this.renderGroup = Ue.get(Mu, this), this.groupTransform = q.IDENTITY, e == null || e.addChild(this), this._updateIsSimple(); + } + /** + * This will disable the render group for this container. + * @advanced + */ + disableRenderGroup() { + if (!this.renderGroup) + return; + const e = this.parentRenderGroup; + e == null || e.removeChild(this), Ue.return(this.renderGroup), this.renderGroup = null, this.groupTransform = this.relativeGroupTransform, e == null || e.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() { + return this._worldTransform || (this._worldTransform = new q()), this.renderGroup ? this._worldTransform.copyFrom(this.renderGroup.worldTransform) : this.parentRenderGroup && this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform), 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(e) { + this._position.x = e; + } + /** + * 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(e) { + this._position.y = e; + } + /** + * 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(e) { + this._position.copyFrom(e); + } + /** + * 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(e) { + this._rotation !== e && (this._rotation = e, 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 * Xl; + } + set angle(e) { + this.rotation = e * jl; + } + /** + * 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() { + return this._pivot === En && (this._pivot = new me(this, 0, 0)), this._pivot; + } + set pivot(e) { + this._pivot === En && (this._pivot = new me(this, 0, 0), this._origin !== Fn && Fe("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof e == "number" ? this._pivot.set(e) : this._pivot.copyFrom(e); + } + /** + * 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() { + return this._skew === yi && (this._skew = new me(this, 0, 0)), this._skew; + } + set skew(e) { + this._skew === yi && (this._skew = new me(this, 0, 0)), this._skew.copyFrom(e); + } + /** + * 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() { + return this._scale === bi && (this._scale = new me(this, 1, 1)), this._scale; + } + set scale(e) { + this._scale === bi && (this._scale = new me(this, 0, 0)), typeof e == "string" && (e = parseFloat(e)), typeof e == "number" ? this._scale.set(e) : this._scale.copyFrom(e); + } + /** + * @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() { + return this._origin === Fn && (this._origin = new me(this, 0, 0)), this._origin; + } + set origin(e) { + this._origin === Fn && (this._origin = new me(this, 0, 0), this._pivot !== En && Fe("Setting both a pivot and origin on a Container is not recommended. This can lead to unexpected behavior if not handled carefully.")), typeof e == "number" ? this._origin.set(e) : this._origin.copyFrom(e); + } + /** + * 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(e) { + const t = this.getLocalBounds().width; + this._setWidth(e, t); + } + /** + * 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(e) { + const t = this.getLocalBounds().height; + this._setHeight(e, t); + } + /** + * 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(e) { + e || (e = {}); + const t = this.getLocalBounds(); + return e.width = Math.abs(this.scale.x * t.width), e.height = Math.abs(this.scale.y * t.height), e; + } + /** + * 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(e, t) { + const n = this.getLocalBounds(); + typeof e == "object" ? (t = e.height ?? e.width, e = e.width) : t ?? (t = e), e !== void 0 && this._setWidth(e, n.width), t !== void 0 && this._setHeight(t, n.height); + } + /** Called when the skew or the rotation changes. */ + _updateSkew() { + const e = this._rotation, t = this._skew; + this._cx = Math.cos(e + t._y), this._sx = Math.sin(e + t._y), this._cy = -Math.sin(e - t._x), this._sy = Math.cos(e - t._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(e) { + return this.position.set( + typeof e.x == "number" ? e.x : this.position.x, + typeof e.y == "number" ? e.y : this.position.y + ), this.scale.set( + typeof e.scaleX == "number" ? e.scaleX || 1 : this.scale.x, + typeof e.scaleY == "number" ? e.scaleY || 1 : this.scale.y + ), this.rotation = typeof e.rotation == "number" ? e.rotation : this.rotation, this.skew.set( + typeof e.skewX == "number" ? e.skewX : this.skew.x, + typeof e.skewY == "number" ? e.skewY : this.skew.y + ), this.pivot.set( + typeof e.pivotX == "number" ? e.pivotX : this.pivot.x, + typeof e.pivotY == "number" ? e.pivotY : this.pivot.y + ), this.origin.set( + typeof e.originX == "number" ? e.originX : this.origin.x, + typeof e.originY == "number" ? e.originY : this.origin.y + ), 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(e) { + e.decompose(this); + } + /** Updates the local transform. */ + updateLocalTransform() { + const e = this._didContainerChangeTick; + if (this._didLocalTransformChangeId === e) + return; + this._didLocalTransformChangeId = e; + const t = this.localTransform, n = this._scale, s = this._pivot, r = this._origin, a = this._position, o = n._x, l = n._y, u = s._x, h = s._y, c = -r._x, f = -r._y; + t.a = this._cx * o, t.b = this._sx * o, t.c = this._cy * l, t.d = this._sy * l, t.tx = a._x - (u * t.a + h * t.c) + (c * t.a + f * t.c) - c, t.ty = a._y - (u * t.b + h * t.d) + (c * t.b + f * t.d) - f; + } + // / ///// color related stuff + set alpha(e) { + e !== this.localAlpha && (this.localAlpha = e, this._updateFlags |= ur, 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(e) { + const n = qe.shared.setValue(e ?? 16777215).toBgrNumber(); + n !== this.localColor && (this.localColor = n, this._updateFlags |= ur, 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 jn(this.localColor); + } + // / //////////////// blend related stuff + set blendMode(e) { + this.localBlendMode !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= Iu, this.localBlendMode = e, 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(e) { + const t = e ? 2 : 0; + (this.localDisplayStatus & 2) !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= xi, this.localDisplayStatus ^= 2, this._onUpdate()); + } + /** @ignore */ + get culled() { + return !(this.localDisplayStatus & 4); + } + /** @ignore */ + set culled(e) { + const t = e ? 0 : 4; + (this.localDisplayStatus & 4) !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= xi, 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(e) { + const t = e ? 1 : 0; + (this.localDisplayStatus & 1) !== t && (this._updateFlags |= xi, this.localDisplayStatus ^= 1, this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), 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(e = !1) { + var s; + if (this.destroyed) + return; + this.destroyed = !0; + let t; + if (this.children.length && (t = 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(), (typeof e == "boolean" ? e : e == null ? void 0 : e.children) && t) + for (let r = 0; r < t.length; ++r) + t[r].destroy(e); + (s = this.renderGroup) == null || s.destroy(), this.renderGroup = null; + } +} +Ve.mixin( + Dt, + mu, + wu, + Fu, + Du, + ku, + bu, + xu, + Su, + cu, + _u, + Cu, + gu +); +class co extends Dt { + // eslint-disable-next-line @typescript-eslint/no-useless-constructor + constructor(e) { + super(e), this.canBundle = !0, this.allowChildren = !1, this._roundPixels = 0, this._lastUsed = -1, this._gpuData = /* @__PURE__ */ Object.create(null), this._bounds = new Je(0, 1, 0, 0), this._boundsDirty = !0; + } + /** + * 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() { + return this._boundsDirty ? (this.updateBounds(), this._boundsDirty = !1, this._bounds) : 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(e) { + this._roundPixels = e ? 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(e) { + const t = this.bounds, { x: n, y: s } = e; + return n >= t.minX && n <= t.maxX && s >= t.minY && s <= t.maxY; + } + /** @private */ + onViewUpdate() { + if (this._didViewChangeTick++, this._boundsDirty = !0, this.didViewUpdate) + return; + this.didViewUpdate = !0; + const e = this.renderGroup || this.parentRenderGroup; + e && e.onChildViewUpdate(this); + } + destroy(e) { + var t, n; + super.destroy(e), this._bounds = null; + for (const s in this._gpuData) + (n = (t = this._gpuData[s]).destroy) == null || n.call(t); + this._gpuData = 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(e, t, n) { + const { renderPipes: s } = t; + s.blendMode.pushBlendMode(this, this.groupBlendMode, e), s[this.renderPipeId].addRenderable(this, e), this.didViewUpdate = !1; + const a = this.children, o = a.length; + for (let l = 0; l < o; l++) + a[l].collectRenderables(e, t, n); + s.blendMode.popBlendMode(e); + } +} +class Ot extends co { + /** + * @param options - The options for creating the sprite. + */ + constructor(e = W.EMPTY) { + e instanceof W && (e = { texture: e }); + const { texture: t = W.EMPTY, anchor: n, roundPixels: s, width: r, height: a, ...o } = e; + super({ + label: "Sprite", + ...o + }), this.renderPipeId = "sprite", this.batched = !0, this._visualBounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 }, this._anchor = new me( + { + _onUpdate: () => { + this.onViewUpdate(); + } + } + ), n ? this.anchor = n : t.defaultAnchor && (this.anchor = t.defaultAnchor), this.texture = t, this.allowChildren = !1, this.roundPixels = s ?? !1, r !== void 0 && (this.width = r), a !== void 0 && (this.height = a); + } + /** + * 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(e, t = !1) { + return e instanceof W ? new Ot(e) : new Ot(W.from(e, t)); + } + set texture(e) { + e || (e = W.EMPTY); + const t = this._texture; + t !== e && (t && t.dynamic && t.off("update", this.onViewUpdate, this), e.dynamic && e.on("update", this.onViewUpdate, this), this._texture = e, this._width && this._setWidth(this._width, this._texture.orig.width), 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() { + return tu(this._visualBounds, this._anchor, this._texture), this._visualBounds; + } + /** + * @deprecated + * @ignore + */ + get sourceBounds() { + return j("8.6.1", "Sprite.sourceBounds is deprecated, use visualBounds instead."), this.visualBounds; + } + /** @private */ + updateBounds() { + const e = this._anchor, t = this._texture, n = this._bounds, { width: s, height: r } = t.orig; + n.minX = -e._x * s, n.maxX = n.minX + s, n.minY = -e._y * r, n.maxY = n.minY + r; + } + /** + * 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(e = !1) { + if (super.destroy(e), typeof e == "boolean" ? e : e == null ? void 0 : e.texture) { + const n = typeof e == "boolean" ? e : e == null ? void 0 : e.textureSource; + this._texture.destroy(n); + } + this._texture = null, this._visualBounds = null, this._bounds = null, this._anchor = null, this._gpuData = 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(e) { + typeof e == "number" ? this._anchor.set(e) : this._anchor.copyFrom(e); + } + /** + * 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(e) { + this._setWidth(e, this._texture.orig.width), this._width = e; + } + /** + * 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(e) { + this._setHeight(e, this._texture.orig.height), this._height = e; + } + /** + * 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(e) { + return e || (e = {}), e.width = Math.abs(this.scale.x) * this._texture.orig.width, e.height = Math.abs(this.scale.y) * this._texture.orig.height, e; + } + /** + * 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(e, t) { + typeof e == "object" ? (t = e.height ?? e.width, e = e.width) : t ?? (t = e), e !== void 0 && this._setWidth(e, this._texture.orig.width), t !== void 0 && this._setHeight(t, this._texture.orig.height); + } +} +const Ru = new Je(); +function fo(i, e, t) { + const n = Ru; + i.measurable = !0, io(i, t, n), e.addBoundsMask(n), i.measurable = !1; +} +function _o(i, e, t) { + const n = ht.get(); + i.measurable = !0; + const s = be.get().identity(), r = po(i, t, s); + ao(i, n, r), i.measurable = !1, e.addBoundsMask(n), be.return(s), ht.return(n); +} +function po(i, e, t) { + return i ? (i !== e && (po(i.parent, e, t), i.updateLocalTransform(), t.append(i.localTransform)), t) : (Fe("Mask bounds, renderable is not inside the root container"), t); +} +class mo { + constructor(e) { + this.priority = 0, this.inverse = !1, this.pipe = "alphaMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e, this.renderMaskToTexture = !(e instanceof Ot), this.mask.renderable = this.renderMaskToTexture, this.mask.includeInBuild = !this.renderMaskToTexture, this.mask.measurable = !1; + } + reset() { + this.mask.measurable = !0, this.mask = null; + } + addBounds(e, t) { + this.inverse || fo(this.mask, e, t); + } + addLocalBounds(e, t) { + _o(this.mask, e, t); + } + containsPoint(e, t) { + const n = this.mask; + return t(n, e); + } + destroy() { + this.reset(); + } + static test(e) { + return e instanceof Ot; + } +} +mo.extension = X.MaskEffect; +class go { + constructor(e) { + this.priority = 0, this.pipe = "colorMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e; + } + destroy() { + } + static test(e) { + return typeof e == "number"; + } +} +go.extension = X.MaskEffect; +class yo { + constructor(e) { + this.priority = 0, this.pipe = "stencilMask", e != null && e.mask && this.init(e.mask); + } + init(e) { + this.mask = e, this.mask.includeInBuild = !1, this.mask.measurable = !1; + } + reset() { + this.mask.measurable = !0, this.mask.includeInBuild = !0, this.mask = null; + } + addBounds(e, t) { + fo(this.mask, e, t); + } + addLocalBounds(e, t) { + _o(this.mask, e, t); + } + containsPoint(e, t) { + const n = this.mask; + return t(n, e); + } + destroy() { + this.reset(); + } + static test(e) { + return e instanceof Dt; + } +} +yo.extension = X.MaskEffect; +const Bu = { + createCanvas: (i, e) => { + const t = document.createElement("canvas"); + return t.width = i, t.height = e, t; + }, + createImage: () => new Image(), + getCanvasRenderingContext2D: () => CanvasRenderingContext2D, + getWebGLRenderingContext: () => WebGLRenderingContext, + getNavigator: () => navigator, + getBaseUrl: () => document.baseURI ?? window.location.href, + getFontFaceSet: () => document.fonts, + fetch: (i, e) => fetch(i, e), + parseXML: (i) => new DOMParser().parseFromString(i, "text/xml") +}; +let hr = Bu; +const mt = { + /** + * Returns the current adapter. + * @returns {environment.Adapter} The current adapter. + */ + get() { + return hr; + }, + /** + * Sets the current adapter. + * @param adapter - The new adapter. + */ + set(i) { + hr = i; + } +}; +class bo extends et { + constructor(e) { + e.resource || (e.resource = mt.get().createCanvas()), e.width || (e.width = e.resource.width, e.autoDensity || (e.width /= e.resolution)), e.height || (e.height = e.resource.height, e.autoDensity || (e.height /= e.resolution)), super(e), this.uploadMethodId = "image", this.autoDensity = e.autoDensity, this.resizeCanvas(), this.transparent = !!e.transparent; + } + resizeCanvas() { + this.autoDensity && "style" in this.resource && (this.resource.style.width = `${this.width}px`, this.resource.style.height = `${this.height}px`), (this.resource.width !== this.pixelWidth || this.resource.height !== this.pixelHeight) && (this.resource.width = this.pixelWidth, this.resource.height = this.pixelHeight); + } + resize(e = this.width, t = this.height, n = this._resolution) { + const s = super.resize(e, t, n); + return s && this.resizeCanvas(), s; + } + static test(e) { + return globalThis.HTMLCanvasElement && e instanceof HTMLCanvasElement || globalThis.OffscreenCanvas && e 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")); + } +} +bo.extension = X.TextureSource; +class Qn extends et { + constructor(e) { + super(e), this.uploadMethodId = "image", this.autoGarbageCollect = !0; + } + static test(e) { + return globalThis.HTMLImageElement && e instanceof HTMLImageElement || typeof ImageBitmap < "u" && e instanceof ImageBitmap || globalThis.VideoFrame && e instanceof VideoFrame; + } +} +Qn.extension = X.TextureSource; +var Zi = /* @__PURE__ */ ((i) => (i[i.INTERACTION = 50] = "INTERACTION", i[i.HIGH = 25] = "HIGH", i[i.NORMAL = 0] = "NORMAL", i[i.LOW = -25] = "LOW", i[i.UTILITY = -50] = "UTILITY", i))(Zi || {}); +class vi { + /** + * 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(e, t = null, n = 0, s = !1) { + this.next = null, this.previous = null, this._destroyed = !1, this._fn = e, this._context = t, this.priority = n, this._once = s; + } + /** + * 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(e, t = null) { + return this._fn === e && this._context === t; + } + /** + * Emit by calling the current function. + * @param ticker - The ticker emitting. + * @returns Next ticker + */ + emit(e) { + this._fn && (this._context ? this._fn.call(this._context, e) : this._fn(e)); + const t = this.next; + return this._once && this.destroy(!0), this._destroyed && (this.next = null), t; + } + /** + * Connect to the list. + * @param previous - Input node, previous listener + */ + connect(e) { + this.previous = e, e.next && (e.next.previous = this), this.next = e.next, e.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(e = !1) { + this._destroyed = !0, this._fn = null, this._context = null, this.previous && (this.previous.next = this.next), this.next && (this.next.previous = this.previous); + const t = this.next; + return this.next = e ? null : t, this.previous = null, t; + } +} +const xo = class De { + constructor() { + this.autoStart = !1, this.deltaTime = 1, this.lastTime = -1, this.speed = 1, this.started = !1, this._requestId = null, this._maxElapsedMS = 100, this._minElapsedMS = 0, this._protected = !1, this._lastFrame = -1, this._head = new vi(null, null, 1 / 0), this.deltaMS = 1 / De.targetFPMS, this.elapsedMS = 1 / De.targetFPMS, this._tick = (e) => { + this._requestId = null, this.started && (this.update(e), 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() { + 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() { + 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() { + this.started ? this._requestIfNeeded() : 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(e, t, n = Zi.NORMAL) { + return this._addListener(new vi(e, t, n)); + } + /** + * 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(e, t, n = Zi.NORMAL) { + return this._addListener(new vi(e, t, n, !0)); + } + /** + * 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(e) { + let t = this._head.next, n = this._head; + if (!t) + e.connect(n); + else { + for (; t; ) { + if (e.priority > t.priority) { + e.connect(n); + break; + } + n = t, t = t.next; + } + e.previous || e.connect(n); + } + return this._startIfPossible(), 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(e, t) { + let n = this._head.next; + for (; n; ) + n.match(e, t) ? n = n.destroy() : n = n.next; + return this._head.next || this._cancelIfNeeded(), 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 e = 0, t = this._head; + for (; t = t.next; ) + e++; + return e; + } + /** + * 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() { + this.started || (this.started = !0, 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() { + this.started && (this.started = !1, 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 e = this._head.next; + for (; e; ) + e = e.destroy(!0); + 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(e = performance.now()) { + let t; + if (e > this.lastTime) { + if (t = this.elapsedMS = e - this.lastTime, t > this._maxElapsedMS && (t = this._maxElapsedMS), t *= this.speed, this._minElapsedMS) { + const r = e - this._lastFrame | 0; + if (r < this._minElapsedMS) + return; + this._lastFrame = e - r % this._minElapsedMS; + } + this.deltaMS = t, this.deltaTime = this.deltaMS * De.targetFPMS; + const n = this._head; + let s = n.next; + for (; s; ) + s = s.emit(this); + n.next || this._cancelIfNeeded(); + } else + this.deltaTime = this.deltaMS = this.elapsedMS = 0; + this.lastTime = e; + } + /** + * 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(e) { + const t = Math.min(this.maxFPS, e), n = Math.min(Math.max(0, t) / 1e3, De.targetFPMS); + this._maxElapsedMS = 1 / n; + } + /** + * 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() { + return this._minElapsedMS ? Math.round(1e3 / this._minElapsedMS) : 0; + } + set maxFPS(e) { + if (e === 0) + this._minElapsedMS = 0; + else { + const t = Math.max(this.minFPS, e); + this._minElapsedMS = 1 / (t / 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 (!De._shared) { + const e = De._shared = new De(); + e.autoStart = !0, e._protected = !0; + } + return De._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 (!De._system) { + const e = De._system = new De(); + e.autoStart = !0, e._protected = !0; + } + return De._system; + } +}; +xo.targetFPMS = 0.06; +let $n = xo, wi; +async function Lu() { + return wi ?? (wi = (async () => { + var a; + const e = mt.get().createCanvas(1, 1).getContext("webgl"); + if (!e) + return "premultiply-alpha-on-upload"; + const t = await new Promise((o) => { + const l = document.createElement("video"); + l.onloadeddata = () => o(l), l.onerror = () => o(null), l.autoplay = !1, l.crossOrigin = "anonymous", l.preload = "auto", l.src = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHTEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggEXTbuMU6uEHFO7a1OsggG97AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQkBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua8yuAQAAAAAAAEPXgQFzxYgAAAAAAAAAAZyBACK1nIN1bmSIgQCGhVZfVlA5g4EBI+ODhAJiWgDglLCBArqBApqBAlPAgQFVsIRVuYEBElTDZ9Vzc9JjwItjxYgAAAAAAAAAAWfInEWjh0VOQ09ERVJEh49MYXZjIGxpYnZweC12cDlnyKJFo4hEVVJBVElPTkSHlDAwOjAwOjAwLjA0MDAwMDAwMAAAH0O2dcfngQCgwqGggQAAAIJJg0IAABAAFgA4JBwYSgAAICAAEb///4r+AAB1oZ2mm+6BAaWWgkmDQgAAEAAWADgkHBhKAAAgIABIQBxTu2uRu4+zgQC3iveBAfGCAXHwgQM=", l.load(); + }); + if (!t) + return "premultiply-alpha-on-upload"; + const n = e.createTexture(); + e.bindTexture(e.TEXTURE_2D, n); + const s = e.createFramebuffer(); + e.bindFramebuffer(e.FRAMEBUFFER, s), e.framebufferTexture2D( + e.FRAMEBUFFER, + e.COLOR_ATTACHMENT0, + e.TEXTURE_2D, + n, + 0 + ), e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL, e.NONE), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, t); + const r = new Uint8Array(4); + return e.readPixels(0, 0, 1, 1, e.RGBA, e.UNSIGNED_BYTE, r), e.deleteFramebuffer(s), e.deleteTexture(n), (a = e.getExtension("WEBGL_lose_context")) == null || a.loseContext(), r[0] <= r[3] ? "premultiplied-alpha" : "premultiply-alpha-on-upload"; + })()), wi; +} +const li = class vo extends et { + constructor(e) { + super(e), this.isReady = !1, this.uploadMethodId = "video", e = { + ...vo.defaultOptions, + ...e + }, this._autoUpdate = !0, this._isConnectedToTicker = !1, this._updateFPS = e.updateFPS || 0, this._msToNextUpdate = 0, this.autoPlay = e.autoPlay !== !1, this.alphaMode = e.alphaMode ?? "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), e.autoLoad !== !1 && this.load(); + } + /** Update the video frame if the source is not destroyed and meets certain conditions. */ + updateFrame() { + if (!this.destroyed) { + if (this._updateFPS) { + const e = $n.shared.elapsedMS * this.resource.playbackRate; + this._msToNextUpdate = Math.floor(this._msToNextUpdate - e); + } + (!this._updateFPS || this._msToNextUpdate <= 0) && (this._msToNextUpdate = this._updateFPS ? Math.floor(1e3 / this._updateFPS) : 0), this.isValid && this.update(); + } + } + /** Callback to update the video frame and potentially request the next frame update. */ + _videoFrameRequestCallback() { + this.updateFrame(), this.destroyed ? this._videoFrameRequestCallbackHandle = null : 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} Handle the validate event + */ + async load() { + if (this._load) + return this._load; + const e = this.resource, t = this.options; + return (e.readyState === e.HAVE_ENOUGH_DATA || e.readyState === e.HAVE_FUTURE_DATA) && e.width && e.height && (e.complete = !0), e.addEventListener("play", this._onPlayStart), e.addEventListener("pause", this._onPlayStop), e.addEventListener("seeked", this._onSeeked), this._isSourceReady() ? this._mediaReady() : (t.preload || e.addEventListener("canplay", this._onCanPlay), e.addEventListener("canplaythrough", this._onCanPlayThrough), e.addEventListener("error", this._onError, !0)), this.alphaMode = await Lu(), this._load = new Promise((n, s) => { + this.isValid ? n(this) : (this._resolve = n, this._reject = s, t.preloadTimeoutMs !== void 0 && (this._preloadTimeout = setTimeout(() => { + this._onError(new ErrorEvent(`Preload exceeded timeout of ${t.preloadTimeoutMs}ms`)); + })), e.load()); + }), this._load; + } + /** + * Handle video error events. + * @param event - The error event + */ + _onError(e) { + this.resource.removeEventListener("error", this._onError, !0), this.emit("error", e), this._reject && (this._reject(e), this._reject = null, this._resolve = null); + } + /** + * Checks if the underlying source is playing. + * @returns True if playing. + */ + _isSourcePlaying() { + const e = this.resource; + return !e.paused && !e.ended; + } + /** + * Checks if the underlying source is ready for playing. + * @returns True if ready. + */ + _isSourceReady() { + return this.resource.readyState > 2; + } + /** Runs the update loop when the video is ready to play. */ + _onPlayStart() { + 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() { + this._autoUpdate && !this._isSourcePlaying() && (this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0); + } + _onCanPlay() { + this.resource.removeEventListener("canplay", this._onCanPlay), this._mediaReady(); + } + _onCanPlayThrough() { + this.resource.removeEventListener("canplaythrough", this._onCanPlay), this._preloadTimeout && (clearTimeout(this._preloadTimeout), this._preloadTimeout = void 0), this._mediaReady(); + } + /** Fired when the video is loaded and ready to play. */ + _mediaReady() { + const e = this.resource; + this.isValid && (this.isReady = !0, this.resize(e.videoWidth, e.videoHeight)), this._msToNextUpdate = 0, this.updateFrame(), this._msToNextUpdate = 0, this._resolve && (this._resolve(this), this._resolve = null, this._reject = null), this._isSourcePlaying() ? this._onPlayStart() : this.autoPlay && this.resource.play(); + } + /** Cleans up resources and event listeners associated with this texture. */ + destroy() { + this._configureAutoUpdate(); + const e = this.resource; + e && (e.removeEventListener("play", this._onPlayStart), e.removeEventListener("pause", this._onPlayStop), e.removeEventListener("seeked", this._onSeeked), e.removeEventListener("canplay", this._onCanPlay), e.removeEventListener("canplaythrough", this._onCanPlayThrough), e.removeEventListener("error", this._onError, !0), e.pause(), e.src = "", e.load()), super.destroy(); + } + /** Should the base texture automatically update itself, set to true by default. */ + get autoUpdate() { + return this._autoUpdate; + } + set autoUpdate(e) { + e !== this._autoUpdate && (this._autoUpdate = e, 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(e) { + e !== this._updateFPS && (this._updateFPS = e, 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() { + this._autoUpdate && this._isSourcePlaying() ? !this._updateFPS && this.resource.requestVideoFrameCallback ? (this._isConnectedToTicker && ($n.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0), this._videoFrameRequestCallbackHandle === null && (this._videoFrameRequestCallbackHandle = this.resource.requestVideoFrameCallback( + this._videoFrameRequestCallback + ))) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker || ($n.shared.add(this.updateFrame, this), this._isConnectedToTicker = !0, this._msToNextUpdate = 0)) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker && ($n.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0)); + } + static test(e) { + return globalThis.HTMLVideoElement && e instanceof HTMLVideoElement; + } +}; +li.extension = X.TextureSource; +li.defaultOptions = { + ...et.defaultOptions, + /** If true, the video will start loading immediately. */ + autoLoad: !0, + /** If true, the video will start playing as soon as it is loaded. */ + autoPlay: !0, + /** 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: !0, + /** If true, the video will loop when it ends. */ + loop: !1, + /** If true, the video will be muted. */ + muted: !0, + /** If true, the video will play inline. */ + playsinline: !0, + /** If true, the video will be preloaded. */ + preload: !1 +}; +li.MIME_TYPES = { + ogv: "video/ogg", + mov: "video/quicktime", + m4v: "video/mp4" +}; +let Nu = li; +const Pt = (i, e, t = !1) => (Array.isArray(i) || (i = [i]), e ? i.map((n) => typeof n == "string" || t ? e(n) : n) : i); +class Ou { + 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(e) { + return this._cache.has(e); + } + /** + * Fetch entry by key + * @param key - The key of the entry to get + */ + get(e) { + const t = this._cache.get(e); + return t || Fe(`[Assets] Asset id ${e} was not found in the Cache`), t; + } + /** + * 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(e, t) { + const n = Pt(e); + let s; + for (let l = 0; l < this.parsers.length; l++) { + const u = this.parsers[l]; + if (u.test(t)) { + s = u.getCacheableAssets(n, t); + break; + } + } + const r = new Map(Object.entries(s || {})); + s || n.forEach((l) => { + r.set(l, t); + }); + const a = [...r.keys()], o = { + cacheKeys: a, + keys: n + }; + n.forEach((l) => { + this._cacheMap.set(l, o); + }), a.forEach((l) => { + const u = s ? s[l] : t; + this._cache.has(l) && this._cache.get(l) !== u && Fe("[Cache] already has key:", l), this._cache.set(l, r.get(l)); + }); + } + /** + * 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(e) { + if (!this._cacheMap.has(e)) { + Fe(`[Assets] Asset id ${e} was not found in the Cache`); + return; + } + const t = this._cacheMap.get(e); + t.cacheKeys.forEach((s) => { + this._cache.delete(s); + }), t.keys.forEach((s) => { + this._cacheMap.delete(s); + }); + } + /** + * All loader parsers registered + * @advanced + */ + get parsers() { + return this._parsers; + } +} +const It = new Ou(), Ki = []; +Ve.handleByList(X.TextureSource, Ki); +function wo(i = {}) { + const e = i && i.resource, t = e ? i.resource : i, n = e ? i : { resource: i }; + for (let s = 0; s < Ki.length; s++) { + const r = Ki[s]; + if (r.test(t)) + return new r(n); + } + throw new Error(`Could not find a source type for resource: ${n.resource}`); +} +function Gu(i = {}, e = !1) { + const t = i && i.resource, n = t ? i.resource : i, s = t ? i : { resource: i }; + if (!e && It.has(n)) + return It.get(n); + const r = new W({ source: wo(s) }); + return r.on("destroy", () => { + It.has(n) && It.remove(n); + }), e || It.set(n, r), r; +} +function zu(i, e = !1) { + return typeof i == "string" ? It.get(i) : i instanceof et ? new W({ source: i }) : Gu(i, e); +} +W.from = zu; +et.from = wo; +Ve.add(mo, go, yo, Nu, Qn, bo, ws); +var Co = /* @__PURE__ */ ((i) => (i[i.Low = 0] = "Low", i[i.Normal = 1] = "Normal", i[i.High = 2] = "High", i))(Co || {}); +function Xe(i) { + if (typeof i != "string") + throw new TypeError(`Path must be a string. Received ${JSON.stringify(i)}`); +} +function qt(i) { + return i.split("?")[0].split("#")[0]; +} +function qu(i) { + return i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +function Uu(i, e, t) { + return i.replace(new RegExp(qu(e), "g"), t); +} +function Hu(i, e) { + let t = "", n = 0, s = -1, r = 0, a = -1; + for (let o = 0; o <= i.length; ++o) { + if (o < i.length) + a = i.charCodeAt(o); + else { + if (a === 47) + break; + a = 47; + } + if (a === 47) { + if (!(s === o - 1 || r === 1)) if (s !== o - 1 && r === 2) { + if (t.length < 2 || n !== 2 || t.charCodeAt(t.length - 1) !== 46 || t.charCodeAt(t.length - 2) !== 46) { + if (t.length > 2) { + const l = t.lastIndexOf("/"); + if (l !== t.length - 1) { + l === -1 ? (t = "", n = 0) : (t = t.slice(0, l), n = t.length - 1 - t.lastIndexOf("/")), s = o, r = 0; + continue; + } + } else if (t.length === 2 || t.length === 1) { + t = "", n = 0, s = o, r = 0; + continue; + } + } + } else + t.length > 0 ? t += `/${i.slice(s + 1, o)}` : t = i.slice(s + 1, o), n = o - s - 1; + s = o, r = 0; + } else a === 46 && r !== -1 ? ++r : r = -1; + } + return t; +} +const fn = { + /** + * 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(i) { + return Uu(i, "\\", "/"); + }, + /** + * 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(i) { + return /^https?:/.test(this.toPosix(i)); + }, + /** + * 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(i) { + return /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i.test(i); + }, + /** + * 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(i) { + return i.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(i) { + return /^[^/:]+:/.test(this.toPosix(i)); + }, + /** + * 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(i) { + Xe(i), i = this.toPosix(i); + const e = /^file:\/\/\//.exec(i); + if (e) + return e[0]; + const t = /^[^/:]+:\/{0,2}/.exec(i); + return t ? t[0] : ""; + }, + /** + * 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(i, e, t) { + if (Xe(i), this.isDataUrl(i) || this.isBlobUrl(i)) + return i; + const n = qt(this.toPosix(e ?? mt.get().getBaseUrl())), s = qt(this.toPosix(t ?? this.rootname(n))); + return i = this.toPosix(i), i.startsWith("/") ? fn.join(s, i.slice(1)) : this.isAbsolute(i) ? i : this.join(n, i); + }, + /** + * 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(i) { + if (Xe(i), i.length === 0) + return "."; + if (this.isDataUrl(i) || this.isBlobUrl(i)) + return i; + i = this.toPosix(i); + let e = ""; + const t = i.startsWith("/"); + this.hasProtocol(i) && (e = this.rootname(i), i = i.slice(e.length)); + const n = i.endsWith("/"); + return i = Hu(i), i.length > 0 && n && (i += "/"), t ? `/${i}` : e + i; + }, + /** + * 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(i) { + return Xe(i), i = this.toPosix(i), this.hasProtocol(i) ? !0 : i.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(...i) { + if (i.length === 0) + return "."; + let e; + for (let t = 0; t < i.length; ++t) { + const n = i[t]; + if (Xe(n), n.length > 0) + if (e === void 0) + e = n; + else { + const s = i[t - 1] ?? ""; + this.joinExtensions.includes(this.extname(s).toLowerCase()) ? e += `/../${n}` : e += `/${n}`; + } + } + return e === void 0 ? "." : this.normalize(e); + }, + /** + * 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(i) { + if (Xe(i), i.length === 0) + return "."; + i = this.toPosix(i); + let e = i.charCodeAt(0); + const t = e === 47; + let n = -1, s = !0; + const r = this.getProtocol(i), a = i; + i = i.slice(r.length); + for (let o = i.length - 1; o >= 1; --o) + if (e = i.charCodeAt(o), e === 47) { + if (!s) { + n = o; + break; + } + } else + s = !1; + return n === -1 ? t ? "/" : this.isUrl(a) ? r + i : r : t && n === 1 ? "//" : r + i.slice(0, n); + }, + /** + * 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(i) { + Xe(i), i = this.toPosix(i); + let e = ""; + if (i.startsWith("/") ? e = "/" : e = this.getProtocol(i), this.isUrl(i)) { + const t = i.indexOf("/", e.length); + t !== -1 ? e = i.slice(0, t) : e = i, e.endsWith("/") || (e += "/"); + } + return e; + }, + /** + * 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(i, e) { + Xe(i), e && Xe(e), i = qt(this.toPosix(i)); + let t = 0, n = -1, s = !0, r; + if (e !== void 0 && e.length > 0 && e.length <= i.length) { + if (e.length === i.length && e === i) + return ""; + let a = e.length - 1, o = -1; + for (r = i.length - 1; r >= 0; --r) { + const l = i.charCodeAt(r); + if (l === 47) { + if (!s) { + t = r + 1; + break; + } + } else + o === -1 && (s = !1, o = r + 1), a >= 0 && (l === e.charCodeAt(a) ? --a === -1 && (n = r) : (a = -1, n = o)); + } + return t === n ? n = o : n === -1 && (n = i.length), i.slice(t, n); + } + for (r = i.length - 1; r >= 0; --r) + if (i.charCodeAt(r) === 47) { + if (!s) { + t = r + 1; + break; + } + } else n === -1 && (s = !1, n = r + 1); + return n === -1 ? "" : i.slice(t, n); + }, + /** + * 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(i) { + Xe(i), i = qt(this.toPosix(i)); + let e = -1, t = 0, n = -1, s = !0, r = 0; + for (let a = i.length - 1; a >= 0; --a) { + const o = i.charCodeAt(a); + if (o === 47) { + if (!s) { + t = a + 1; + break; + } + continue; + } + n === -1 && (s = !1, n = a + 1), o === 46 ? e === -1 ? e = a : r !== 1 && (r = 1) : e !== -1 && (r = -1); + } + return e === -1 || n === -1 || r === 0 || r === 1 && e === n - 1 && e === t + 1 ? "" : i.slice(e, n); + }, + /** + * 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(i) { + Xe(i); + const e = { root: "", dir: "", base: "", ext: "", name: "" }; + if (i.length === 0) + return e; + i = qt(this.toPosix(i)); + let t = i.charCodeAt(0); + const n = this.isAbsolute(i); + let s; + e.root = this.rootname(i), n || this.hasProtocol(i) ? s = 1 : s = 0; + let r = -1, a = 0, o = -1, l = !0, u = i.length - 1, h = 0; + for (; u >= s; --u) { + if (t = i.charCodeAt(u), t === 47) { + if (!l) { + a = u + 1; + break; + } + continue; + } + o === -1 && (l = !1, o = u + 1), t === 46 ? r === -1 ? r = u : h !== 1 && (h = 1) : r !== -1 && (h = -1); + } + return r === -1 || o === -1 || h === 0 || h === 1 && r === o - 1 && r === a + 1 ? o !== -1 && (a === 0 && n ? e.base = e.name = i.slice(1, o) : e.base = e.name = i.slice(a, o)) : (a === 0 && n ? (e.name = i.slice(1, r), e.base = i.slice(1, o)) : (e.name = i.slice(a, r), e.base = i.slice(a, o)), e.ext = i.slice(r, o)), e.dir = this.dirname(i), e; + }, + sep: "/", + delimiter: ":", + joinExtensions: [".html"] +}; +function Ao(i, e, t, n, s) { + const r = e[t]; + for (let a = 0; a < r.length; a++) { + const o = r[a]; + t < e.length - 1 ? Ao(i.replace(n[t], o), e, t + 1, n, s) : s.push(i.replace(n[t], o)); + } +} +function Vu(i) { + const e = /\{(.*?)\}/g, t = i.match(e), n = []; + if (t) { + const s = []; + t.forEach((r) => { + const a = r.substring(1, r.length - 1).split(","); + s.push(a); + }), Ao(i, s, 0, t, n); + } else + n.push(i); + return n; +} +const cr = (i) => !Array.isArray(i); +class ko { + constructor() { + this._defaultBundleIdentifierOptions = { + connector: "-", + createBundleAssetId: (e, t) => `${e}${this._bundleIdConnector}${t}`, + extractAssetIdFromBundle: (e, t) => t.replace(`${e}${this._bundleIdConnector}`, "") + }, this._bundleIdConnector = this._defaultBundleIdentifierOptions.connector, this._createBundleAssetId = this._defaultBundleIdentifierOptions.createBundleAssetId, 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(e) { + if (this._bundleIdConnector = e.connector ?? this._bundleIdConnector, this._createBundleAssetId = e.createBundleAssetId ?? this._createBundleAssetId, this._extractAssetIdFromBundle = e.extractAssetIdFromBundle ?? this._extractAssetIdFromBundle, 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(...e) { + e.forEach((t) => { + this._preferredOrder.push(t), t.priority || (t.priority = Object.keys(t.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(e) { + this._basePath = e; + } + 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(e) { + this._rootPath = e; + } + 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(e) { + if (typeof e == "string") + this._defaultSearchParams = e; + else { + const t = e; + this._defaultSearchParams = Object.keys(t).map((n) => `${encodeURIComponent(n)}=${encodeURIComponent(t[n])}`).join("&"); + } + } + /** + * Returns the aliases for a given asset + * @param asset - the asset to get the aliases for + */ + getAlias(e) { + const { alias: t, src: n } = e; + return Pt( + t || n, + (r) => typeof r == "string" ? r : Array.isArray(r) ? r.map((a) => (a == null ? void 0 : a.src) ?? a) : r != null && r.src ? r.src : r, + !0 + ); + } + /** + * 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(e) { + this._manifest && Fe("[Resolver] Manifest already exists, this will be overwritten"), this._manifest = e, e.bundles.forEach((t) => { + this.addBundle(t.name, t.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(e, t) { + const n = []; + let s = t; + Array.isArray(t) || (s = Object.entries(t).map(([r, a]) => typeof a == "string" || Array.isArray(a) ? { alias: r, src: a } : { alias: r, ...a })), s.forEach((r) => { + const a = r.src, o = r.alias; + let l; + if (typeof o == "string") { + const u = this._createBundleAssetId(e, o); + n.push(u), l = [o, u]; + } else { + const u = o.map((h) => this._createBundleAssetId(e, h)); + n.push(...u), l = [...o, ...u]; + } + this.add({ + ...r, + alias: l, + src: a + }); + }), this._bundles[e] = n; + } + /** + * 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(e) { + const t = []; + Array.isArray(e) ? t.push(...e) : t.push(e); + let n; + n = (r) => { + this.hasKey(r) && Fe(`[Resolver] already has key: ${r} overwriting`); + }, Pt(t).forEach((r) => { + const { src: a } = r; + let { data: o, format: l, loadParser: u, parser: h } = r; + const c = Pt(a).map((p) => typeof p == "string" ? Vu(p) : Array.isArray(p) ? p : [p]), f = this.getAlias(r); + Array.isArray(f) ? f.forEach(n) : n(f); + const d = []; + c.forEach((p) => { + p.forEach((b) => { + let m = {}; + if (typeof b != "object") { + m.src = b; + for (let x = 0; x < this._parsers.length; x++) { + const g = this._parsers[x]; + if (g.test(b)) { + m = g.parse(b); + break; + } + } + } else + o = b.data ?? o, l = b.format ?? l, (b.loadParser || b.parser) && (u = b.loadParser ?? u, h = b.parser ?? h), m = { + ...m, + ...b + }; + if (!f) + throw new Error(`[Resolver] alias is undefined for this asset: ${m.src}`); + m = this._buildResolvedAsset(m, { + aliases: f, + data: o, + format: l, + loadParser: u, + parser: h + }), d.push(m); + }); + }), f.forEach((p) => { + this._assetMap[p] = d; + }); + }); + } + // 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(e) { + const t = cr(e); + e = Pt(e); + const n = {}; + return e.forEach((s) => { + const r = this._bundles[s]; + if (r) { + const a = this.resolve(r), o = {}; + for (const l in a) { + const u = a[l]; + o[this._extractAssetIdFromBundle(s, l)] = u; + } + n[s] = o; + } + }), t ? n[e[0]] : n; + } + /** + * 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(e) { + const t = this.resolve(e); + if (typeof e != "string") { + const n = {}; + for (const s in t) + n[s] = t[s].src; + return n; + } + return t.src; + } + resolve(e) { + const t = cr(e); + e = Pt(e); + const n = {}; + return e.forEach((s) => { + if (!this._resolverHash[s]) + if (this._assetMap[s]) { + let r = this._assetMap[s]; + const a = this._getPreferredOrder(r); + a == null || a.priority.forEach((o) => { + a.params[o].forEach((l) => { + const u = r.filter((h) => h[o] ? h[o] === l : !1); + u.length && (r = u); + }); + }), this._resolverHash[s] = r[0]; + } else + this._resolverHash[s] = this._buildResolvedAsset({ + alias: [s], + src: s + }, {}); + n[s] = this._resolverHash[s]; + }), t ? n[e[0]] : n; + } + /** + * Checks if an asset with a given key exists in the resolver + * @param key - The key of the asset + */ + hasKey(e) { + return !!this._assetMap[e]; + } + /** + * Checks if a bundle with the given key exists in the resolver + * @param key - The key of the bundle + */ + hasBundle(e) { + return !!this._bundles[e]; + } + /** + * Internal function for figuring out what prefer criteria an asset should use. + * @param assets + */ + _getPreferredOrder(e) { + for (let t = 0; t < e.length; t++) { + const n = e[t], s = this._preferredOrder.find((r) => r.params.format.includes(n.format)); + if (s) + return s; + } + 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(e) { + if (!this._defaultSearchParams) + return e; + const t = /\?/.test(e) ? "&" : "?"; + return `${e}${t}${this._defaultSearchParams}`; + } + _buildResolvedAsset(e, t) { + const { aliases: n, data: s, loadParser: r, parser: a, format: o } = t; + return (this._basePath || this._rootPath) && (e.src = fn.toAbsolute(e.src, this._basePath, this._rootPath)), e.alias = n ?? e.alias ?? [e.src], e.src = this._appendDefaultSearchParams(e.src), e.data = { ...s || {}, ...e.data }, e.loadParser = r ?? e.loadParser, e.parser = a ?? e.parser, e.format = o ?? e.format ?? Yu(e.src), e; + } +} +ko.RETINA_PREFIX = /@([0-9\.]+)x/; +function Yu(i) { + return i.split(".").pop().split("?").shift().split("#").shift(); +} +const dr = (i, e) => { + const t = e.split("?")[1]; + return t && (i += `?${t}`), i; +}, Do = class en { + constructor(e, t) { + this.linkedSheets = []; + let n = e; + (e == null ? void 0 : e.source) instanceof et && (n = { + texture: e, + data: t + }); + const { texture: s, data: r, cachePrefix: a = "" } = n; + this.cachePrefix = a, this._texture = s instanceof W ? s : null, this.textureSource = s.source, this.textures = {}, this.animations = {}, this.data = r; + const o = parseFloat(r.meta.scale); + o ? (this.resolution = o, s.source.resolution = this.resolution) : this.resolution = s.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((e) => { + this._callback = e, this._batchIndex = 0, this._frameKeys.length <= en.BATCH_SIZE ? (this._processFrames(0), this._processAnimations(), this._parseComplete()) : this._nextBatch(); + }); + } + /** + * Process a batch of frames + * @param initialFrameIndex - The index of frame to start. + */ + _processFrames(e) { + let t = e; + const n = en.BATCH_SIZE; + for (; t - e < n && t < this._frameKeys.length; ) { + const s = this._frameKeys[t], r = this._frames[s], a = r.frame; + if (a) { + let o = null, l = null; + const u = r.trimmed !== !1 && r.sourceSize ? r.sourceSize : r.frame, h = new ce( + 0, + 0, + Math.floor(u.w) / this.resolution, + Math.floor(u.h) / this.resolution + ); + r.rotated ? o = new ce( + Math.floor(a.x) / this.resolution, + Math.floor(a.y) / this.resolution, + Math.floor(a.h) / this.resolution, + Math.floor(a.w) / this.resolution + ) : o = new ce( + Math.floor(a.x) / this.resolution, + Math.floor(a.y) / this.resolution, + Math.floor(a.w) / this.resolution, + Math.floor(a.h) / this.resolution + ), r.trimmed !== !1 && r.spriteSourceSize && (l = new ce( + Math.floor(r.spriteSourceSize.x) / this.resolution, + Math.floor(r.spriteSourceSize.y) / this.resolution, + Math.floor(a.w) / this.resolution, + Math.floor(a.h) / this.resolution + )), this.textures[s] = new W({ + source: this.textureSource, + frame: o, + orig: h, + trim: l, + rotate: r.rotated ? 2 : 0, + defaultAnchor: r.anchor, + defaultBorders: r.borders, + label: s.toString() + }); + } + t++; + } + } + /** Parse animations config. */ + _processAnimations() { + const e = this.data.animations || {}; + for (const t in e) { + this.animations[t] = []; + for (let n = 0; n < e[t].length; n++) { + const s = e[t][n]; + this.animations[t].push(this.textures[s]); + } + } + } + /** The parse has completed. */ + _parseComplete() { + const e = this._callback; + this._callback = null, this._batchIndex = 0, e.call(this, this.textures); + } + /** Begin the next batch of textures. */ + _nextBatch() { + this._processFrames(this._batchIndex * en.BATCH_SIZE), this._batchIndex++, setTimeout(() => { + this._batchIndex * en.BATCH_SIZE < this._frameKeys.length ? this._nextBatch() : (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(e = !1) { + var t; + for (const n in this.textures) + this.textures[n].destroy(); + this._frames = null, this._frameKeys = null, this.data = null, this.textures = null, e && ((t = this._texture) == null || t.destroy(), this.textureSource.destroy()), this._texture = null, this.textureSource = null, this.linkedSheets = []; + } +}; +Do.BATCH_SIZE = 1e3; +let fr = Do; +const Xu = [ + "jpg", + "png", + "jpeg", + "avif", + "webp", + "basis", + "etc2", + "bc7", + "bc6h", + "bc5", + "bc4", + "bc3", + "bc2", + "bc1", + "eac", + "astc" +]; +function So(i, e, t) { + const n = {}; + if (i.forEach((s) => { + n[s] = e; + }), Object.keys(e.textures).forEach((s) => { + n[`${e.cachePrefix}${s}`] = e.textures[s]; + }), !t) { + const s = fn.dirname(i[0]); + e.linkedSheets.forEach((r, a) => { + const o = So([`${s}/${e.data.meta.related_multi_packs[a]}`], r, !0); + Object.assign(n, o); + }); + } + return n; +} +const ju = { + extension: X.Asset, + /** Handle the caching of the related Spritesheet Textures */ + cache: { + test: (i) => i instanceof fr, + getCacheableAssets: (i, e) => So(i, e, !1) + }, + /** Resolve the resolution of the asset. */ + resolver: { + extension: { + type: X.ResolveParser, + name: "resolveSpritesheet" + }, + test: (i) => { + const t = i.split("?")[0].split("."), n = t.pop(), s = t.pop(); + return n === "json" && Xu.includes(s); + }, + parse: (i) => { + var t; + const e = i.split("."); + return { + resolution: parseFloat(((t = ko.RETINA_PREFIX.exec(i)) == null ? void 0 : t[1]) ?? "1"), + format: e[e.length - 2], + src: i + }; + } + }, + /** + * 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: X.LoadParser, + priority: Co.Normal, + name: "spritesheetLoader" + }, + async testParse(i, e) { + return fn.extname(e.src).toLowerCase() === ".json" && !!i.frames; + }, + async parse(i, e, t) { + var c, f; + const { + texture: n, + // if user need to use preloaded texture + imageFilename: s, + // if user need to use custom filename (not from jsonFile.meta.image) + textureOptions: r, + // if user need to set texture options on texture + cachePrefix: a + // if user need to use custom cache prefix + } = (e == null ? void 0 : e.data) ?? {}; + let o = fn.dirname(e.src); + o && o.lastIndexOf("/") !== o.length - 1 && (o += "/"); + let l; + if (n instanceof W) + l = n; + else { + const d = dr(o + (s ?? i.meta.image), e.src); + l = (await t.load([{ src: d, data: r }]))[d]; + } + const u = new fr({ + texture: l.source, + data: i, + cachePrefix: a + }); + await u.parse(); + const h = (c = i == null ? void 0 : i.meta) == null ? void 0 : c.related_multi_packs; + if (Array.isArray(h)) { + const d = []; + for (const b of h) { + if (typeof b != "string") + continue; + let m = o + b; + (f = e.data) != null && f.ignoreMultiPack || (m = dr(m, e.src), d.push(t.load({ + src: m, + data: { + textureOptions: r, + ignoreMultiPack: !0 + } + }))); + } + const p = await Promise.all(d); + u.linkedSheets = p, p.forEach((b) => { + b.linkedSheets = [u].concat(u.linkedSheets.filter((m) => m !== b)); + }); + } + return u; + }, + async unload(i, e, t) { + await t.unload(i.textureSource._sourceOrigin), i.destroy(!1); + } + } +}; +Ve.add(ju); +const Ci = /* @__PURE__ */ Object.create(null), _r = /* @__PURE__ */ Object.create(null); +function As(i, e) { + let t = _r[i]; + return t === void 0 && (Ci[e] === void 0 && (Ci[e] = 1), _r[i] = t = Ci[e]++), t; +} +let Et; +function Eo() { + return (!Et || Et != null && Et.isContextLost()) && (Et = mt.get().createCanvas().getContext("webgl", {})), Et; +} +let Tn; +function Wu() { + if (!Tn) { + Tn = "mediump"; + const i = Eo(); + i && i.getShaderPrecisionFormat && (Tn = i.getShaderPrecisionFormat(i.FRAGMENT_SHADER, i.HIGH_FLOAT).precision ? "highp" : "mediump"); + } + return Tn; +} +function Zu(i, e, t) { + return e ? i : t ? (i = i.replace("out vec4 finalColor;", ""), ` + + #ifdef GL_ES // This checks if it is WebGL1 + #define in varying + #define finalColor gl_FragColor + #define texture texture2D + #endif + ${i} + `) : ` + + #ifdef GL_ES // This checks if it is WebGL1 + #define in attribute + #define out varying + #endif + ${i} + `; +} +function Ku(i, e, t) { + const n = t ? e.maxSupportedFragmentPrecision : e.maxSupportedVertexPrecision; + if (i.substring(0, 9) !== "precision") { + let s = t ? e.requestedFragmentPrecision : e.requestedVertexPrecision; + return s === "highp" && n !== "highp" && (s = "mediump"), `precision ${s} float; +${i}`; + } else if (n !== "highp" && i.substring(0, 15) === "precision highp") + return i.replace("precision highp", "precision mediump"); + return i; +} +function Qu(i, e) { + return e ? `#version 300 es +${i}` : i; +} +const Ju = {}, eh = {}; +function th(i, { name: e = "pixi-program" }, t = !0) { + e = e.replace(/\s+/g, "-"), e += t ? "-fragment" : "-vertex"; + const n = t ? Ju : eh; + return n[e] ? (n[e]++, e += `-${n[e]}`) : n[e] = 1, i.indexOf("#define SHADER_NAME") !== -1 ? i : `${`#define SHADER_NAME ${e}`} +${i}`; +} +function nh(i, e) { + return e ? i.replace("#version 300 es", "") : i; +} +const Ai = { + // strips any version headers.. + stripVersion: nh, + // adds precision string if not already present + ensurePrecision: Ku, + // add some defines if WebGL1 to make it more compatible with WebGL2 shaders + addProgramDefines: Zu, + // add the program name to the shader + setProgramName: th, + // add the version string to the shader header + insertVersion: Qu +}, Ut = /* @__PURE__ */ Object.create(null), Fo = class Qi { + /** + * Creates a shiny new GlProgram. Used by WebGL renderer. + * @param options - The options for the program. + */ + constructor(e) { + e = { ...Qi.defaultOptions, ...e }; + const t = e.fragment.indexOf("#version 300 es") !== -1, n = { + stripVersion: t, + ensurePrecision: { + requestedFragmentPrecision: e.preferredFragmentPrecision, + requestedVertexPrecision: e.preferredVertexPrecision, + maxSupportedVertexPrecision: "highp", + maxSupportedFragmentPrecision: Wu() + }, + setProgramName: { + name: e.name + }, + addProgramDefines: t, + insertVersion: t + }; + let s = e.fragment, r = e.vertex; + Object.keys(Ai).forEach((a) => { + const o = n[a]; + s = Ai[a](s, o, !0), r = Ai[a](r, o, !1); + }), this.fragment = s, this.vertex = r, this.transformFeedbackVaryings = e.transformFeedbackVaryings, this._key = As(`${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, Ut[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(e) { + const t = `${e.vertex}:${e.fragment}`; + return Ut[t] || (Ut[t] = new Qi(e), Ut[t]._cacheKey = t), Ut[t]; + } +}; +Fo.defaultOptions = { + preferredVertexPrecision: "highp", + preferredFragmentPrecision: "mediump" +}; +let $o = Fo; +const pr = { + uint8x2: { size: 2, stride: 2, normalised: !1 }, + uint8x4: { size: 4, stride: 4, normalised: !1 }, + sint8x2: { size: 2, stride: 2, normalised: !1 }, + sint8x4: { size: 4, stride: 4, normalised: !1 }, + unorm8x2: { size: 2, stride: 2, normalised: !0 }, + unorm8x4: { size: 4, stride: 4, normalised: !0 }, + snorm8x2: { size: 2, stride: 2, normalised: !0 }, + snorm8x4: { size: 4, stride: 4, normalised: !0 }, + uint16x2: { size: 2, stride: 4, normalised: !1 }, + uint16x4: { size: 4, stride: 8, normalised: !1 }, + sint16x2: { size: 2, stride: 4, normalised: !1 }, + sint16x4: { size: 4, stride: 8, normalised: !1 }, + unorm16x2: { size: 2, stride: 4, normalised: !0 }, + unorm16x4: { size: 4, stride: 8, normalised: !0 }, + snorm16x2: { size: 2, stride: 4, normalised: !0 }, + snorm16x4: { size: 4, stride: 8, normalised: !0 }, + float16x2: { size: 2, stride: 4, normalised: !1 }, + float16x4: { size: 4, stride: 8, normalised: !1 }, + float32: { size: 1, stride: 4, normalised: !1 }, + float32x2: { size: 2, stride: 8, normalised: !1 }, + float32x3: { size: 3, stride: 12, normalised: !1 }, + float32x4: { size: 4, stride: 16, normalised: !1 }, + uint32: { size: 1, stride: 4, normalised: !1 }, + uint32x2: { size: 2, stride: 8, normalised: !1 }, + uint32x3: { size: 3, stride: 12, normalised: !1 }, + uint32x4: { size: 4, stride: 16, normalised: !1 }, + sint32: { size: 1, stride: 4, normalised: !1 }, + sint32x2: { size: 2, stride: 8, normalised: !1 }, + sint32x3: { size: 3, stride: 12, normalised: !1 }, + sint32x4: { size: 4, stride: 16, normalised: !1 } +}; +function ih(i) { + return pr[i] ?? pr.float32; +} +const sh = { + f32: "float32", + "vec2": "float32x2", + "vec3": "float32x3", + "vec4": "float32x4", + vec2f: "float32x2", + vec3f: "float32x3", + vec4f: "float32x4", + i32: "sint32", + "vec2": "sint32x2", + "vec3": "sint32x3", + "vec4": "sint32x4", + u32: "uint32", + "vec2": "uint32x2", + "vec3": "uint32x3", + "vec4": "uint32x4", + bool: "uint32", + "vec2": "uint32x2", + "vec3": "uint32x3", + "vec4": "uint32x4" +}; +function rh({ source: i, entryPoint: e }) { + const t = {}, n = i.indexOf(`fn ${e}`); + if (n !== -1) { + const s = i.indexOf("->", n); + if (s !== -1) { + const r = i.substring(n, s), a = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g; + let o; + for (; (o = a.exec(r)) !== null; ) { + const l = sh[o[3]] ?? "float32"; + t[o[2]] = { + location: parseInt(o[1], 10), + format: l, + stride: ih(l).stride, + offset: 0, + instance: !1, + start: 0 + }; + } + } + } + return t; +} +function ki(i) { + var c, f; + const e = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g, t = /@group\((\d+)\)/, n = /@binding\((\d+)\)/, s = /var(<[^>]+>)? (\w+)/, r = /:\s*(\w+)/, a = /struct\s+(\w+)\s*{([^}]+)}/g, o = /(\w+)\s*:\s*([\w\<\>]+)/g, l = /struct\s+(\w+)/, u = (c = i.match(e)) == null ? void 0 : c.map((d) => ({ + group: parseInt(d.match(t)[1], 10), + binding: parseInt(d.match(n)[1], 10), + name: d.match(s)[2], + isUniform: d.match(s)[1] === "", + type: d.match(r)[1] + })); + if (!u) + return { + groups: [], + structs: [] + }; + const h = ((f = i.match(a)) == null ? void 0 : f.map((d) => { + const p = d.match(l)[1], b = d.match(o).reduce((m, x) => { + const [g, _] = x.split(":"); + return m[g.trim()] = _.trim(), m; + }, {}); + return b ? { name: p, members: b } : null; + }).filter(({ name: d }) => u.some((p) => p.type === d))) ?? []; + return { + groups: u, + structs: h + }; +} +var tn = /* @__PURE__ */ ((i) => (i[i.VERTEX = 1] = "VERTEX", i[i.FRAGMENT = 2] = "FRAGMENT", i[i.COMPUTE = 4] = "COMPUTE", i))(tn || {}); +function ah({ groups: i }) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t]; + e[n.group] || (e[n.group] = []), n.isUniform ? e[n.group].push({ + binding: n.binding, + visibility: tn.VERTEX | tn.FRAGMENT, + buffer: { + type: "uniform" + } + }) : n.type === "sampler" ? e[n.group].push({ + binding: n.binding, + visibility: tn.FRAGMENT, + sampler: { + type: "filtering" + } + }) : n.type === "texture_2d" && e[n.group].push({ + binding: n.binding, + visibility: tn.FRAGMENT, + texture: { + sampleType: "float", + viewDimension: "2d", + multisampled: !1 + } + }); + } + return e; +} +function oh({ groups: i }) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t]; + e[n.group] || (e[n.group] = {}), e[n.group][n.name] = n.binding; + } + return e; +} +function lh(i, e) { + const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), s = [...i.structs, ...e.structs].filter((a) => t.has(a.name) ? !1 : (t.add(a.name), !0)), r = [...i.groups, ...e.groups].filter((a) => { + const o = `${a.name}-${a.binding}`; + return n.has(o) ? !1 : (n.add(o), !0); + }); + return { structs: s, groups: r }; +} +const Ht = /* @__PURE__ */ Object.create(null); +class ui { + /** + * Create a new GpuProgram + * @param options - The options for the gpu program + */ + constructor(e) { + var o, l; + this._layoutKey = 0, this._attributeLocationsKey = 0; + const { fragment: t, vertex: n, layout: s, gpuLayout: r, name: a } = e; + if (this.name = a, this.fragment = t, this.vertex = n, t.source === n.source) { + const u = ki(t.source); + this.structsAndGroups = u; + } else { + const u = ki(n.source), h = ki(t.source); + this.structsAndGroups = lh(u, h); + } + this.layout = s ?? oh(this.structsAndGroups), this.gpuLayout = r ?? ah(this.structsAndGroups), this.autoAssignGlobalUniforms = ((o = this.layout[0]) == null ? void 0 : o.globalUniforms) !== void 0, this.autoAssignLocalUniforms = ((l = this.layout[1]) == null ? void 0 : l.localUniforms) !== void 0, this._generateProgramKey(); + } + // TODO maker this pure + _generateProgramKey() { + const { vertex: e, fragment: t } = this, n = e.source + t.source + e.entryPoint + t.entryPoint; + this._layoutKey = As(n, "program"); + } + get attributeData() { + return this._attributeData ?? (this._attributeData = rh(this.vertex)), this._attributeData; + } + /** destroys the program */ + destroy() { + this.gpuLayout = null, this.layout = null, this.structsAndGroups = null, this.fragment = null, this.vertex = null, Ht[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(e) { + const t = `${e.vertex.source}:${e.fragment.source}:${e.fragment.entryPoint}:${e.vertex.entryPoint}`; + return Ht[t] || (Ht[t] = new ui(e), Ht[t]._cacheKey = t), Ht[t]; + } +} +const To = [ + "f32", + "i32", + "vec2", + "vec3", + "vec4", + "mat2x2", + "mat3x3", + "mat4x4", + "mat3x2", + "mat4x2", + "mat2x3", + "mat4x3", + "mat2x4", + "mat3x4", + "vec2", + "vec3", + "vec4" +], uh = To.reduce((i, e) => (i[e] = !0, i), {}); +function hh(i, e) { + switch (i) { + case "f32": + return 0; + case "vec2": + return new Float32Array(2 * e); + case "vec3": + return new Float32Array(3 * e); + case "vec4": + return new Float32Array(4 * e); + case "mat2x2": + return new Float32Array([ + 1, + 0, + 0, + 1 + ]); + case "mat3x3": + return new Float32Array([ + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 + ]); + case "mat4x4": + return new Float32Array([ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ]); + } + return null; +} +const Mo = class Po { + /** + * Create a new Uniform group + * @param uniformStructures - The structures of the uniform group + * @param options - The optional parameters of this uniform group + */ + constructor(e, t) { + this._touched = 0, this.uid = re("uniform"), this._resourceType = "uniformGroup", this._resourceId = re("resource"), this.isUniformGroup = !0, this._dirtyId = 0, this.destroyed = !1, t = { ...Po.defaultOptions, ...t }, this.uniformStructures = e; + const n = {}; + for (const s in e) { + const r = e[s]; + if (r.name = s, r.size = r.size ?? 1, !uh[r.type]) { + const a = r.type.match(/^array<(\w+(?:<\w+>)?),\s*(\d+)>$/); + if (a) { + const [, o, l] = a; + throw new Error( + `Uniform type ${r.type} is not supported. Use type: '${o}', size: ${l} instead.` + ); + } + throw new Error(`Uniform type ${r.type} is not supported. Supported uniform types are: ${To.join(", ")}`); + } + r.value ?? (r.value = hh(r.type, r.size)), n[s] = r.value; + } + this.uniforms = n, this._dirtyId = 1, this.ubo = t.ubo, this.isStatic = t.isStatic, this._signature = As(Object.keys(n).map( + (s) => `${s}-${e[s].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++; + } +}; +Mo.defaultOptions = { + /** if true the UniformGroup is handled as an Uniform buffer object. */ + ubo: !1, + /** if true, then you are responsible for when the data is uploaded to the GPU by calling `update()` */ + isStatic: !1 +}; +let Io = Mo; +class Wn { + /** + * Create a new instance eof the Bind Group. + * @param resources - The resources that are bound together for use by a shader. + */ + constructor(e) { + this.resources = /* @__PURE__ */ Object.create(null), this._dirty = !0; + let t = 0; + for (const n in e) { + const s = e[n]; + this.setResource(s, t++); + } + 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 = !1; + const e = []; + let t = 0; + for (const n in this.resources) + e[t++] = this.resources[n]._resourceId; + this._key = e.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(e, t) { + var s, r; + const n = this.resources[t]; + e !== n && (n && ((s = e.off) == null || s.call(e, "change", this.onResourceChange, this)), (r = e.on) == null || r.call(e, "change", this.onResourceChange, this), this.resources[t] = e, this._dirty = !0); + } + /** + * 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(e) { + return this.resources[e]; + } + /** + * Used internally to 'touch' each resource, to ensure that the GC + * knows that all resources in this bind group are still being used. + * @param tick - The current tick. + * @internal + */ + _touch(e) { + const t = this.resources; + for (const n in t) + t[n]._touched = e; + } + /** Destroys this bind group and removes all listeners. */ + destroy() { + var t; + const e = this.resources; + for (const n in e) { + const s = e[n]; + (t = s == null ? void 0 : s.off) == null || t.call(s, "change", this.onResourceChange, this); + } + this.resources = null; + } + onResourceChange(e) { + if (this._dirty = !0, e.destroyed) { + const t = this.resources; + for (const n in t) + t[n] === e && (t[n] = null); + } else + this._updateKey(); + } +} +var Ji = /* @__PURE__ */ ((i) => (i[i.WEBGL = 1] = "WEBGL", i[i.WEBGPU = 2] = "WEBGPU", i[i.BOTH = 3] = "BOTH", i))(Ji || {}); +class ks extends dt { + constructor(e) { + super(), this.uid = re("shader"), this._uniformBindMap = /* @__PURE__ */ Object.create(null), this._ownedBindGroups = []; + let { + gpuProgram: t, + glProgram: n, + groups: s, + resources: r, + compatibleRenderers: a, + groupMap: o + } = e; + this.gpuProgram = t, this.glProgram = n, a === void 0 && (a = 0, t && (a |= Ji.WEBGPU), n && (a |= Ji.WEBGL)), this.compatibleRenderers = a; + const l = {}; + if (!r && !s && (r = {}), r && s) + throw new Error("[Shader] Cannot have both resources and groups"); + if (!t && s && !o) + throw new Error("[Shader] No group map or WebGPU shader provided - consider using resources instead."); + if (!t && s && o) + for (const u in o) + for (const h in o[u]) { + const c = o[u][h]; + l[c] = { + group: u, + binding: h, + name: c + }; + } + else if (t && s && !o) { + const u = t.structsAndGroups.groups; + o = {}, u.forEach((h) => { + o[h.group] = o[h.group] || {}, o[h.group][h.binding] = h.name, l[h.name] = h; + }); + } else if (r) { + s = {}, o = {}, t && t.structsAndGroups.groups.forEach((c) => { + o[c.group] = o[c.group] || {}, o[c.group][c.binding] = c.name, l[c.name] = c; + }); + let u = 0; + for (const h in r) + l[h] || (s[99] || (s[99] = new Wn(), this._ownedBindGroups.push(s[99])), l[h] = { group: 99, binding: u, name: h }, o[99] = o[99] || {}, o[99][u] = h, u++); + for (const h in r) { + const c = h; + let f = r[h]; + !f.source && !f._resourceType && (f = new Io(f)); + const d = l[c]; + d && (s[d.group] || (s[d.group] = new Wn(), this._ownedBindGroups.push(s[d.group])), s[d.group].setResource(f, d.binding)); + } + } + this.groups = s, this._uniformBindMap = o, this.resources = this._buildResourceAccessor(s, l); + } + /** + * 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(e, t, n) { + var s, r; + (s = this._uniformBindMap)[t] || (s[t] = {}), (r = this._uniformBindMap[t])[n] || (r[n] = e), this.groups[t] || (this.groups[t] = new Wn(), this._ownedBindGroups.push(this.groups[t])); + } + _buildResourceAccessor(e, t) { + const n = {}; + for (const s in t) { + const r = t[s]; + Object.defineProperty(n, r.name, { + get() { + return e[r.group].getResource(r.binding); + }, + set(a) { + e[r.group].setResource(a, r.binding); + } + }); + } + return n; + } + /** + * 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(e = !1) { + var t, n; + this.emit("destroy", this), e && ((t = this.gpuProgram) == null || t.destroy(), (n = this.glProgram) == null || n.destroy()), this.gpuProgram = null, this.glProgram = null, this.removeAllListeners(), this._uniformBindMap = null, this._ownedBindGroups.forEach((s) => { + s.destroy(); + }), this._ownedBindGroups = null, this.resources = null, this.groups = null; + } + static from(e) { + const { gpu: t, gl: n, ...s } = e; + let r, a; + return t && (r = ui.from(t)), n && (a = $o.from(n)), new ks({ + gpuProgram: r, + glProgram: a, + ...s + }); + } +} +const es = []; +Ve.handleByNamedList(X.Environment, es); +async function ch(i) { + if (!i) + for (let e = 0; e < es.length; e++) { + const t = es[e]; + if (t.value.test()) { + await t.value.load(); + return; + } + } +} +let Vt; +function dh() { + if (typeof Vt == "boolean") + return Vt; + try { + Vt = new Function("param1", "param2", "param3", "return param1[param2] === param3;")({ a: "b" }, "a", "b") === !0; + } catch { + Vt = !1; + } + return Vt; +} +function mr(i, e, t = 2) { + const n = e && e.length, s = n ? e[0] * t : i.length; + let r = Ro(i, 0, s, t, !0); + const a = []; + if (!r || r.next === r.prev) return a; + let o, l, u; + if (n && (r = gh(i, e, r, t)), i.length > 80 * t) { + o = i[0], l = i[1]; + let h = o, c = l; + for (let f = t; f < s; f += t) { + const d = i[f], p = i[f + 1]; + d < o && (o = d), p < l && (l = p), d > h && (h = d), p > c && (c = p); + } + u = Math.max(h - o, c - l), u = u !== 0 ? 32767 / u : 0; + } + return _n(r, a, t, o, l, u, 0), a; +} +function Ro(i, e, t, n, s) { + let r; + if (s === Eh(i, e, t, n) > 0) + for (let a = e; a < t; a += n) r = gr(a / n | 0, i[a], i[a + 1], r); + else + for (let a = t - n; a >= e; a -= n) r = gr(a / n | 0, i[a], i[a + 1], r); + return r && Gt(r, r.next) && (mn(r), r = r.next), r; +} +function Ct(i, e) { + if (!i) return i; + e || (e = i); + let t = i, n; + do + if (n = !1, !t.steiner && (Gt(t, t.next) || ie(t.prev, t, t.next) === 0)) { + if (mn(t), t = e = t.prev, t === t.next) break; + n = !0; + } else + t = t.next; + while (n || t !== e); + return e; +} +function _n(i, e, t, n, s, r, a) { + if (!i) return; + !a && r && wh(i, n, s, r); + let o = i; + for (; i.prev !== i.next; ) { + const l = i.prev, u = i.next; + if (r ? _h(i, n, s, r) : fh(i)) { + e.push(l.i, i.i, u.i), mn(i), i = u.next, o = u.next; + continue; + } + if (i = u, i === o) { + a ? a === 1 ? (i = ph(Ct(i), e), _n(i, e, t, n, s, r, 2)) : a === 2 && mh(i, e, t, n, s, r) : _n(Ct(i), e, t, n, s, r, 1); + break; + } + } +} +function fh(i) { + const e = i.prev, t = i, n = i.next; + if (ie(e, t, n) >= 0) return !1; + const s = e.x, r = t.x, a = n.x, o = e.y, l = t.y, u = n.y, h = Math.min(s, r, a), c = Math.min(o, l, u), f = Math.max(s, r, a), d = Math.max(o, l, u); + let p = n.next; + for (; p !== e; ) { + if (p.x >= h && p.x <= f && p.y >= c && p.y <= d && nn(s, o, r, l, a, u, p.x, p.y) && ie(p.prev, p, p.next) >= 0) return !1; + p = p.next; + } + return !0; +} +function _h(i, e, t, n) { + const s = i.prev, r = i, a = i.next; + if (ie(s, r, a) >= 0) return !1; + const o = s.x, l = r.x, u = a.x, h = s.y, c = r.y, f = a.y, d = Math.min(o, l, u), p = Math.min(h, c, f), b = Math.max(o, l, u), m = Math.max(h, c, f), x = ts(d, p, e, t, n), g = ts(b, m, e, t, n); + let _ = i.prevZ, y = i.nextZ; + for (; _ && _.z >= x && y && y.z <= g; ) { + if (_.x >= d && _.x <= b && _.y >= p && _.y <= m && _ !== s && _ !== a && nn(o, h, l, c, u, f, _.x, _.y) && ie(_.prev, _, _.next) >= 0 || (_ = _.prevZ, y.x >= d && y.x <= b && y.y >= p && y.y <= m && y !== s && y !== a && nn(o, h, l, c, u, f, y.x, y.y) && ie(y.prev, y, y.next) >= 0)) return !1; + y = y.nextZ; + } + for (; _ && _.z >= x; ) { + if (_.x >= d && _.x <= b && _.y >= p && _.y <= m && _ !== s && _ !== a && nn(o, h, l, c, u, f, _.x, _.y) && ie(_.prev, _, _.next) >= 0) return !1; + _ = _.prevZ; + } + for (; y && y.z <= g; ) { + if (y.x >= d && y.x <= b && y.y >= p && y.y <= m && y !== s && y !== a && nn(o, h, l, c, u, f, y.x, y.y) && ie(y.prev, y, y.next) >= 0) return !1; + y = y.nextZ; + } + return !0; +} +function ph(i, e) { + let t = i; + do { + const n = t.prev, s = t.next.next; + !Gt(n, s) && Lo(n, t, t.next, s) && pn(n, s) && pn(s, n) && (e.push(n.i, t.i, s.i), mn(t), mn(t.next), t = i = s), t = t.next; + } while (t !== i); + return Ct(t); +} +function mh(i, e, t, n, s, r) { + let a = i; + do { + let o = a.next.next; + for (; o !== a.prev; ) { + if (a.i !== o.i && kh(a, o)) { + let l = No(a, o); + a = Ct(a, a.next), l = Ct(l, l.next), _n(a, e, t, n, s, r, 0), _n(l, e, t, n, s, r, 0); + return; + } + o = o.next; + } + a = a.next; + } while (a !== i); +} +function gh(i, e, t, n) { + const s = []; + for (let r = 0, a = e.length; r < a; r++) { + const o = e[r] * n, l = r < a - 1 ? e[r + 1] * n : i.length, u = Ro(i, o, l, n, !1); + u === u.next && (u.steiner = !0), s.push(Ah(u)); + } + s.sort(yh); + for (let r = 0; r < s.length; r++) + t = bh(s[r], t); + return t; +} +function yh(i, e) { + let t = i.x - e.x; + if (t === 0 && (t = i.y - e.y, t === 0)) { + const n = (i.next.y - i.y) / (i.next.x - i.x), s = (e.next.y - e.y) / (e.next.x - e.x); + t = n - s; + } + return t; +} +function bh(i, e) { + const t = xh(i, e); + if (!t) + return e; + const n = No(t, i); + return Ct(n, n.next), Ct(t, t.next); +} +function xh(i, e) { + let t = e; + const n = i.x, s = i.y; + let r = -1 / 0, a; + if (Gt(i, t)) return t; + do { + if (Gt(i, t.next)) return t.next; + if (s <= t.y && s >= t.next.y && t.next.y !== t.y) { + const c = t.x + (s - t.y) * (t.next.x - t.x) / (t.next.y - t.y); + if (c <= n && c > r && (r = c, a = t.x < t.next.x ? t : t.next, c === n)) + return a; + } + t = t.next; + } while (t !== e); + if (!a) return null; + const o = a, l = a.x, u = a.y; + let h = 1 / 0; + t = a; + do { + if (n >= t.x && t.x >= l && n !== t.x && Bo(s < u ? n : r, s, l, u, s < u ? r : n, s, t.x, t.y)) { + const c = Math.abs(s - t.y) / (n - t.x); + pn(t, i) && (c < h || c === h && (t.x > a.x || t.x === a.x && vh(a, t))) && (a = t, h = c); + } + t = t.next; + } while (t !== o); + return a; +} +function vh(i, e) { + return ie(i.prev, i, e.prev) < 0 && ie(e.next, i, i.next) < 0; +} +function wh(i, e, t, n) { + let s = i; + do + s.z === 0 && (s.z = ts(s.x, s.y, e, t, n)), s.prevZ = s.prev, s.nextZ = s.next, s = s.next; + while (s !== i); + s.prevZ.nextZ = null, s.prevZ = null, Ch(s); +} +function Ch(i) { + let e, t = 1; + do { + let n = i, s; + i = null; + let r = null; + for (e = 0; n; ) { + e++; + let a = n, o = 0; + for (let u = 0; u < t && (o++, a = a.nextZ, !!a); u++) + ; + let l = t; + for (; o > 0 || l > 0 && a; ) + o !== 0 && (l === 0 || !a || n.z <= a.z) ? (s = n, n = n.nextZ, o--) : (s = a, a = a.nextZ, l--), r ? r.nextZ = s : i = s, s.prevZ = r, r = s; + n = a; + } + r.nextZ = null, t *= 2; + } while (e > 1); + return i; +} +function ts(i, e, t, n, s) { + return i = (i - t) * s | 0, e = (e - n) * s | 0, i = (i | i << 8) & 16711935, i = (i | i << 4) & 252645135, i = (i | i << 2) & 858993459, i = (i | i << 1) & 1431655765, e = (e | e << 8) & 16711935, e = (e | e << 4) & 252645135, e = (e | e << 2) & 858993459, e = (e | e << 1) & 1431655765, i | e << 1; +} +function Ah(i) { + let e = i, t = i; + do + (e.x < t.x || e.x === t.x && e.y < t.y) && (t = e), e = e.next; + while (e !== i); + return t; +} +function Bo(i, e, t, n, s, r, a, o) { + return (s - a) * (e - o) >= (i - a) * (r - o) && (i - a) * (n - o) >= (t - a) * (e - o) && (t - a) * (r - o) >= (s - a) * (n - o); +} +function nn(i, e, t, n, s, r, a, o) { + return !(i === a && e === o) && Bo(i, e, t, n, s, r, a, o); +} +function kh(i, e) { + return i.next.i !== e.i && i.prev.i !== e.i && !Dh(i, e) && // doesn't intersect other edges + (pn(i, e) && pn(e, i) && Sh(i, e) && // locally visible + (ie(i.prev, i, e.prev) || ie(i, e.prev, e)) || // does not create opposite-facing sectors + Gt(i, e) && ie(i.prev, i, i.next) > 0 && ie(e.prev, e, e.next) > 0); +} +function ie(i, e, t) { + return (e.y - i.y) * (t.x - e.x) - (e.x - i.x) * (t.y - e.y); +} +function Gt(i, e) { + return i.x === e.x && i.y === e.y; +} +function Lo(i, e, t, n) { + const s = Pn(ie(i, e, t)), r = Pn(ie(i, e, n)), a = Pn(ie(t, n, i)), o = Pn(ie(t, n, e)); + return !!(s !== r && a !== o || s === 0 && Mn(i, t, e) || r === 0 && Mn(i, n, e) || a === 0 && Mn(t, i, n) || o === 0 && Mn(t, e, n)); +} +function Mn(i, e, t) { + return e.x <= Math.max(i.x, t.x) && e.x >= Math.min(i.x, t.x) && e.y <= Math.max(i.y, t.y) && e.y >= Math.min(i.y, t.y); +} +function Pn(i) { + return i > 0 ? 1 : i < 0 ? -1 : 0; +} +function Dh(i, e) { + let t = i; + do { + if (t.i !== i.i && t.next.i !== i.i && t.i !== e.i && t.next.i !== e.i && Lo(t, t.next, i, e)) return !0; + t = t.next; + } while (t !== i); + return !1; +} +function pn(i, e) { + return ie(i.prev, i, i.next) < 0 ? ie(i, e, i.next) >= 0 && ie(i, i.prev, e) >= 0 : ie(i, e, i.prev) < 0 || ie(i, i.next, e) < 0; +} +function Sh(i, e) { + let t = i, n = !1; + const s = (i.x + e.x) / 2, r = (i.y + e.y) / 2; + do + t.y > r != t.next.y > r && t.next.y !== t.y && s < (t.next.x - t.x) * (r - t.y) / (t.next.y - t.y) + t.x && (n = !n), t = t.next; + while (t !== i); + return n; +} +function No(i, e) { + const t = ns(i.i, i.x, i.y), n = ns(e.i, e.x, e.y), s = i.next, r = e.prev; + return i.next = e, e.prev = i, t.next = s, s.prev = t, n.next = t, t.prev = n, r.next = n, n.prev = r, n; +} +function gr(i, e, t, n) { + const s = ns(i, e, t); + return n ? (s.next = n.next, s.prev = n, n.next.prev = s, n.next = s) : (s.prev = s, s.next = s), s; +} +function mn(i) { + i.next.prev = i.prev, i.prev.next = i.next, i.prevZ && (i.prevZ.nextZ = i.nextZ), i.nextZ && (i.nextZ.prevZ = i.prevZ); +} +function ns(i, e, t) { + return { + i, + // vertex index in coordinates array + x: e, + y: t, + // 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: !1 + // indicates whether this is a steiner point + }; +} +function Eh(i, e, t, n) { + let s = 0; + for (let r = e, a = t - n; r < t; r += n) + s += (i[a] - i[r]) * (i[r + 1] + i[a + 1]), a = r; + return s; +} +const Fh = mr.default || mr; +var Oo = /* @__PURE__ */ ((i) => (i[i.NONE = 0] = "NONE", i[i.COLOR = 16384] = "COLOR", i[i.STENCIL = 1024] = "STENCIL", i[i.DEPTH = 256] = "DEPTH", i[i.COLOR_DEPTH = 16640] = "COLOR_DEPTH", i[i.COLOR_STENCIL = 17408] = "COLOR_STENCIL", i[i.DEPTH_STENCIL = 1280] = "DEPTH_STENCIL", i[i.ALL = 17664] = "ALL", i))(Oo || {}); +class $h { + /** + * @param name - The function name that will be executed on the listeners added to this Runner. + */ + constructor(e) { + this.items = [], this._name = e; + } + /* 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(e, t, n, s, r, a, o, l) { + const { name: u, items: h } = this; + for (let c = 0, f = h.length; c < f; c++) + h[c][u](e, t, n, s, r, a, o, l); + 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(e) { + return e[this._name] && (this.remove(e), this.items.push(e)), this; + } + /** + * Remove a single listener from the dispatch queue. + * @param {any} item - The listener that you would like to remove. + */ + remove(e) { + const t = this.items.indexOf(e); + return t !== -1 && this.items.splice(t, 1), this; + } + /** + * Check to see if the listener is already in the Runner + * @param {any} item - The listener that you would like to check. + */ + contains(e) { + return this.items.indexOf(e) !== -1; + } + /** Remove all listeners from the Runner */ + removeAll() { + return this.items.length = 0, 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; + } +} +const Th = [ + "init", + "destroy", + "contextChange", + "resolutionChange", + "resetState", + "renderEnd", + "renderStart", + "render", + "update", + "postrender", + "prerender" +], Go = class zo extends dt { + /** + * 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(e) { + super(), this.uid = re("renderer"), this.runners = /* @__PURE__ */ Object.create(null), this.renderPipes = /* @__PURE__ */ Object.create(null), this._initOptions = {}, this._systemsHash = /* @__PURE__ */ Object.create(null), this.type = e.type, this.name = e.name, this.config = e; + const t = [...Th, ...this.config.runners ?? []]; + this._addRunners(...t), this._unsafeEvalCheck(); + } + /** + * Initialize the renderer. + * @param options - The options to use to create the renderer. + */ + async init(e = {}) { + const t = e.skipExtensionImports === !0 ? !0 : e.manageImports === !1; + await ch(t), this._addSystems(this.config.systems), this._addPipes(this.config.renderPipes, this.config.renderPipeAdaptors); + for (const n in this._systemsHash) + e = { ...this._systemsHash[n].constructor.defaultOptions, ...e }; + e = { ...zo.defaultOptions, ...e }, this._roundPixels = e.roundPixels ? 1 : 0; + for (let n = 0; n < this.runners.init.items.length; n++) + await this.runners.init.items[n].init(e); + this._initOptions = e; + } + render(e, t) { + let n = e; + if (n instanceof Dt && (n = { container: n }, t && (j(le, "passing a second argument is deprecated, please use render options instead"), n.target = t.renderTexture)), n.target || (n.target = this.view.renderTarget), n.target === this.view.renderTarget && (this._lastObjectRendered = n.container, n.clearColor ?? (n.clearColor = this.background.colorRgba), n.clear ?? (n.clear = this.background.clearBeforeRender)), n.clearColor) { + const s = Array.isArray(n.clearColor) && n.clearColor.length === 4; + n.clearColor = s ? n.clearColor : qe.shared.setValue(n.clearColor).toArray(); + } + n.transform || (n.container.updateLocalTransform(), n.transform = n.container.localTransform), n.container.visible && (n.container.enableRenderGroup(), this.runners.prerender.emit(n), this.runners.renderStart.emit(n), this.runners.render.emit(n), this.runners.renderEnd.emit(n), this.runners.postrender.emit(n)); + } + /** + * 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(e, t, n) { + const s = this.view.resolution; + this.view.resize(e, t, n), this.emit("resize", this.view.screen.width, this.view.screen.height, this.view.resolution), n !== void 0 && n !== s && this.runners.resolutionChange.emit(n); + } + /** + * 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(e = {}) { + const t = this; + e.target || (e.target = t.renderTarget.renderTarget), e.clearColor || (e.clearColor = this.background.colorRgba), e.clear ?? (e.clear = Oo.ALL); + const { clear: n, clearColor: s, target: r } = e; + qe.shared.setValue(s ?? this.background.colorRgba), t.renderTarget.clear(r, n, qe.shared.toArray()); + } + /** The resolution / device pixel ratio of the renderer. */ + get resolution() { + return this.view.resolution; + } + set resolution(e) { + this.view.resolution = e, this.runners.resolutionChange.emit(e); + } + /** + * 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() { + return this.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(...e) { + e.forEach((t) => { + this.runners[t] = new $h(t); + }); + } + _addSystems(e) { + let t; + for (t in e) { + const n = e[t]; + this._addSystem(n.value, n.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(e, t) { + const n = new e(this); + if (this[t]) + throw new Error(`Whoops! The name "${t}" is already in use`); + this[t] = n, this._systemsHash[t] = n; + for (const s in this.runners) + this.runners[s].add(n); + return this; + } + _addPipes(e, t) { + const n = t.reduce((s, r) => (s[r.name] = r.value, s), {}); + e.forEach((s) => { + const r = s.value, a = s.name, o = n[a]; + this.renderPipes[a] = new r( + this, + o ? new o() : null + ), this.runners.destroy.add(this.renderPipes[a]); + }); + } + destroy(e = !1) { + this.runners.destroy.items.reverse(), this.runners.destroy.emit(e), Object.values(this.runners).forEach((t) => { + t.destroy(); + }), (e === !0 || typeof e == "object" && e.releaseGlobalResources) && oi.release(), 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(e) { + return this.textureGenerator.generateTexture(e); + } + /** + * 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 (!dh()) + 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(); + } +}; +Go.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: !1, + /** + * Should round pixels be forced when rendering? + * @default false + */ + roundPixels: !1 +}; +let qo = Go, In; +function Mh(i) { + return In !== void 0 || (In = (() => { + var t; + const e = { + stencil: !0, + failIfMajorPerformanceCaveat: i ?? qo.defaultOptions.failIfMajorPerformanceCaveat + }; + try { + if (!mt.get().getWebGLRenderingContext()) + return !1; + let s = mt.get().createCanvas().getContext("webgl", e); + const r = !!((t = s == null ? void 0 : s.getContextAttributes()) != null && t.stencil); + if (s) { + const a = s.getExtension("WEBGL_lose_context"); + a && a.loseContext(); + } + return s = null, r; + } catch { + return !1; + } + })()), In; +} +let Rn; +async function Ph(i = {}) { + return Rn !== void 0 || (Rn = await (async () => { + const e = mt.get().getNavigator().gpu; + if (!e) + return !1; + try { + return await (await e.requestAdapter(i)).requestDevice(), !0; + } catch { + return !1; + } + })()), Rn; +} +const yr = ["webgl", "webgpu", "canvas"]; +async function Ih(i) { + let e = []; + i.preference ? (e.push(i.preference), yr.forEach((r) => { + r !== i.preference && e.push(r); + })) : e = yr.slice(); + let t, n = {}; + for (let r = 0; r < e.length; r++) { + const a = e[r]; + if (a === "webgpu" && await Ph()) { + const { WebGPURenderer: o } = await import("./WebGPURenderer-scPngJ2c.js"); + t = o, n = { ...i, ...i.webgpu }; + break; + } else if (a === "webgl" && Mh( + i.failIfMajorPerformanceCaveat ?? qo.defaultOptions.failIfMajorPerformanceCaveat + )) { + const { WebGLRenderer: o } = await import("./WebGLRenderer-DDL2mbll.js"); + t = o, n = { ...i, ...i.webgl }; + break; + } else if (a === "canvas") + throw n = { ...i }, new Error("CanvasRenderer is not yet implemented"); + } + if (delete n.webgpu, delete n.webgl, !t) + throw new Error("No available renderer for the current environment"); + const s = new t(); + return await s.init(n), s; +} +const Uo = "8.13.2"; +class Ho { + static init() { + var e; + (e = globalThis.__PIXI_APP_INIT__) == null || e.call(globalThis, this, Uo); + } + static destroy() { + } +} +Ho.extension = X.Application; +class Rh { + constructor(e) { + this._renderer = e; + } + init() { + var e; + (e = globalThis.__PIXI_RENDERER_INIT__) == null || e.call(globalThis, this._renderer, Uo); + } + destroy() { + this._renderer = null; + } +} +Rh.extension = { + type: [ + X.WebGLSystem, + X.WebGPUSystem + ], + name: "initHook", + priority: -10 +}; +const Vo = class is { + constructor(...e) { + this.stage = new Dt(), e[0] !== void 0 && j(le, "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(e) { + e = { ...e }, this.renderer = await Ih(e), is._plugins.forEach((t) => { + t.init.call(this, e); + }); + } + /** + * 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() { + return j(le, "Application.view is deprecated, please use Application.canvas instead."), 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(e = !1, t = !1) { + const n = is._plugins.slice(0); + n.reverse(), n.forEach((s) => { + s.destroy.call(this); + }), this.stage.destroy(t), this.stage = null, this.renderer.destroy(e), this.renderer = null; + } +}; +Vo._plugins = []; +let Yo = Vo; +Ve.handleByList(X.Application, Yo._plugins); +Ve.add(Ho); +const br = [{ offset: 0, color: "white" }, { offset: 1, color: "black" }], Ds = class ss { + constructor(...e) { + this.uid = re("fillGradient"), this._tick = 0, this.type = "linear", this.colorStops = []; + let t = Bh(e); + t = { ...t.type === "radial" ? ss.defaultRadialOptions : ss.defaultLinearOptions, ...ja(t) }, this._textureSize = t.textureSize, this._wrapMode = t.wrapMode, t.type === "radial" ? (this.center = t.center, this.outerCenter = t.outerCenter ?? this.center, this.innerRadius = t.innerRadius, this.outerRadius = t.outerRadius, this.scale = t.scale, this.rotation = t.rotation) : (this.start = t.start, this.end = t.end), this.textureSpace = t.textureSpace, this.type = t.type, t.colorStops.forEach((s) => { + this.addColorStop(s.offset, s.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(e, t) { + return this.colorStops.push({ offset: e, color: qe.shared.setValue(t).toHexa() }), 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: e, y: t } = this.start, { x: n, y: s } = this.end, r = n - e, a = s - t; + const o = r < 0 || a < 0; + if (this._wrapMode === "clamp-to-edge") { + if (r < 0) { + const m = e; + e = n, n = m, r *= -1; + } + if (a < 0) { + const m = t; + t = s, s = m, a *= -1; + } + } + const l = this.colorStops.length ? this.colorStops : br, u = this._textureSize, { canvas: h, context: c } = vr(u, 1), f = o ? c.createLinearGradient(this._textureSize, 0, 0, 0) : c.createLinearGradient(0, 0, this._textureSize, 0); + xr(f, l), c.fillStyle = f, c.fillRect(0, 0, u, 1), this.texture = new W({ + source: new Qn({ + resource: h, + addressMode: this._wrapMode + }) + }); + const d = Math.sqrt(r * r + a * a), p = Math.atan2(a, r), b = new q(); + b.scale(d / u, 1), b.rotate(p), b.translate(e, t), this.textureSpace === "local" && b.scale(u, u), this.transform = b; + } + /** + * Builds the internal texture and transform for the gradient. + * Called automatically when the gradient is first used. + * @internal + */ + buildGradient() { + this.texture || this._tick++, this.type === "linear" ? this.buildLinearGradient() : 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 e = this.colorStops.length ? this.colorStops : br, t = this._textureSize, { canvas: n, context: s } = vr(t, t), { x: r, y: a } = this.center, { x: o, y: l } = this.outerCenter, u = this.innerRadius, h = this.outerRadius, c = o - h, f = l - h, d = t / (h * 2), p = (r - c) * d, b = (a - f) * d, m = s.createRadialGradient( + p, + b, + u * d, + (o - c) * d, + (l - f) * d, + h * d + ); + xr(m, e), s.fillStyle = e[e.length - 1].color, s.fillRect(0, 0, t, t), s.fillStyle = m, s.translate(p, b), s.rotate(this.rotation), s.scale(1, this.scale), s.translate(-p, -b), s.fillRect(0, 0, t, t), this.texture = new W({ + source: new Qn({ + resource: n, + addressMode: this._wrapMode + }) + }); + const x = new q(); + x.scale(1 / d, 1 / d), x.translate(c, f), this.textureSpace === "local" && x.scale(t, t), this.transform = x; + } + /** Destroys the gradient, releasing resources. This will also destroy the internal texture. */ + destroy() { + var e; + (e = this.texture) == null || e.destroy(!0), 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}`; + } +}; +Ds.defaultLinearOptions = { + start: { x: 0, y: 0 }, + end: { x: 0, y: 1 }, + colorStops: [], + textureSpace: "local", + type: "linear", + textureSize: 256, + wrapMode: "clamp-to-edge" +}; +Ds.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 xn = Ds; +function xr(i, e) { + for (let t = 0; t < e.length; t++) { + const n = e[t]; + i.addColorStop(n.offset, n.color); + } +} +function vr(i, e) { + const t = mt.get().createCanvas(i, e), n = t.getContext("2d"); + return { canvas: t, context: n }; +} +function Bh(i) { + let e = i[0] ?? {}; + return (typeof e == "number" || i[1]) && (j("8.5.2", "use options object instead"), e = { + type: "linear", + start: { x: i[0], y: i[1] }, + end: { x: i[2], y: i[3] }, + textureSpace: i[4], + textureSize: i[5] ?? xn.defaultLinearOptions.textureSize + }), e; +} +const wr = { + 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 Lh { + constructor(e, t) { + this.uid = re("fillPattern"), this._tick = 0, this.transform = new q(), this.texture = e, this.transform.scale( + 1 / e.frame.width, + 1 / e.frame.height + ), t && (e.source.style.addressModeU = wr[t].addressModeU, e.source.style.addressModeV = wr[t].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(e) { + const t = this.texture; + this.transform.copyFrom(e), this.transform.invert(), this.transform.scale( + 1 / t.frame.width, + 1 / t.frame.height + ), this._tick++; + } + /** Internal texture used to render the gradient */ + get texture() { + return this._texture; + } + set texture(e) { + this._texture !== e && (this._texture = e, 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(!0), this.texture = null; + } +} +var Nh = Gh, Di = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }, Oh = /([astvzqmhlc])([^astvzqmhlc]*)/ig; +function Gh(i) { + var e = []; + return i.replace(Oh, function(t, n, s) { + var r = n.toLowerCase(); + for (s = qh(s), r == "m" && s.length > 2 && (e.push([n].concat(s.splice(0, 2))), r = "l", n = n == "m" ? "l" : "L"); ; ) { + if (s.length == Di[r]) + return s.unshift(n), e.push(s); + if (s.length < Di[r]) throw new Error("malformed path data"); + e.push([n].concat(s.splice(0, Di[r]))); + } + }), e; +} +var zh = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig; +function qh(i) { + var e = i.match(zh); + return e ? e.map(Number) : []; +} +const Uh = /* @__PURE__ */ Ha(Nh); +function Hh(i, e) { + const t = Uh(i), n = []; + let s = null, r = 0, a = 0; + for (let o = 0; o < t.length; o++) { + const l = t[o], u = l[0], h = l; + switch (u) { + case "M": + r = h[1], a = h[2], e.moveTo(r, a); + break; + case "m": + r += h[1], a += h[2], e.moveTo(r, a); + break; + case "H": + r = h[1], e.lineTo(r, a); + break; + case "h": + r += h[1], e.lineTo(r, a); + break; + case "V": + a = h[1], e.lineTo(r, a); + break; + case "v": + a += h[1], e.lineTo(r, a); + break; + case "L": + r = h[1], a = h[2], e.lineTo(r, a); + break; + case "l": + r += h[1], a += h[2], e.lineTo(r, a); + break; + case "C": + r = h[5], a = h[6], e.bezierCurveTo( + h[1], + h[2], + // First control point + h[3], + h[4], + // Second control point + r, + a + // End point + ); + break; + case "c": + e.bezierCurveTo( + r + h[1], + a + h[2], + // First control point + r + h[3], + a + h[4], + // Second control point + r + h[5], + a + h[6] + // End point + ), r += h[5], a += h[6]; + break; + case "S": + r = h[3], a = h[4], e.bezierCurveToShort( + h[1], + h[2], + // Control point + r, + a + // End point + ); + break; + case "s": + e.bezierCurveToShort( + r + h[1], + a + h[2], + // Control point + r + h[3], + a + h[4] + // End point + ), r += h[3], a += h[4]; + break; + case "Q": + r = h[3], a = h[4], e.quadraticCurveTo( + h[1], + h[2], + // Control point + r, + a + // End point + ); + break; + case "q": + e.quadraticCurveTo( + r + h[1], + a + h[2], + // Control point + r + h[3], + a + h[4] + // End point + ), r += h[3], a += h[4]; + break; + case "T": + r = h[1], a = h[2], e.quadraticCurveToShort( + r, + a + // End point + ); + break; + case "t": + r += h[1], a += h[2], e.quadraticCurveToShort( + r, + a + // End point + ); + break; + case "A": + r = h[6], a = h[7], e.arcToSvg( + h[1], + // rx + h[2], + // ry + h[3], + // x-axis-rotation + h[4], + // large-arc-flag + h[5], + // sweep-flag + r, + a + // End point + ); + break; + case "a": + r += h[6], a += h[7], e.arcToSvg( + h[1], + // rx + h[2], + // ry + h[3], + // x-axis-rotation + h[4], + // large-arc-flag + h[5], + // sweep-flag + r, + a + // End point + ); + break; + case "Z": + case "z": + e.closePath(), n.length > 0 && (s = n.pop(), s ? (r = s.startX, a = s.startY) : (r = 0, a = 0)), s = null; + break; + default: + Fe(`Unknown SVG path command: ${u}`); + } + u !== "Z" && u !== "z" && s === null && (s = { startX: r, startY: a }, n.push(s)); + } + return e; +} +class Ss { + /** + * @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(e = 0, t = 0, n = 0) { + this.type = "circle", this.x = e, this.y = t, this.radius = n; + } + /** + * 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 Ss(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(e, t) { + if (this.radius <= 0) + return !1; + const n = this.radius * this.radius; + let s = this.x - e, r = this.y - t; + return s *= s, r *= r, s + r <= n; + } + /** + * 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(e, t, n, s = 0.5) { + if (this.radius === 0) + return !1; + const r = this.x - e, a = this.y - t, o = this.radius, l = (1 - s) * n, u = Math.sqrt(r * r + a * a); + return u <= o + l && u > o - (n - l); + } + /** + * 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(e) { + return e || (e = new ce()), e.x = this.x - this.radius, e.y = this.y - this.radius, e.width = this.radius * 2, e.height = this.radius * 2, e; + } + /** + * 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(e) { + return this.x = e.x, this.y = e.y, this.radius = e.radius, 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(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:Circle x=${this.x} y=${this.y} radius=${this.radius}]`; + } +} +class Es { + /** + * @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(e = 0, t = 0, n = 0, s = 0) { + this.type = "ellipse", this.x = e, this.y = t, this.halfWidth = n, this.halfHeight = s; + } + /** + * 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 Es(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(e, t) { + if (this.halfWidth <= 0 || this.halfHeight <= 0) + return !1; + let n = (e - this.x) / this.halfWidth, s = (t - this.y) / this.halfHeight; + return n *= n, s *= s, n + s <= 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(e, t, n, s = 0.5) { + const { halfWidth: r, halfHeight: a } = this; + if (r <= 0 || a <= 0) + return !1; + const o = n * (1 - s), l = n - o, u = r - l, h = a - l, c = r + o, f = a + o, d = e - this.x, p = t - this.y, b = d * d / (u * u) + p * p / (h * h), m = d * d / (c * c) + p * p / (f * f); + return b > 1 && m <= 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(e) { + return e || (e = new ce()), e.x = this.x - this.halfWidth, e.y = this.y - this.halfHeight, e.width = this.halfWidth * 2, e.height = this.halfHeight * 2, e; + } + /** + * 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(e) { + return this.x = e.x, this.y = e.y, this.halfWidth = e.halfWidth, this.halfHeight = e.halfHeight, 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(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:Ellipse x=${this.x} y=${this.y} halfWidth=${this.halfWidth} halfHeight=${this.halfHeight}]`; + } +} +function Vh(i, e, t, n, s, r) { + const a = i - t, o = e - n, l = s - t, u = r - n, h = a * l + o * u, c = l * l + u * u; + let f = -1; + c !== 0 && (f = h / c); + let d, p; + f < 0 ? (d = t, p = n) : f > 1 ? (d = s, p = r) : (d = t + f * l, p = n + f * u); + const b = i - d, m = e - p; + return b * b + m * m; +} +let Yh, Xh; +class an { + /** + * @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(...e) { + this.type = "polygon"; + let t = Array.isArray(e[0]) ? e[0] : e; + if (typeof t[0] != "number") { + const n = []; + for (let s = 0, r = t.length; s < r; s++) + n.push(t[s].x, t[s].y); + t = n; + } + this.points = t, this.closePath = !0; + } + /** + * 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 e = 0; + const t = this.points, n = t.length; + for (let s = 0; s < n; s += 2) { + const r = t[s], a = t[s + 1], o = t[(s + 2) % n], l = t[(s + 3) % n]; + e += (o - r) * (l + a); + } + return e < 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(e) { + const t = this.getBounds(Yh), n = e.getBounds(Xh); + if (!t.containsRect(n)) + return !1; + const s = e.points; + for (let r = 0; r < s.length; r += 2) { + const a = s[r], o = s[r + 1]; + if (!this.contains(a, o)) + return !1; + } + return !0; + } + /** + * 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 e = this.points.slice(), t = new an(e); + return t.closePath = this.closePath, t; + } + /** + * 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(e, t) { + let n = !1; + const s = this.points.length / 2; + for (let r = 0, a = s - 1; r < s; a = r++) { + const o = this.points[r * 2], l = this.points[r * 2 + 1], u = this.points[a * 2], h = this.points[a * 2 + 1]; + l > t != h > t && e < (u - o) * ((t - l) / (h - l)) + o && (n = !n); + } + return n; + } + /** + * 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(e, t, n, s = 0.5) { + const r = n * n, a = r * (1 - s), o = r - a, { points: l } = this, u = l.length - (this.closePath ? 0 : 2); + for (let h = 0; h < u; h += 2) { + const c = l[h], f = l[h + 1], d = l[(h + 2) % l.length], p = l[(h + 3) % l.length], b = Vh(e, t, c, f, d, p), m = Math.sign((d - c) * (t - f) - (p - f) * (e - c)); + if (b <= (m < 0 ? o : a)) + return !0; + } + return !1; + } + /** + * 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(e) { + e || (e = new ce()); + const t = this.points; + let n = 1 / 0, s = -1 / 0, r = 1 / 0, a = -1 / 0; + for (let o = 0, l = t.length; o < l; o += 2) { + const u = t[o], h = t[o + 1]; + n = u < n ? u : n, s = u > s ? u : s, r = h < r ? h : r, a = h > a ? h : a; + } + return e.x = n, e.width = s - n, e.y = r, e.height = a - r, e; + } + /** + * 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(e) { + return this.points = e.points.slice(), this.closePath = e.closePath, 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(e) { + return e.copyFrom(this), e; + } + toString() { + return `[pixi.js/math:PolygoncloseStroke=${this.closePath}points=${this.points.reduce((e, t) => `${e}, ${t}`, "")}]`; + } + /** + * 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() { + return j("8.11.0", "Polygon.lastX is deprecated, please use Polygon.lastX instead."), 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() { + return j("8.11.0", "Polygon.y is deprecated, please use Polygon.lastY instead."), 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]; + } +} +const Bn = (i, e, t, n, s, r, a) => { + const o = i - t, l = e - n, u = Math.sqrt(o * o + l * l); + return u >= s - r && u <= s + a; +}; +class Fs { + /** + * @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(e = 0, t = 0, n = 0, s = 0, r = 20) { + this.type = "roundedRectangle", this.x = e, this.y = t, this.width = n, this.height = s, this.radius = r; + } + /** + * 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(e) { + return e || (e = new ce()), e.x = this.x, e.y = this.y, e.width = this.width, e.height = this.height, e; + } + /** + * 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 Fs(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(e) { + return this.x = e.x, this.y = e.y, this.width = e.width, this.height = e.height, 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(e) { + return e.copyFrom(this), e; + } + /** + * 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(e, t) { + if (this.width <= 0 || this.height <= 0) + return !1; + if (e >= this.x && e <= this.x + this.width && t >= this.y && t <= this.y + this.height) { + const n = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2)); + if (t >= this.y + n && t <= this.y + this.height - n || e >= this.x + n && e <= this.x + this.width - n) + return !0; + let s = e - (this.x + n), r = t - (this.y + n); + const a = n * n; + if (s * s + r * r <= a || (s = e - (this.x + this.width - n), s * s + r * r <= a) || (r = t - (this.y + this.height - n), s * s + r * r <= a) || (s = e - (this.x + n), s * s + r * r <= a)) + return !0; + } + return !1; + } + /** + * 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(e, t, n, s = 0.5) { + const { x: r, y: a, width: o, height: l, radius: u } = this, h = n * (1 - s), c = n - h, f = r + u, d = a + u, p = o - u * 2, b = l - u * 2, m = r + o, x = a + l; + return (e >= r - h && e <= r + c || e >= m - c && e <= m + h) && t >= d && t <= d + b || (t >= a - h && t <= a + c || t >= x - c && t <= x + h) && e >= f && e <= f + p ? !0 : ( + // Top-left + e < f && t < d && Bn( + e, + t, + f, + d, + u, + c, + h + ) || e > m - u && t < d && Bn( + e, + t, + m - u, + d, + u, + c, + h + ) || e > m - u && t > x - u && Bn( + e, + t, + m - u, + x - u, + u, + c, + h + ) || e < f && t > x - u && Bn( + e, + t, + f, + x - u, + u, + c, + h + ) + ); + } + toString() { + return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`; + } +} +const Xo = {}; +function jh(i, e, t) { + let n = 2166136261; + for (let s = 0; s < e; s++) + n ^= i[s].uid, n = Math.imul(n, 16777619), n >>>= 0; + return Xo[n] || Wh(i, e, n, t); +} +function Wh(i, e, t, n) { + const s = {}; + let r = 0; + for (let o = 0; o < n; o++) { + const l = o < e ? i[o] : W.EMPTY.source; + s[r++] = l.source, s[r++] = l.style; + } + const a = new Wn(s); + return Xo[t] = a, a; +} +class Cr { + constructor(e) { + typeof e == "number" ? this.rawBinaryData = new ArrayBuffer(e) : e instanceof Uint8Array ? this.rawBinaryData = e.buffer : this.rawBinaryData = e, 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() { + return this._int8View || (this._int8View = new Int8Array(this.rawBinaryData)), this._int8View; + } + /** View on the raw binary data as a `Uint8Array`. */ + get uint8View() { + return this._uint8View || (this._uint8View = new Uint8Array(this.rawBinaryData)), this._uint8View; + } + /** View on the raw binary data as a `Int16Array`. */ + get int16View() { + return this._int16View || (this._int16View = new Int16Array(this.rawBinaryData)), this._int16View; + } + /** View on the raw binary data as a `Int32Array`. */ + get int32View() { + return this._int32View || (this._int32View = new Int32Array(this.rawBinaryData)), this._int32View; + } + /** View on the raw binary data as a `Float64Array`. */ + get float64View() { + return this._float64Array || (this._float64Array = new Float64Array(this.rawBinaryData)), this._float64Array; + } + /** View on the raw binary data as a `BigUint64Array`. */ + get bigUint64View() { + return this._bigUint64Array || (this._bigUint64Array = new BigUint64Array(this.rawBinaryData)), 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(e) { + return this[`${e}View`]; + } + /** Destroys all buffer references. Do not use after calling this. */ + destroy() { + this.rawBinaryData = null, this._int8View = null, this._uint8View = null, this._int16View = null, this.uint16View = null, this._int32View = null, this.uint32View = null, this.float32View = 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(e) { + switch (e) { + case "int8": + case "uint8": + return 1; + case "int16": + case "uint16": + return 2; + case "int32": + case "uint32": + case "float32": + return 4; + default: + throw new Error(`${e} isn't a valid view type`); + } + } +} +function Ar(i, e) { + const t = i.byteLength / 8 | 0, n = new Float64Array(i, 0, t); + new Float64Array(e, 0, t).set(n); + const r = i.byteLength - t * 8; + if (r > 0) { + const a = new Uint8Array(i, t * 8, r); + new Uint8Array(e, t * 8, r).set(a); + } +} +const Zh = { + normal: "normal-npm", + add: "add-npm", + screen: "screen-npm" +}; +var Kh = /* @__PURE__ */ ((i) => (i[i.DISABLED = 0] = "DISABLED", i[i.RENDERING_MASK_ADD = 1] = "RENDERING_MASK_ADD", i[i.MASK_ACTIVE = 2] = "MASK_ACTIVE", i[i.INVERSE_MASK_ACTIVE = 3] = "INVERSE_MASK_ACTIVE", i[i.RENDERING_MASK_REMOVE = 4] = "RENDERING_MASK_REMOVE", i[i.NONE = 5] = "NONE", i))(Kh || {}); +function kr(i, e) { + return e.alphaMode === "no-premultiply-alpha" && Zh[i] || i; +} +const Qh = [ + "precision mediump float;", + "void main(void){", + "float test = 0.1;", + "%forloop%", + "gl_FragColor = vec4(0.0);", + "}" +].join(` +`); +function Jh(i) { + let e = ""; + for (let t = 0; t < i; ++t) + t > 0 && (e += ` +else `), t < i - 1 && (e += `if(test == ${t}.0){}`); + return e; +} +function ec(i, e) { + if (i === 0) + throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`"); + const t = e.createShader(e.FRAGMENT_SHADER); + try { + for (; ; ) { + const n = Qh.replace(/%forloop%/gi, Jh(i)); + if (e.shaderSource(t, n), e.compileShader(t), !e.getShaderParameter(t, e.COMPILE_STATUS)) + i = i / 2 | 0; + else + break; + } + } finally { + e.deleteShader(t); + } + return i; +} +let Ft = null; +function tc() { + var e; + if (Ft) + return Ft; + const i = Eo(); + return Ft = i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS), Ft = ec( + Ft, + i + ), (e = i.getExtension("WEBGL_lose_context")) == null || e.loseContext(), Ft; +} +class nc { + constructor() { + this.ids = /* @__PURE__ */ Object.create(null), this.textures = [], this.count = 0; + } + /** Clear the textures and their locations. */ + clear() { + for (let e = 0; e < this.count; e++) { + const t = this.textures[e]; + this.textures[e] = null, this.ids[t.uid] = null; + } + this.count = 0; + } +} +class ic { + constructor() { + this.renderPipeId = "batch", this.action = "startBatch", this.start = 0, this.size = 0, this.textures = new nc(), this.blendMode = "normal", this.topology = "triangle-strip", this.canBundle = !0; + } + destroy() { + this.textures = null, this.gpuBindGroup = null, this.bindGroup = null, this.batcher = null; + } +} +const on = []; +let Jn = 0; +oi.register({ + clear: () => { + if (on.length > 0) + for (const i of on) + i && i.destroy(); + on.length = 0, Jn = 0; + } +}); +function Dr() { + return Jn > 0 ? on[--Jn] : new ic(); +} +function Sr(i) { + on[Jn++] = i; +} +let Yt = 0; +const jo = class Wo { + constructor(e) { + this.uid = re("batcher"), this.dirty = !0, this.batchIndex = 0, this.batches = [], this._elements = [], e = { ...Wo.defaultOptions, ...e }, e.maxTextures || (j("v8.8.0", "maxTextures is a required option for Batcher now, please pass it in the options"), e.maxTextures = tc()); + const { maxTextures: t, attributesInitialSize: n, indicesInitialSize: s } = e; + this.attributeBuffer = new Cr(n * 4), this.indexBuffer = new Uint16Array(s), this.maxTextures = t; + } + begin() { + this.elementSize = 0, this.elementStart = 0, this.indexSize = 0, this.attributeSize = 0; + for (let e = 0; e < this.batchIndex; e++) + Sr(this.batches[e]); + this.batchIndex = 0, this._batchIndexStart = 0, this._batchIndexSize = 0, this.dirty = !0; + } + add(e) { + this._elements[this.elementSize++] = e, e._indexStart = this.indexSize, e._attributeStart = this.attributeSize, e._batcher = this, this.indexSize += e.indexSize, this.attributeSize += e.attributeSize * this.vertexSize; + } + checkAndUpdateTexture(e, t) { + const n = e._batch.textures.ids[t._source.uid]; + return !n && n !== 0 ? !1 : (e._textureId = n, e.texture = t, !0); + } + updateElement(e) { + this.dirty = !0; + const t = this.attributeBuffer; + e.packAsQuad ? this.packQuadAttributes( + e, + t.float32View, + t.uint32View, + e._attributeStart, + e._textureId + ) : this.packAttributes( + e, + t.float32View, + t.uint32View, + e._attributeStart, + e._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(e) { + const t = this._elements; + if (!t[this.elementStart]) + return; + let n = Dr(), s = n.textures; + s.clear(); + const r = t[this.elementStart]; + let a = kr(r.blendMode, r.texture._source), o = r.topology; + this.attributeSize * 4 > this.attributeBuffer.size && this._resizeAttributeBuffer(this.attributeSize * 4), this.indexSize > this.indexBuffer.length && this._resizeIndexBuffer(this.indexSize); + const l = this.attributeBuffer.float32View, u = this.attributeBuffer.uint32View, h = this.indexBuffer; + let c = this._batchIndexSize, f = this._batchIndexStart, d = "startBatch"; + const p = this.maxTextures; + for (let b = this.elementStart; b < this.elementSize; ++b) { + const m = t[b]; + t[b] = null; + const g = m.texture._source, _ = kr(m.blendMode, g), y = a !== _ || o !== m.topology; + if (g._batchTick === Yt && !y) { + m._textureId = g._textureBindLocation, c += m.indexSize, m.packAsQuad ? (this.packQuadAttributes( + m, + l, + u, + m._attributeStart, + m._textureId + ), this.packQuadIndex( + h, + m._indexStart, + m._attributeStart / this.vertexSize + )) : (this.packAttributes( + m, + l, + u, + m._attributeStart, + m._textureId + ), this.packIndex( + m, + h, + m._indexStart, + m._attributeStart / this.vertexSize + )), m._batch = n; + continue; + } + g._batchTick = Yt, (s.count >= p || y) && (this._finishBatch( + n, + f, + c - f, + s, + a, + o, + e, + d + ), d = "renderBatch", f = c, a = _, o = m.topology, n = Dr(), s = n.textures, s.clear(), ++Yt), m._textureId = g._textureBindLocation = s.count, s.ids[g.uid] = s.count, s.textures[s.count++] = g, m._batch = n, c += m.indexSize, m.packAsQuad ? (this.packQuadAttributes( + m, + l, + u, + m._attributeStart, + m._textureId + ), this.packQuadIndex( + h, + m._indexStart, + m._attributeStart / this.vertexSize + )) : (this.packAttributes( + m, + l, + u, + m._attributeStart, + m._textureId + ), this.packIndex( + m, + h, + m._indexStart, + m._attributeStart / this.vertexSize + )); + } + s.count > 0 && (this._finishBatch( + n, + f, + c - f, + s, + a, + o, + e, + d + ), f = c, ++Yt), this.elementStart = this.elementSize, this._batchIndexStart = f, this._batchIndexSize = c; + } + _finishBatch(e, t, n, s, r, a, o, l) { + e.gpuBindGroup = null, e.bindGroup = null, e.action = l, e.batcher = this, e.textures = s, e.blendMode = r, e.topology = a, e.start = t, e.size = n, ++Yt, this.batches[this.batchIndex++] = e, o.add(e); + } + finish(e) { + this.break(e); + } + /** + * Resizes the attribute buffer to the given size (1 = 1 float32) + * @param size - the size in vertices to ensure (not bytes!) + */ + ensureAttributeBuffer(e) { + e * 4 <= this.attributeBuffer.size || this._resizeAttributeBuffer(e * 4); + } + /** + * Resizes the index buffer to the given size (1 = 1 float32) + * @param size - the size in vertices to ensure (not bytes!) + */ + ensureIndexBuffer(e) { + e <= this.indexBuffer.length || this._resizeIndexBuffer(e); + } + _resizeAttributeBuffer(e) { + const t = Math.max(e, this.attributeBuffer.size * 2), n = new Cr(t); + Ar(this.attributeBuffer.rawBinaryData, n.rawBinaryData), this.attributeBuffer = n; + } + _resizeIndexBuffer(e) { + const t = this.indexBuffer; + let n = Math.max(e, t.length * 1.5); + n += n % 2; + const s = n > 65535 ? new Uint32Array(n) : new Uint16Array(n); + if (s.BYTES_PER_ELEMENT !== t.BYTES_PER_ELEMENT) + for (let r = 0; r < t.length; r++) + s[r] = t[r]; + else + Ar(t.buffer, s.buffer); + this.indexBuffer = s; + } + packQuadIndex(e, t, n) { + e[t] = n + 0, e[t + 1] = n + 1, e[t + 2] = n + 2, e[t + 3] = n + 0, e[t + 4] = n + 2, e[t + 5] = n + 3; + } + packIndex(e, t, n, s) { + const r = e.indices, a = e.indexSize, o = e.indexOffset, l = e.attributeOffset; + for (let u = 0; u < a; u++) + t[n++] = s + r[u + o] - l; + } + destroy() { + if (this.batches !== null) { + for (let e = 0; e < this.batches.length; e++) + Sr(this.batches[e]); + this.batches = null; + for (let e = 0; e < this._elements.length; e++) + this._elements[e] && (this._elements[e]._batch = null); + this._elements = null, this.indexBuffer = null, this.attributeBuffer.destroy(), this.attributeBuffer = null; + } + } +}; +jo.defaultOptions = { + maxTextures: null, + attributesInitialSize: 4, + indicesInitialSize: 6 +}; +let sc = jo; +var ve = /* @__PURE__ */ ((i) => (i[i.MAP_READ = 1] = "MAP_READ", i[i.MAP_WRITE = 2] = "MAP_WRITE", i[i.COPY_SRC = 4] = "COPY_SRC", i[i.COPY_DST = 8] = "COPY_DST", i[i.INDEX = 16] = "INDEX", i[i.VERTEX = 32] = "VERTEX", i[i.UNIFORM = 64] = "UNIFORM", i[i.STORAGE = 128] = "STORAGE", i[i.INDIRECT = 256] = "INDIRECT", i[i.QUERY_RESOLVE = 512] = "QUERY_RESOLVE", i[i.STATIC = 1024] = "STATIC", i))(ve || {}); +class gn extends dt { + /** + * Creates a new Buffer with the given options + * @param options - the options for the buffer + */ + constructor(e) { + let { data: t, size: n } = e; + const { usage: s, label: r, shrinkToFit: a } = e; + super(), this.uid = re("buffer"), this._resourceType = "buffer", this._resourceId = re("resource"), this._touched = 0, this._updateID = 1, this._dataInt32 = null, this.shrinkToFit = !0, this.destroyed = !1, t instanceof Array && (t = new Float32Array(t)), this._data = t, n ?? (n = t == null ? void 0 : t.byteLength); + const o = !!t; + this.descriptor = { + size: n, + usage: s, + mappedAtCreation: o, + label: r + }, this.shrinkToFit = a ?? !0; + } + /** the data in the buffer */ + get data() { + return this._data; + } + set data(e) { + this.setDataWithSize(e, e.length, !0); + } + get dataInt32() { + return this._dataInt32 || (this._dataInt32 = new Int32Array(this.data.buffer)), this._dataInt32; + } + /** whether the buffer is static or not */ + get static() { + return !!(this.descriptor.usage & ve.STATIC); + } + set static(e) { + e ? this.descriptor.usage |= ve.STATIC : this.descriptor.usage &= ~ve.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(e, t, n) { + if (this._updateID++, this._updateSize = t * e.BYTES_PER_ELEMENT, this._data === e) { + n && this.emit("update", this); + return; + } + const s = this._data; + if (this._data = e, this._dataInt32 = null, !s || s.length !== e.length) { + !this.shrinkToFit && s && e.byteLength < s.byteLength ? n && this.emit("update", this) : (this.descriptor.size = e.byteLength, this._resourceId = re("resource"), this.emit("change", this)); + return; + } + n && 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(e) { + this._updateSize = e ?? this._updateSize, this._updateID++, this.emit("update", this); + } + /** Destroys the buffer */ + destroy() { + this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this._data = null, this.descriptor = null, this.removeAllListeners(); + } +} +function Zo(i, e) { + if (!(i instanceof gn)) { + let t = e ? ve.INDEX : ve.VERTEX; + i instanceof Array && (e ? (i = new Uint32Array(i), t = ve.INDEX | ve.COPY_DST) : (i = new Float32Array(i), t = ve.VERTEX | ve.COPY_DST)), i = new gn({ + data: i, + label: e ? "index-mesh-buffer" : "vertex-mesh-buffer", + usage: t + }); + } + return i; +} +function rc(i, e, t) { + const n = i.getAttribute(e); + if (!n) + return t.minX = 0, t.minY = 0, t.maxX = 0, t.maxY = 0, t; + const s = n.buffer.data; + let r = 1 / 0, a = 1 / 0, o = -1 / 0, l = -1 / 0; + const u = s.BYTES_PER_ELEMENT, h = (n.offset || 0) / u, c = (n.stride || 2 * 4) / u; + for (let f = h; f < s.length; f += c) { + const d = s[f], p = s[f + 1]; + d > o && (o = d), p > l && (l = p), d < r && (r = d), p < a && (a = p); + } + return t.minX = r, t.minY = a, t.maxX = o, t.maxY = l, t; +} +function ac(i) { + return (i instanceof gn || Array.isArray(i) || i.BYTES_PER_ELEMENT) && (i = { + buffer: i + }), i.buffer = Zo(i.buffer, !1), i; +} +class oc extends dt { + /** + * Create a new instance of a geometry + * @param options - The options for the geometry. + */ + constructor(e = {}) { + super(), this.uid = re("geometry"), this._layoutKey = 0, this.instanceCount = 1, this._bounds = new Je(), this._boundsDirty = !0; + const { attributes: t, indexBuffer: n, topology: s } = e; + if (this.buffers = [], this.attributes = {}, t) + for (const r in t) + this.addAttribute(r, t[r]); + this.instanceCount = e.instanceCount ?? 1, n && this.addIndex(n), this.topology = s || "triangle-list"; + } + onBufferUpdate() { + this._boundsDirty = !0, this.emit("update", this); + } + /** + * Returns the requested attribute. + * @param id - The name of the attribute required + * @returns - The attribute requested. + */ + getAttribute(e) { + return this.attributes[e]; + } + /** + * 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(e) { + return this.getAttribute(e).buffer; + } + /** + * Used to figure out how many vertices there are in this geometry + * @returns the number of vertices in the geometry + */ + getSize() { + for (const e in this.attributes) { + const t = this.attributes[e]; + return t.buffer.data.length / (t.stride / 4 || t.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(e, t) { + const n = ac(t); + this.buffers.indexOf(n.buffer) === -1 && (this.buffers.push(n.buffer), n.buffer.on("update", this.onBufferUpdate, this), n.buffer.on("change", this.onBufferUpdate, this)), this.attributes[e] = n; + } + /** + * 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(e) { + this.indexBuffer = Zo(e, !0), this.buffers.push(this.indexBuffer); + } + /** Returns the bounds of the geometry. */ + get bounds() { + return this._boundsDirty ? (this._boundsDirty = !1, rc(this, "aPosition", this._bounds)) : this._bounds; + } + /** + * destroys the geometry. + * @param destroyBuffers - destroy the buffers associated with this geometry + */ + destroy(e = !1) { + this.emit("destroy", this), this.removeAllListeners(), e && this.buffers.forEach((t) => t.destroy()), this.attributes = null, this.buffers = null, this.indexBuffer = null, this._bounds = null; + } +} +const lc = new Float32Array(1), uc = new Uint32Array(1); +class hc extends oc { + constructor() { + const t = new gn({ + data: lc, + label: "attribute-batch-buffer", + usage: ve.VERTEX | ve.COPY_DST, + shrinkToFit: !1 + }), n = new gn({ + data: uc, + label: "index-batch-buffer", + usage: ve.INDEX | ve.COPY_DST, + // | BufferUsage.STATIC, + shrinkToFit: !1 + }), s = 6 * 4; + super({ + attributes: { + aPosition: { + buffer: t, + format: "float32x2", + stride: s, + offset: 0 + }, + aUV: { + buffer: t, + format: "float32x2", + stride: s, + offset: 2 * 4 + }, + aColor: { + buffer: t, + format: "unorm8x4", + stride: s, + offset: 4 * 4 + }, + aTextureIdAndRound: { + buffer: t, + format: "uint16x2", + stride: s, + offset: 5 * 4 + } + }, + indexBuffer: n + }); + } +} +function Er(i, e, t) { + if (i) + for (const n in i) { + const s = n.toLocaleLowerCase(), r = e[s]; + if (r) { + let a = i[n]; + n === "header" && (a = a.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "")), t && r.push(`//----${t}----//`), r.push(a); + } else + Fe(`${n} placement hook does not exist in shader`); + } +} +const cc = /\{\{(.*?)\}\}/g; +function Fr(i) { + var n; + const e = {}; + return (((n = i.match(cc)) == null ? void 0 : n.map((s) => s.replace(/[{()}]/g, ""))) ?? []).forEach((s) => { + e[s] = []; + }), e; +} +function $r(i, e) { + let t; + const n = /@in\s+([^;]+);/g; + for (; (t = n.exec(i)) !== null; ) + e.push(t[1]); +} +function Tr(i, e, t = !1) { + const n = []; + $r(e, n), i.forEach((o) => { + o.header && $r(o.header, n); + }); + const s = n; + t && s.sort(); + const r = s.map((o, l) => ` @location(${l}) ${o},`).join(` +`); + let a = e.replace(/@in\s+[^;]+;\s*/g, ""); + return a = a.replace("{{in}}", ` +${r} +`), a; +} +function Mr(i, e) { + let t; + const n = /@out\s+([^;]+);/g; + for (; (t = n.exec(i)) !== null; ) + e.push(t[1]); +} +function dc(i) { + const t = /\b(\w+)\s*:/g.exec(i); + return t ? t[1] : ""; +} +function fc(i) { + const e = /@.*?\s+/g; + return i.replace(e, ""); +} +function _c(i, e) { + const t = []; + Mr(e, t), i.forEach((l) => { + l.header && Mr(l.header, t); + }); + let n = 0; + const s = t.sort().map((l) => l.indexOf("builtin") > -1 ? l : `@location(${n++}) ${l}`).join(`, +`), r = t.sort().map((l) => ` var ${fc(l)};`).join(` +`), a = `return VSOutput( + ${t.sort().map((l) => ` ${dc(l)}`).join(`, +`)});`; + let o = e.replace(/@out\s+[^;]+;\s*/g, ""); + return o = o.replace("{{struct}}", ` +${s} +`), o = o.replace("{{start}}", ` +${r} +`), o = o.replace("{{return}}", ` +${a} +`), o; +} +function Pr(i, e) { + let t = i; + for (const n in e) { + const s = e[n]; + s.join(` +`).length ? t = t.replace(`{{${n}}}`, `//-----${n} START-----// +${s.join(` +`)} +//----${n} FINISH----//`) : t = t.replace(`{{${n}}}`, ""); + } + return t; +} +const _t = /* @__PURE__ */ Object.create(null), Si = /* @__PURE__ */ new Map(); +let pc = 0; +function mc({ + template: i, + bits: e +}) { + const t = Ko(i, e); + if (_t[t]) + return _t[t]; + const { vertex: n, fragment: s } = yc(i, e); + return _t[t] = Qo(n, s, e), _t[t]; +} +function gc({ + template: i, + bits: e +}) { + const t = Ko(i, e); + return _t[t] || (_t[t] = Qo(i.vertex, i.fragment, e)), _t[t]; +} +function yc(i, e) { + const t = e.map((a) => a.vertex).filter((a) => !!a), n = e.map((a) => a.fragment).filter((a) => !!a); + let s = Tr(t, i.vertex, !0); + s = _c(t, s); + const r = Tr(n, i.fragment, !0); + return { + vertex: s, + fragment: r + }; +} +function Ko(i, e) { + return e.map((t) => (Si.has(t) || Si.set(t, pc++), Si.get(t))).sort((t, n) => t - n).join("-") + i.vertex + i.fragment; +} +function Qo(i, e, t) { + const n = Fr(i), s = Fr(e); + return t.forEach((r) => { + Er(r.vertex, n, r.name), Er(r.fragment, s, r.name); + }), { + vertex: Pr(i, n), + fragment: Pr(e, s) + }; +} +const bc = ( + /* wgsl */ + ` + @in aPosition: vec2; + @in aUV: vec2; + + @out @builtin(position) vPosition: vec4; + @out vUV : vec2; + @out vColor : vec4; + + {{header}} + + struct VSOutput { + {{struct}} + }; + + @vertex + fn main( {{in}} ) -> VSOutput { + + var worldTransformMatrix = globalUniforms.uWorldTransformMatrix; + var modelMatrix = mat3x3( + 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(1., 1., 1., 1.); + + {{main}} + + vUV = uv; + + var modelViewProjectionMatrix = globalUniforms.uProjectionMatrix * worldTransformMatrix * modelMatrix; + + vPosition = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0); + + vColor *= globalUniforms.uWorldColorAlpha; + + {{end}} + + {{return}} + }; +` +), xc = ( + /* wgsl */ + ` + @in vUV : vec2; + @in vColor : vec4; + + {{header}} + + @fragment + fn main( + {{in}} + ) -> @location(0) vec4 { + + {{start}} + + var outColor:vec4; + + {{main}} + + var finalColor:vec4 = outColor * vColor; + + {{end}} + + return finalColor; + }; +` +), vc = ( + /* 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}} + } +` +), wc = ( + /* glsl */ + ` + + in vec4 vColor; + in vec2 vUV; + + out vec4 finalColor; + + {{header}} + + void main(void) { + + {{start}} + + vec4 outColor; + + {{main}} + + finalColor = outColor * vColor; + + {{end}} + } +` +), Cc = { + name: "global-uniforms-bit", + vertex: { + header: ( + /* wgsl */ + ` + struct GlobalUniforms { + uProjectionMatrix:mat3x3, + uWorldTransformMatrix:mat3x3, + uWorldColorAlpha: vec4, + uResolution: vec2, + } + + @group(0) @binding(0) var globalUniforms : GlobalUniforms; + ` + ) + } +}, Ac = { + name: "global-uniforms-bit", + vertex: { + header: ( + /* glsl */ + ` + uniform mat3 uProjectionMatrix; + uniform mat3 uWorldTransformMatrix; + uniform vec4 uWorldColorAlpha; + uniform vec2 uResolution; + ` + ) + } +}; +function kc({ bits: i, name: e }) { + const t = mc({ + template: { + fragment: xc, + vertex: bc + }, + bits: [ + Cc, + ...i + ] + }); + return ui.from({ + name: e, + vertex: { + source: t.vertex, + entryPoint: "main" + }, + fragment: { + source: t.fragment, + entryPoint: "main" + } + }); +} +function Dc({ bits: i, name: e }) { + return new $o({ + name: e, + ...gc({ + template: { + vertex: vc, + fragment: wc + }, + bits: [ + Ac, + ...i + ] + }) + }); +} +const Sc = { + name: "color-bit", + vertex: { + header: ( + /* wgsl */ + ` + @in aColor: vec4; + ` + ), + main: ( + /* wgsl */ + ` + vColor *= vec4(aColor.rgb * aColor.a, aColor.a); + ` + ) + } +}, Ec = { + name: "color-bit", + vertex: { + header: ( + /* glsl */ + ` + in vec4 aColor; + ` + ), + main: ( + /* glsl */ + ` + vColor *= vec4(aColor.rgb * aColor.a, aColor.a); + ` + ) + } +}, Ei = {}; +function Fc(i) { + const e = []; + if (i === 1) + e.push("@group(1) @binding(0) var textureSource1: texture_2d;"), e.push("@group(1) @binding(1) var textureSampler1: sampler;"); + else { + let t = 0; + for (let n = 0; n < i; n++) + e.push(`@group(1) @binding(${t++}) var textureSource${n + 1}: texture_2d;`), e.push(`@group(1) @binding(${t++}) var textureSampler${n + 1}: sampler;`); + } + return e.join(` +`); +} +function $c(i) { + const e = []; + if (i === 1) + e.push("outColor = textureSampleGrad(textureSource1, textureSampler1, vUV, uvDx, uvDy);"); + else { + e.push("switch vTextureId {"); + for (let t = 0; t < i; t++) + t === i - 1 ? e.push(" default:{") : e.push(` case ${t}:{`), e.push(` outColor = textureSampleGrad(textureSource${t + 1}, textureSampler${t + 1}, vUV, uvDx, uvDy);`), e.push(" break;}"); + e.push("}"); + } + return e.join(` +`); +} +function Tc(i) { + return Ei[i] || (Ei[i] = { + name: "texture-batch-bit", + vertex: { + header: ` + @in aTextureIdAndRound: vec2; + @out @interpolate(flat) vTextureId : u32; + `, + main: ` + vTextureId = aTextureIdAndRound.y; + `, + end: ` + if(aTextureIdAndRound.x == 1) + { + vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw); + } + ` + }, + fragment: { + header: ` + @in @interpolate(flat) vTextureId: u32; + + ${Fc(i)} + `, + main: ` + var uvDx = dpdx(vUV); + var uvDy = dpdy(vUV); + + ${$c(i)} + ` + } + }), Ei[i]; +} +const Fi = {}; +function Mc(i) { + const e = []; + for (let t = 0; t < i; t++) + t > 0 && e.push("else"), t < i - 1 && e.push(`if(vTextureId < ${t}.5)`), e.push("{"), e.push(` outColor = texture(uTextures[${t}], vUV);`), e.push("}"); + return e.join(` +`); +} +function Pc(i) { + return Fi[i] || (Fi[i] = { + 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[${i}]; + + `, + main: ` + + ${Mc(i)} + ` + } + }), Fi[i]; +} +const Ic = { + name: "round-pixels-bit", + vertex: { + header: ( + /* wgsl */ + ` + fn roundPixels(position: vec2, targetSize: vec2) -> vec2 + { + return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0; + } + ` + ) + } +}, Rc = { + 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; + } + ` + ) + } +}, Ir = {}; +function Bc(i) { + let e = Ir[i]; + if (e) + return e; + const t = new Int32Array(i); + for (let n = 0; n < i; n++) + t[n] = n; + return e = Ir[i] = new Io({ + uTextures: { value: t, type: "i32", size: i } + }, { isStatic: !0 }), e; +} +class Lc extends ks { + constructor(e) { + const t = Dc({ + name: "batch", + bits: [ + Ec, + Pc(e), + Rc + ] + }), n = kc({ + name: "batch", + bits: [ + Sc, + Tc(e), + Ic + ] + }); + super({ + glProgram: t, + gpuProgram: n, + resources: { + batchSamplers: Bc(e) + } + }); + } +} +let $i = null; +const Jo = class el extends sc { + constructor(e) { + super(e), this.geometry = new hc(), this.name = el.extension.name, this.vertexSize = 6, $i ?? ($i = new Lc(e.maxTextures)), this.shader = $i; + } + /** + * 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(e, t, n, s, r) { + const a = r << 16 | e.roundPixels & 65535, o = e.transform, l = o.a, u = o.b, h = o.c, c = o.d, f = o.tx, d = o.ty, { positions: p, uvs: b } = e, m = e.color, x = e.attributeOffset, g = x + e.attributeSize; + for (let _ = x; _ < g; _++) { + const y = _ * 2, C = p[y], v = p[y + 1]; + t[s++] = l * C + h * v + f, t[s++] = c * v + u * C + d, t[s++] = b[y], t[s++] = b[y + 1], n[s++] = m, n[s++] = a; + } + } + /** + * 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(e, t, n, s, r) { + const a = e.texture, o = e.transform, l = o.a, u = o.b, h = o.c, c = o.d, f = o.tx, d = o.ty, p = e.bounds, b = p.maxX, m = p.minX, x = p.maxY, g = p.minY, _ = a.uvs, y = e.color, C = r << 16 | e.roundPixels & 65535; + t[s + 0] = l * m + h * g + f, t[s + 1] = c * g + u * m + d, t[s + 2] = _.x0, t[s + 3] = _.y0, n[s + 4] = y, n[s + 5] = C, t[s + 6] = l * b + h * g + f, t[s + 7] = c * g + u * b + d, t[s + 8] = _.x1, t[s + 9] = _.y1, n[s + 10] = y, n[s + 11] = C, t[s + 12] = l * b + h * x + f, t[s + 13] = c * x + u * b + d, t[s + 14] = _.x2, t[s + 15] = _.y2, n[s + 16] = y, n[s + 17] = C, t[s + 18] = l * m + h * x + f, t[s + 19] = c * x + u * m + d, t[s + 20] = _.x3, t[s + 21] = _.y3, n[s + 22] = y, n[s + 23] = C; + } +}; +Jo.extension = { + type: [ + X.Batcher + ], + name: "default" +}; +let Nc = Jo; +function Oc(i, e, t, n, s, r, a, o = null) { + let l = 0; + t *= e, s *= r; + const u = o.a, h = o.b, c = o.c, f = o.d, d = o.tx, p = o.ty; + for (; l < a; ) { + const b = i[t], m = i[t + 1]; + n[s] = u * b + c * m + d, n[s + 1] = h * b + f * m + p, s += r, t += e, l++; + } +} +function Gc(i, e, t, n) { + let s = 0; + for (e *= t; s < n; ) + i[e] = 0, i[e + 1] = 0, e += t, s++; +} +function tl(i, e, t, n, s) { + const r = e.a, a = e.b, o = e.c, l = e.d, u = e.tx, h = e.ty; + t || (t = 0), n || (n = 2), s || (s = i.length / n - t); + let c = t * n; + for (let f = 0; f < s; f++) { + const d = i[c], p = i[c + 1]; + i[c] = r * d + o * p + u, i[c + 1] = a * d + l * p + h, c += n; + } +} +const zc = new q(); +class nl { + constructor() { + this.packAsQuad = !1, this.batcherName = "default", this.topology = "triangle-list", this.applyTransform = !0, 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() { + return this.renderable && this.applyTransform ? this.renderable.groupBlendMode : "normal"; + } + get color() { + const e = this.baseColor, t = e >> 16 | e & 65280 | (e & 255) << 16, n = this.renderable; + return n ? ro(t, n.groupColor) + (this.alpha * n.groupAlpha * 255 << 24) : t + (this.alpha * 255 << 24); + } + get transform() { + var e; + return ((e = this.renderable) == null ? void 0 : e.groupTransform) || zc; + } + copyTo(e) { + e.indexOffset = this.indexOffset, e.indexSize = this.indexSize, e.attributeOffset = this.attributeOffset, e.attributeSize = this.attributeSize, e.baseColor = this.baseColor, e.alpha = this.alpha, e.texture = this.texture, e.geometryData = this.geometryData, e.topology = this.topology; + } + reset() { + this.applyTransform = !0, this.renderable = null, this.topology = "triangle-list"; + } + destroy() { + this.renderable = null, this.texture = null, this.geometryData = null, this._batcher = null, this._batch = null; + } +} +const yn = { + extension: { + type: X.ShapeBuilder, + name: "circle" + }, + build(i, e) { + let t, n, s, r, a, o; + if (i.type === "circle") { + const y = i; + if (a = o = y.radius, a <= 0) + return !1; + t = y.x, n = y.y, s = r = 0; + } else if (i.type === "ellipse") { + const y = i; + if (a = y.halfWidth, o = y.halfHeight, a <= 0 || o <= 0) + return !1; + t = y.x, n = y.y, s = r = 0; + } else { + const y = i, C = y.width / 2, v = y.height / 2; + t = y.x + C, n = y.y + v, a = o = Math.max(0, Math.min(y.radius, Math.min(C, v))), s = C - a, r = v - o; + } + if (s < 0 || r < 0) + return !1; + const l = Math.ceil(2.3 * Math.sqrt(a + o)), u = l * 8 + (s ? 4 : 0) + (r ? 4 : 0); + if (u === 0) + return !1; + if (l === 0) + return e[0] = e[6] = t + s, e[1] = e[3] = n + r, e[2] = e[4] = t - s, e[5] = e[7] = n - r, !0; + let h = 0, c = l * 4 + (s ? 2 : 0) + 2, f = c, d = u, p = s + a, b = r, m = t + p, x = t - p, g = n + b; + if (e[h++] = m, e[h++] = g, e[--c] = g, e[--c] = x, r) { + const y = n - b; + e[f++] = x, e[f++] = y, e[--d] = y, e[--d] = m; + } + for (let y = 1; y < l; y++) { + const C = Math.PI / 2 * (y / l), v = s + Math.cos(C) * a, w = r + Math.sin(C) * o, $ = t + v, D = t - v, k = n + w, F = n - w; + e[h++] = $, e[h++] = k, e[--c] = k, e[--c] = D, e[f++] = D, e[f++] = F, e[--d] = F, e[--d] = $; + } + p = s, b = r + o, m = t + p, x = t - p, g = n + b; + const _ = n - b; + return e[h++] = m, e[h++] = g, e[--d] = _, e[--d] = m, s && (e[h++] = x, e[h++] = g, e[--d] = _, e[--d] = x), !0; + }, + triangulate(i, e, t, n, s, r) { + if (i.length === 0) + return; + let a = 0, o = 0; + for (let h = 0; h < i.length; h += 2) + a += i[h], o += i[h + 1]; + a /= i.length / 2, o /= i.length / 2; + let l = n; + e[l * t] = a, e[l * t + 1] = o; + const u = l++; + for (let h = 0; h < i.length; h += 2) + e[l * t] = i[h], e[l * t + 1] = i[h + 1], h > 0 && (s[r++] = l, s[r++] = u, s[r++] = l - 1), l++; + s[r++] = u + 1, s[r++] = u, s[r++] = l - 1; + } +}, qc = { ...yn, extension: { ...yn.extension, name: "ellipse" } }, Uc = { ...yn, extension: { ...yn.extension, name: "roundedRectangle" } }, il = 1e-4, Rr = 1e-4; +function Hc(i) { + const e = i.length; + if (e < 6) + return 1; + let t = 0; + for (let n = 0, s = i[e - 2], r = i[e - 1]; n < e; n += 2) { + const a = i[n], o = i[n + 1]; + t += (a - s) * (o + r), s = a, r = o; + } + return t < 0 ? -1 : 1; +} +function Br(i, e, t, n, s, r, a, o) { + const l = i - t * s, u = e - n * s, h = i + t * r, c = e + n * r; + let f, d; + a ? (f = n, d = -t) : (f = -n, d = t); + const p = l + f, b = u + d, m = h + f, x = c + d; + return o.push(p, b), o.push(m, x), 2; +} +function yt(i, e, t, n, s, r, a, o) { + const l = t - i, u = n - e; + let h = Math.atan2(l, u), c = Math.atan2(s - i, r - e); + o && h < c ? h += Math.PI * 2 : !o && h > c && (c += Math.PI * 2); + let f = h; + const d = c - h, p = Math.abs(d), b = Math.sqrt(l * l + u * u), m = (15 * p * Math.sqrt(b) / Math.PI >> 0) + 1, x = d / m; + if (f += x, o) { + a.push(i, e), a.push(t, n); + for (let g = 1, _ = f; g < m; g++, _ += x) + a.push(i, e), a.push( + i + Math.sin(_) * b, + e + Math.cos(_) * b + ); + a.push(i, e), a.push(s, r); + } else { + a.push(t, n), a.push(i, e); + for (let g = 1, _ = f; g < m; g++, _ += x) + a.push( + i + Math.sin(_) * b, + e + Math.cos(_) * b + ), a.push(i, e); + a.push(s, r), a.push(i, e); + } + return m * 2; +} +function Vc(i, e, t, n, s, r) { + const a = il; + if (i.length === 0) + return; + const o = e; + let l = o.alignment; + if (e.alignment !== 0.5) { + let T = Hc(i); + l = (l - 0.5) * T + 0.5; + } + const u = new ge(i[0], i[1]), h = new ge(i[i.length - 2], i[i.length - 1]), c = n, f = Math.abs(u.x - h.x) < a && Math.abs(u.y - h.y) < a; + if (c) { + i = i.slice(), f && (i.pop(), i.pop(), h.set(i[i.length - 2], i[i.length - 1])); + const T = (u.x + h.x) * 0.5, O = (h.y + u.y) * 0.5; + i.unshift(T, O), i.push(T, O); + } + const d = s, p = i.length / 2; + let b = i.length; + const m = d.length / 2, x = o.width / 2, g = x * x, _ = o.miterLimit * o.miterLimit; + let y = i[0], C = i[1], v = i[2], w = i[3], $ = 0, D = 0, k = -(C - w), F = y - v, I = 0, z = 0, G = Math.sqrt(k * k + F * F); + k /= G, F /= G, k *= x, F *= x; + const de = l, A = (1 - de) * 2, E = de * 2; + c || (o.cap === "round" ? b += yt( + y - k * (A - E) * 0.5, + C - F * (A - E) * 0.5, + y - k * A, + C - F * A, + y + k * E, + C + F * E, + d, + !0 + ) + 2 : o.cap === "square" && (b += Br(y, C, k, F, A, E, !0, d))), d.push( + y - k * A, + C - F * A + ), d.push( + y + k * E, + C + F * E + ); + for (let T = 1; T < p - 1; ++T) { + y = i[(T - 1) * 2], C = i[(T - 1) * 2 + 1], v = i[T * 2], w = i[T * 2 + 1], $ = i[(T + 1) * 2], D = i[(T + 1) * 2 + 1], k = -(C - w), F = y - v, G = Math.sqrt(k * k + F * F), k /= G, F /= G, k *= x, F *= x, I = -(w - D), z = v - $, G = Math.sqrt(I * I + z * z), I /= G, z /= G, I *= x, z *= x; + const O = v - y, S = C - w, R = v - $, U = D - w, N = O * R + S * U, Q = S * R - U * O, V = Q < 0; + if (Math.abs(Q) < 1e-3 * Math.abs(N)) { + d.push( + v - k * A, + w - F * A + ), d.push( + v + k * E, + w + F * E + ), N >= 0 && (o.join === "round" ? b += yt( + v, + w, + v - k * A, + w - F * A, + v - I * A, + w - z * A, + d, + !1 + ) + 4 : b += 2, d.push( + v - I * E, + w - z * E + ), d.push( + v + I * A, + w + z * A + )); + continue; + } + const oe = (-k + y) * (-F + w) - (-k + v) * (-F + C), M = (-I + $) * (-z + w) - (-I + v) * (-z + D), Te = (O * M - R * oe) / Q, Me = (U * oe - S * M) / Q, tt = (Te - v) * (Te - v) + (Me - w) * (Me - w), Ye = v + (Te - v) * A, Ae = w + (Me - w) * A, fe = v - (Te - v) * E, Pe = w - (Me - w) * E, gt = Math.min(O * O + S * S, R * R + U * U), Ie = V ? A : E, zt = gt + Ie * Ie * g; + tt <= zt ? o.join === "bevel" || tt / g > _ ? (V ? (d.push(Ye, Ae), d.push(v + k * E, w + F * E), d.push(Ye, Ae), d.push(v + I * E, w + z * E)) : (d.push(v - k * A, w - F * A), d.push(fe, Pe), d.push(v - I * A, w - z * A), d.push(fe, Pe)), b += 2) : o.join === "round" ? V ? (d.push(Ye, Ae), d.push(v + k * E, w + F * E), b += yt( + v, + w, + v + k * E, + w + F * E, + v + I * E, + w + z * E, + d, + !0 + ) + 4, d.push(Ye, Ae), d.push(v + I * E, w + z * E)) : (d.push(v - k * A, w - F * A), d.push(fe, Pe), b += yt( + v, + w, + v - k * A, + w - F * A, + v - I * A, + w - z * A, + d, + !1 + ) + 4, d.push(v - I * A, w - z * A), d.push(fe, Pe)) : (d.push(Ye, Ae), d.push(fe, Pe)) : (d.push(v - k * A, w - F * A), d.push(v + k * E, w + F * E), o.join === "round" ? V ? b += yt( + v, + w, + v + k * E, + w + F * E, + v + I * E, + w + z * E, + d, + !0 + ) + 2 : b += yt( + v, + w, + v - k * A, + w - F * A, + v - I * A, + w - z * A, + d, + !1 + ) + 2 : o.join === "miter" && tt / g <= _ && (V ? (d.push(fe, Pe), d.push(fe, Pe)) : (d.push(Ye, Ae), d.push(Ye, Ae)), b += 2), d.push(v - I * A, w - z * A), d.push(v + I * E, w + z * E), b += 2); + } + y = i[(p - 2) * 2], C = i[(p - 2) * 2 + 1], v = i[(p - 1) * 2], w = i[(p - 1) * 2 + 1], k = -(C - w), F = y - v, G = Math.sqrt(k * k + F * F), k /= G, F /= G, k *= x, F *= x, d.push(v - k * A, w - F * A), d.push(v + k * E, w + F * E), c || (o.cap === "round" ? b += yt( + v - k * (A - E) * 0.5, + w - F * (A - E) * 0.5, + v - k * A, + w - F * A, + v + k * E, + w + F * E, + d, + !1 + ) + 2 : o.cap === "square" && (b += Br(v, w, k, F, A, E, !1, d))); + const B = Rr * Rr; + for (let T = m; T < b + m - 2; ++T) + y = d[T * 2], C = d[T * 2 + 1], v = d[(T + 1) * 2], w = d[(T + 1) * 2 + 1], $ = d[(T + 2) * 2], D = d[(T + 2) * 2 + 1], !(Math.abs(y * (w - D) + v * (D - C) + $ * (C - w)) < B) && r.push(T, T + 1, T + 2); +} +function Yc(i, e, t, n) { + const s = il; + if (i.length === 0) + return; + const r = i[0], a = i[1], o = i[i.length - 2], l = i[i.length - 1], u = e || Math.abs(r - o) < s && Math.abs(a - l) < s, h = t, c = i.length / 2, f = h.length / 2; + for (let d = 0; d < c; d++) + h.push(i[d * 2]), h.push(i[d * 2 + 1]); + for (let d = 0; d < c - 1; d++) + n.push(f + d, f + d + 1); + u && n.push(f + c - 1, f); +} +function sl(i, e, t, n, s, r, a) { + const o = Fh(i, e, 2); + if (!o) + return; + for (let u = 0; u < o.length; u += 3) + r[a++] = o[u] + s, r[a++] = o[u + 1] + s, r[a++] = o[u + 2] + s; + let l = s * n; + for (let u = 0; u < i.length; u += 2) + t[l] = i[u], t[l + 1] = i[u + 1], l += n; +} +const Xc = [], jc = { + extension: { + type: X.ShapeBuilder, + name: "polygon" + }, + build(i, e) { + for (let t = 0; t < i.points.length; t++) + e[t] = i.points[t]; + return !0; + }, + triangulate(i, e, t, n, s, r) { + sl(i, Xc, e, t, n, s, r); + } +}, Wc = { + extension: { + type: X.ShapeBuilder, + name: "rectangle" + }, + build(i, e) { + const t = i, n = t.x, s = t.y, r = t.width, a = t.height; + return r > 0 && a > 0 ? (e[0] = n, e[1] = s, e[2] = n + r, e[3] = s, e[4] = n + r, e[5] = s + a, e[6] = n, e[7] = s + a, !0) : !1; + }, + triangulate(i, e, t, n, s, r) { + let a = 0; + n *= t, e[n + a] = i[0], e[n + a + 1] = i[1], a += t, e[n + a] = i[2], e[n + a + 1] = i[3], a += t, e[n + a] = i[6], e[n + a + 1] = i[7], a += t, e[n + a] = i[4], e[n + a + 1] = i[5], a += t; + const o = n / t; + s[r++] = o, s[r++] = o + 1, s[r++] = o + 2, s[r++] = o + 1, s[r++] = o + 3, s[r++] = o + 2; + } +}, Zc = { + extension: { + type: X.ShapeBuilder, + name: "triangle" + }, + build(i, e) { + return e[0] = i.x, e[1] = i.y, e[2] = i.x2, e[3] = i.y2, e[4] = i.x3, e[5] = i.y3, !0; + }, + triangulate(i, e, t, n, s, r) { + let a = 0; + n *= t, e[n + a] = i[0], e[n + a + 1] = i[1], a += t, e[n + a] = i[2], e[n + a + 1] = i[3], a += t, e[n + a] = i[4], e[n + a + 1] = i[5]; + const o = n / t; + s[r++] = o, s[r++] = o + 1, s[r++] = o + 2; + } +}, Kc = new q(), Qc = new ce(); +function Jc(i, e, t, n) { + const s = e.matrix ? i.copyFrom(e.matrix).invert() : i.identity(); + if (e.textureSpace === "local") { + const a = t.getBounds(Qc); + e.width && a.pad(e.width); + const { x: o, y: l } = a, u = 1 / a.width, h = 1 / a.height, c = -o * u, f = -l * h, d = s.a, p = s.b, b = s.c, m = s.d; + s.a *= u, s.b *= u, s.c *= h, s.d *= h, s.tx = c * d + f * b + s.tx, s.ty = c * p + f * m + s.ty; + } else + s.translate(e.texture.frame.x, e.texture.frame.y), s.scale(1 / e.texture.source.width, 1 / e.texture.source.height); + const r = e.texture.source.style; + return !(e.fill instanceof xn) && r.addressMode === "clamp-to-edge" && (r.addressMode = "repeat", r.update()), n && s.append(Kc.copyFrom(n).invert()), s; +} +const hi = {}; +Ve.handleByMap(X.ShapeBuilder, hi); +Ve.add(Wc, jc, Zc, yn, qc, Uc); +const ed = new ce(), td = new q(); +function nd(i, e) { + const { geometryData: t, batches: n } = e; + n.length = 0, t.indices.length = 0, t.vertices.length = 0, t.uvs.length = 0; + for (let s = 0; s < i.instructions.length; s++) { + const r = i.instructions[s]; + if (r.action === "texture") + id(r.data, n, t); + else if (r.action === "fill" || r.action === "stroke") { + const a = r.action === "stroke", o = r.data.path.shapePath, l = r.data.style, u = r.data.hole; + a && u && Lr(u.shapePath, l, !0, n, t), u && (o.shapePrimitives[o.shapePrimitives.length - 1].holes = u.shapePath.shapePrimitives), Lr(o, l, a, n, t); + } + } +} +function id(i, e, t) { + const n = [], s = hi.rectangle, r = ed; + r.x = i.dx, r.y = i.dy, r.width = i.dw, r.height = i.dh; + const a = i.transform; + if (!s.build(r, n)) + return; + const { vertices: o, uvs: l, indices: u } = t, h = u.length, c = o.length / 2; + a && tl(n, a), s.triangulate(n, o, 2, c, u, h); + const f = i.image, d = f.uvs; + l.push( + d.x0, + d.y0, + d.x1, + d.y1, + d.x3, + d.y3, + d.x2, + d.y2 + ); + const p = Ue.get(nl); + p.indexOffset = h, p.indexSize = u.length - h, p.attributeOffset = c, p.attributeSize = o.length / 2 - c, p.baseColor = i.style, p.alpha = i.alpha, p.texture = f, p.geometryData = t, e.push(p); +} +function Lr(i, e, t, n, s) { + const { vertices: r, uvs: a, indices: o } = s; + i.shapePrimitives.forEach(({ shape: l, transform: u, holes: h }) => { + const c = [], f = hi[l.type]; + if (!f.build(l, c)) + return; + const d = o.length, p = r.length / 2; + let b = "triangle-list"; + if (u && tl(c, u), t) { + const _ = l.closePath ?? !0, y = e; + y.pixelLine ? (Yc(c, _, r, o), b = "line-list") : Vc(c, y, !1, _, r, o); + } else if (h) { + const _ = [], y = c.slice(); + sd(h).forEach((v) => { + _.push(y.length / 2), y.push(...v); + }), sl(y, _, r, 2, p, o, d); + } else + f.triangulate(c, r, 2, p, o, d); + const m = a.length / 2, x = e.texture; + if (x !== W.WHITE) { + const _ = Jc(td, e, l, u); + Oc(r, 2, p, a, m, 2, r.length / 2 - p, _); + } else + Gc(a, m, 2, r.length / 2 - p); + const g = Ue.get(nl); + g.indexOffset = d, g.indexSize = o.length - d, g.attributeOffset = p, g.attributeSize = r.length / 2 - p, g.baseColor = e.color, g.alpha = e.alpha, g.texture = x, g.geometryData = s, g.topology = b, n.push(g); + }); +} +function sd(i) { + const e = []; + for (let t = 0; t < i.length; t++) { + const n = i[t].shape, s = []; + hi[n.type].build(n, s) && e.push(s); + } + return e; +} +class rd { + constructor() { + this.batches = [], this.geometryData = { + vertices: [], + uvs: [], + indices: [] + }; + } +} +class ad { + constructor() { + this.instructions = new uo(); + } + init(e) { + this.batcher = new Nc({ + maxTextures: e + }), this.instructions.reset(); + } + /** + * @deprecated since version 8.0.0 + * Use `batcher.geometry` instead. + * @see {Batcher#geometry} + */ + get geometry() { + return j(Ql, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead."), this.batcher.geometry; + } + destroy() { + this.batcher.destroy(), this.instructions.destroy(), this.batcher = null, this.instructions = null; + } +} +const $s = class rs { + constructor(e) { + this._gpuContextHash = {}, this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null), this._renderer = e, e.renderableGC.addManagedHash(this, "_gpuContextHash"), e.renderableGC.addManagedHash(this, "_graphicsDataContextHash"); + } + /** + * Runner init called, update the default options + * @ignore + */ + init(e) { + rs.defaultOptions.bezierSmoothness = (e == null ? void 0 : e.bezierSmoothness) ?? rs.defaultOptions.bezierSmoothness; + } + /** + * Returns the render data for a given GraphicsContext. + * @param context - The GraphicsContext to get the render data for. + * @internal + */ + getContextRenderData(e) { + return this._graphicsDataContextHash[e.uid] || this._initContextRenderData(e); + } + /** + * 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(e) { + let t = this._gpuContextHash[e.uid] || this._initContext(e); + if (e.dirty) { + t ? this._cleanGraphicsContextData(e) : t = this._initContext(e), nd(e, t); + const n = e.batchMode; + e.customShader || n === "no-batch" ? t.isBatchable = !1 : n === "auto" ? t.isBatchable = t.geometryData.vertices.length < 400 : t.isBatchable = !0, e.dirty = !1; + } + return t; + } + /** + * 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(e) { + return this._gpuContextHash[e.uid] || this._initContext(e); + } + _initContextRenderData(e) { + const t = Ue.get(ad, { + maxTextures: this._renderer.limits.maxBatchableTextures + }), { batches: n, geometryData: s } = this._gpuContextHash[e.uid], r = s.vertices.length, a = s.indices.length; + for (let h = 0; h < n.length; h++) + n[h].applyTransform = !1; + const o = t.batcher; + o.ensureAttributeBuffer(r), o.ensureIndexBuffer(a), o.begin(); + for (let h = 0; h < n.length; h++) { + const c = n[h]; + o.add(c); + } + o.finish(t.instructions); + const l = o.geometry; + l.indexBuffer.setDataWithSize(o.indexBuffer, o.indexSize, !0), l.buffers[0].setDataWithSize(o.attributeBuffer.float32View, o.attributeSize, !0); + const u = o.batches; + for (let h = 0; h < u.length; h++) { + const c = u[h]; + c.bindGroup = jh( + c.textures.textures, + c.textures.count, + this._renderer.limits.maxBatchableTextures + ); + } + return this._graphicsDataContextHash[e.uid] = t, t; + } + _initContext(e) { + const t = new rd(); + return t.context = e, this._gpuContextHash[e.uid] = t, e.on("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[e.uid]; + } + onGraphicsContextDestroy(e) { + this._cleanGraphicsContextData(e), e.off("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[e.uid] = null; + } + _cleanGraphicsContextData(e) { + const t = this._gpuContextHash[e.uid]; + t.isBatchable || this._graphicsDataContextHash[e.uid] && (Ue.return(this.getContextRenderData(e)), this._graphicsDataContextHash[e.uid] = null), t.batches && t.batches.forEach((n) => { + Ue.return(n); + }); + } + destroy() { + for (const e in this._gpuContextHash) + this._gpuContextHash[e] && this.onGraphicsContextDestroy(this._gpuContextHash[e].context); + } +}; +$s.extension = { + type: [ + X.WebGLSystem, + X.WebGPUSystem, + X.CanvasSystem + ], + name: "graphicsContext" +}; +$s.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 rl = $s; +const od = 8, Ln = 11920929e-14, ld = 1; +function al(i, e, t, n, s, r, a, o, l, u) { + const c = Math.min( + 0.99, + // a value of 1.0 actually inverts smoothing, so we cap it at 0.99 + Math.max(0, u ?? rl.defaultOptions.bezierSmoothness) + ); + let f = (ld - c) / 1; + return f *= f, ud(e, t, n, s, r, a, o, l, i, f), i; +} +function ud(i, e, t, n, s, r, a, o, l, u) { + as(i, e, t, n, s, r, a, o, l, u, 0), l.push(a, o); +} +function as(i, e, t, n, s, r, a, o, l, u, h) { + if (h > od) + return; + const c = (i + t) / 2, f = (e + n) / 2, d = (t + s) / 2, p = (n + r) / 2, b = (s + a) / 2, m = (r + o) / 2, x = (c + d) / 2, g = (f + p) / 2, _ = (d + b) / 2, y = (p + m) / 2, C = (x + _) / 2, v = (g + y) / 2; + if (h > 0) { + let w = a - i, $ = o - e; + const D = Math.abs((t - a) * $ - (n - o) * w), k = Math.abs((s - a) * $ - (r - o) * w); + if (D > Ln && k > Ln) { + if ((D + k) * (D + k) <= u * (w * w + $ * $)) { + l.push(C, v); + return; + } + } else if (D > Ln) { + if (D * D <= u * (w * w + $ * $)) { + l.push(C, v); + return; + } + } else if (k > Ln) { + if (k * k <= u * (w * w + $ * $)) { + l.push(C, v); + return; + } + } else if (w = C - (i + a) / 2, $ = v - (e + o) / 2, w * w + $ * $ <= u) { + l.push(C, v); + return; + } + } + as(i, e, c, f, x, g, C, v, l, u, h + 1), as(C, v, _, y, b, m, a, o, l, u, h + 1); +} +const hd = 8, cd = 11920929e-14, dd = 1; +function fd(i, e, t, n, s, r, a, o) { + const u = Math.min( + 0.99, + // a value of 1.0 actually inverts smoothing, so we cap it at 0.99 + Math.max(0, o ?? rl.defaultOptions.bezierSmoothness) + ); + let h = (dd - u) / 1; + return h *= h, _d(e, t, n, s, r, a, i, h), i; +} +function _d(i, e, t, n, s, r, a, o) { + os(a, i, e, t, n, s, r, o, 0), a.push(s, r); +} +function os(i, e, t, n, s, r, a, o, l) { + if (l > hd) + return; + const u = (e + n) / 2, h = (t + s) / 2, c = (n + r) / 2, f = (s + a) / 2, d = (u + c) / 2, p = (h + f) / 2; + let b = r - e, m = a - t; + const x = Math.abs((n - r) * m - (s - a) * b); + if (x > cd) { + if (x * x <= o * (b * b + m * m)) { + i.push(d, p); + return; + } + } else if (b = d - (e + r) / 2, m = p - (t + a) / 2, b * b + m * m <= o) { + i.push(d, p); + return; + } + os(i, e, t, u, h, d, p, o, l + 1), os(i, d, p, c, f, r, a, o, l + 1); +} +function ol(i, e, t, n, s, r, a, o) { + let l = Math.abs(s - r); + (!a && s > r || a && r > s) && (l = 2 * Math.PI - l), o || (o = Math.max(6, Math.floor(6 * Math.pow(n, 1 / 3) * (l / Math.PI)))), o = Math.max(o, 3); + let u = l / o, h = s; + u *= a ? -1 : 1; + for (let c = 0; c < o + 1; c++) { + const f = Math.cos(h), d = Math.sin(h), p = e + f * n, b = t + d * n; + i.push(p, b), h += u; + } +} +function pd(i, e, t, n, s, r) { + const a = i[i.length - 2], l = i[i.length - 1] - t, u = a - e, h = s - t, c = n - e, f = Math.abs(l * c - u * h); + if (f < 1e-8 || r === 0) { + (i[i.length - 2] !== e || i[i.length - 1] !== t) && i.push(e, t); + return; + } + const d = l * l + u * u, p = h * h + c * c, b = l * h + u * c, m = r * Math.sqrt(d) / f, x = r * Math.sqrt(p) / f, g = m * b / d, _ = x * b / p, y = m * c + x * u, C = m * h + x * l, v = u * (x + g), w = l * (x + g), $ = c * (m + _), D = h * (m + _), k = Math.atan2(w - C, v - y), F = Math.atan2(D - C, $ - y); + ol( + i, + y + e, + C + t, + r, + k, + F, + u * h > c * l + ); +} +const ln = Math.PI * 2, Ti = { + centerX: 0, + centerY: 0, + ang1: 0, + ang2: 0 +}, Mi = ({ x: i, y: e }, t, n, s, r, a, o, l) => { + i *= t, e *= n; + const u = s * i - r * e, h = r * i + s * e; + return l.x = u + a, l.y = h + o, l; +}; +function md(i, e) { + const t = e === -1.5707963267948966 ? -0.551915024494 : 1.3333333333333333 * Math.tan(e / 4), n = e === 1.5707963267948966 ? 0.551915024494 : t, s = Math.cos(i), r = Math.sin(i), a = Math.cos(i + e), o = Math.sin(i + e); + return [ + { + x: s - r * n, + y: r + s * n + }, + { + x: a + o * n, + y: o - a * n + }, + { + x: a, + y: o + } + ]; +} +const Nr = (i, e, t, n) => { + const s = i * n - e * t < 0 ? -1 : 1; + let r = i * t + e * n; + return r > 1 && (r = 1), r < -1 && (r = -1), s * Math.acos(r); +}, gd = (i, e, t, n, s, r, a, o, l, u, h, c, f) => { + const d = Math.pow(s, 2), p = Math.pow(r, 2), b = Math.pow(h, 2), m = Math.pow(c, 2); + let x = d * p - d * m - p * b; + x < 0 && (x = 0), x /= d * m + p * b, x = Math.sqrt(x) * (a === o ? -1 : 1); + const g = x * s / r * c, _ = x * -r / s * h, y = u * g - l * _ + (i + t) / 2, C = l * g + u * _ + (e + n) / 2, v = (h - g) / s, w = (c - _) / r, $ = (-h - g) / s, D = (-c - _) / r, k = Nr(1, 0, v, w); + let F = Nr(v, w, $, D); + o === 0 && F > 0 && (F -= ln), o === 1 && F < 0 && (F += ln), f.centerX = y, f.centerY = C, f.ang1 = k, f.ang2 = F; +}; +function yd(i, e, t, n, s, r, a, o = 0, l = 0, u = 0) { + if (r === 0 || a === 0) + return; + const h = Math.sin(o * ln / 360), c = Math.cos(o * ln / 360), f = c * (e - n) / 2 + h * (t - s) / 2, d = -h * (e - n) / 2 + c * (t - s) / 2; + if (f === 0 && d === 0) + return; + r = Math.abs(r), a = Math.abs(a); + const p = Math.pow(f, 2) / Math.pow(r, 2) + Math.pow(d, 2) / Math.pow(a, 2); + p > 1 && (r *= Math.sqrt(p), a *= Math.sqrt(p)), gd( + e, + t, + n, + s, + r, + a, + l, + u, + h, + c, + f, + d, + Ti + ); + let { ang1: b, ang2: m } = Ti; + const { centerX: x, centerY: g } = Ti; + let _ = Math.abs(m) / (ln / 4); + Math.abs(1 - _) < 1e-7 && (_ = 1); + const y = Math.max(Math.ceil(_), 1); + m /= y; + let C = i[i.length - 2], v = i[i.length - 1]; + const w = { x: 0, y: 0 }; + for (let $ = 0; $ < y; $++) { + const D = md(b, m), { x: k, y: F } = Mi(D[0], r, a, c, h, x, g, w), { x: I, y: z } = Mi(D[1], r, a, c, h, x, g, w), { x: G, y: de } = Mi(D[2], r, a, c, h, x, g, w); + al( + i, + C, + v, + k, + F, + I, + z, + G, + de + ), C = G, v = de, b += m; + } +} +function bd(i, e, t) { + const n = (a, o) => { + const l = o.x - a.x, u = o.y - a.y, h = Math.sqrt(l * l + u * u), c = l / h, f = u / h; + return { len: h, nx: c, ny: f }; + }, s = (a, o) => { + a === 0 ? i.moveTo(o.x, o.y) : i.lineTo(o.x, o.y); + }; + let r = e[e.length - 1]; + for (let a = 0; a < e.length; a++) { + const o = e[a % e.length], l = o.radius ?? t; + if (l <= 0) { + s(a, o), r = o; + continue; + } + const u = e[(a + 1) % e.length], h = n(o, r), c = n(o, u); + if (h.len < 1e-4 || c.len < 1e-4) { + s(a, o), r = o; + continue; + } + let f = Math.asin(h.nx * c.ny - h.ny * c.nx), d = 1, p = !1; + h.nx * c.nx - h.ny * -c.ny < 0 ? f < 0 ? f = Math.PI + f : (f = Math.PI - f, d = -1, p = !0) : f > 0 && (d = -1, p = !0); + const b = f / 2; + let m, x = Math.abs( + Math.cos(b) * l / Math.sin(b) + ); + x > Math.min(h.len / 2, c.len / 2) ? (x = Math.min(h.len / 2, c.len / 2), m = Math.abs(x * Math.sin(b) / Math.cos(b))) : m = l; + const g = o.x + c.nx * x + -c.ny * m * d, _ = o.y + c.ny * x + c.nx * m * d, y = Math.atan2(h.ny, h.nx) + Math.PI / 2 * d, C = Math.atan2(c.ny, c.nx) - Math.PI / 2 * d; + a === 0 && i.moveTo( + g + Math.cos(y) * m, + _ + Math.sin(y) * m + ), i.arc(g, _, m, y, C, p), r = o; + } +} +function xd(i, e, t, n) { + const s = (o, l) => Math.sqrt((o.x - l.x) ** 2 + (o.y - l.y) ** 2), r = (o, l, u) => ({ + x: o.x + (l.x - o.x) * u, + y: o.y + (l.y - o.y) * u + }), a = e.length; + for (let o = 0; o < a; o++) { + const l = e[(o + 1) % a], u = l.radius ?? t; + if (u <= 0) { + o === 0 ? i.moveTo(l.x, l.y) : i.lineTo(l.x, l.y); + continue; + } + const h = e[o], c = e[(o + 2) % a], f = s(h, l); + let d; + if (f < 1e-4) + d = l; + else { + const m = Math.min(f / 2, u); + d = r( + l, + h, + m / f + ); + } + const p = s(c, l); + let b; + if (p < 1e-4) + b = l; + else { + const m = Math.min(p / 2, u); + b = r( + l, + c, + m / p + ); + } + o === 0 ? i.moveTo(d.x, d.y) : i.lineTo(d.x, d.y), i.quadraticCurveTo(l.x, l.y, b.x, b.y, n); + } +} +const vd = new ce(); +class wd { + constructor(e) { + this.shapePrimitives = [], this._currentPoly = null, this._bounds = new Je(), this._graphicsPath2D = e, this.signed = e.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(e, t) { + return this.startPoly(e, t), 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(e, t) { + this._ensurePoly(); + const n = this._currentPoly.points, s = n[n.length - 2], r = n[n.length - 1]; + return (s !== e || r !== t) && n.push(e, t), 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(e, t, n, s, r, a) { + this._ensurePoly(!1); + const o = this._currentPoly.points; + return ol(o, e, t, n, s, r, a), 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(e, t, n, s, r) { + this._ensurePoly(); + const a = this._currentPoly.points; + return pd(a, e, t, n, s, r), 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(e, t, n, s, r, a, o) { + const l = this._currentPoly.points; + return yd( + l, + this._currentPoly.lastX, + this._currentPoly.lastY, + a, + o, + e, + t, + n, + s, + r + ), 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(e, t, n, s, r, a, o) { + this._ensurePoly(); + const l = this._currentPoly; + return al( + this._currentPoly.points, + l.lastX, + l.lastY, + e, + t, + n, + s, + r, + a, + o + ), 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(e, t, n, s, r) { + this._ensurePoly(); + const a = this._currentPoly; + return fd( + this._currentPoly.points, + a.lastX, + a.lastY, + e, + t, + n, + s, + r + ), 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() { + return this.endPoly(!0), 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(e, t) { + this.endPoly(), t && !t.isIdentity() && (e = e.clone(!0), e.transform(t)); + const n = this.shapePrimitives, s = n.length; + for (let r = 0; r < e.instructions.length; r++) { + const a = e.instructions[r]; + this[a.action](...a.data); + } + if (e.checkForHoles && n.length - s > 1) { + let r = null; + for (let a = s; a < n.length; a++) { + const o = n[a]; + if (o.shape.type === "polygon") { + const l = o.shape, u = r == null ? void 0 : r.shape; + u && u.containsPolygon(l) ? (r.holes || (r.holes = []), r.holes.push(o), n.copyWithin(a, a + 1), n.length--, a--) : r = o; + } + } + } + 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(e = !1) { + this.endPoly(e); + } + /** + * 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(e, t, n, s, r) { + return this.drawShape(new ce(e, t, n, s), r), 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(e, t, n, s) { + return this.drawShape(new Ss(e, t, n), s), 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(e, t, n) { + const s = new an(e); + return s.closePath = t, this.drawShape(s, n), 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(e, t, n, s, r = 0, a) { + s = Math.max(s | 0, 3); + const o = -1 * Math.PI / 2 + r, l = Math.PI * 2 / s, u = []; + for (let h = 0; h < s; h++) { + const c = o - h * l; + u.push( + e + n * Math.cos(c), + t + n * Math.sin(c) + ); + } + return this.poly(u, !0, a), 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(e, t, n, s, r, a = 0, o) { + if (s = Math.max(s | 0, 3), r <= 0) + return this.regularPoly(e, t, n, s, a); + const l = n * Math.sin(Math.PI / s) - 1e-3; + r = Math.min(r, l); + const u = -1 * Math.PI / 2 + a, h = Math.PI * 2 / s, c = (s - 2) * Math.PI / s / 2; + for (let f = 0; f < s; f++) { + const d = f * h + u, p = e + n * Math.cos(d), b = t + n * Math.sin(d), m = d + Math.PI + c, x = d - Math.PI - c, g = p + r * Math.cos(m), _ = b + r * Math.sin(m), y = p + r * Math.cos(x), C = b + r * Math.sin(x); + f === 0 ? this.moveTo(g, _) : this.lineTo(g, _), this.quadraticCurveTo(p, b, y, C, o); + } + 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(e, t, n = !1, s) { + return e.length < 3 ? this : (n ? xd(this, e, t, s) : bd(this, e, t), 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(e, t, n, s, r) { + if (r === 0) + return this.rect(e, t, n, s); + const a = Math.min(n, s) / 2, o = Math.min(a, Math.max(-a, r)), l = e + n, u = t + s, h = o < 0 ? -o : 0, c = Math.abs(o); + return this.moveTo(e, t + c).arcTo(e + h, t + h, e + c, t, c).lineTo(l - c, t).arcTo(l - h, t + h, l, t + c, c).lineTo(l, u - c).arcTo(l - h, u - h, e + n - c, u, c).lineTo(e + c, u).arcTo(e + h, u - h, e, u - c, c).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(e, t, n, s, r, a) { + if (r <= 0) + return this.rect(e, t, n, s); + const o = Math.min(r, Math.min(n, s) / 2), l = e + n, u = t + s, h = [ + e + o, + t, + l - o, + t, + l, + t + o, + l, + u - o, + l - o, + u, + e + o, + u, + e, + u - o, + e, + t + o + ]; + for (let c = h.length - 1; c >= 2; c -= 2) + h[c] === h[c - 2] && h[c - 1] === h[c - 3] && h.splice(c - 1, 2); + return this.poly(h, !0, a); + } + /** + * 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(e, t, n, s, r) { + return this.drawShape(new Es(e, t, n, s), r), 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(e, t, n, s, r, a) { + return this.drawShape(new Fs(e, t, n, s, r), a), 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(e, t) { + return this.endPoly(), this.shapePrimitives.push({ shape: e, transform: t }), 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(e, t) { + let n = this._currentPoly; + return n && this.endPoly(), n = new an(), n.points.push(e, t), this._currentPoly = n, 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(e = !1) { + const t = this._currentPoly; + return t && t.points.length > 2 && (t.closePath = e, this.shapePrimitives.push({ shape: t })), this._currentPoly = null, this; + } + _ensurePoly(e = !0) { + if (!this._currentPoly && (this._currentPoly = new an(), e)) { + const t = this.shapePrimitives[this.shapePrimitives.length - 1]; + if (t) { + let n = t.shape.x, s = t.shape.y; + if (t.transform && !t.transform.isIdentity()) { + const r = t.transform, a = n; + n = r.a * n + r.c * s + r.tx, s = r.b * a + r.d * s + r.ty; + } + this._currentPoly.points.push(n, s); + } else + this._currentPoly.points.push(0, 0); + } + } + /** Builds the path. */ + buildPath() { + const e = this._graphicsPath2D; + this.shapePrimitives.length = 0, this._currentPoly = null; + for (let t = 0; t < e.instructions.length; t++) { + const n = e.instructions[t]; + this[n.action](...n.data); + } + this.finish(); + } + /** Gets the bounds of the path. */ + get bounds() { + const e = this._bounds; + e.clear(); + const t = this.shapePrimitives; + for (let n = 0; n < t.length; n++) { + const s = t[n], r = s.shape.getBounds(vd); + s.transform ? e.addRect(r, s.transform) : e.addRect(r); + } + return e; + } +} +class ct { + /** + * 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(e, t = !1) { + this.instructions = [], this.uid = re("graphicsPath"), this._dirty = !0, this.checkForHoles = t, typeof e == "string" ? Hh(e, this) : this.instructions = (e == null ? void 0 : e.slice()) ?? []; + } + /** + * 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() { + return this._shapePath || (this._shapePath = new wd(this)), this._dirty && (this._dirty = !1, this._shapePath.buildPath()), 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(e, t) { + return e = e.clone(), this.instructions.push({ action: "addPath", data: [e, t] }), this._dirty = !0, this; + } + arc(...e) { + return this.instructions.push({ action: "arc", data: e }), this._dirty = !0, this; + } + arcTo(...e) { + return this.instructions.push({ action: "arcTo", data: e }), this._dirty = !0, this; + } + arcToSvg(...e) { + return this.instructions.push({ action: "arcToSvg", data: e }), this._dirty = !0, this; + } + bezierCurveTo(...e) { + return this.instructions.push({ action: "bezierCurveTo", data: e }), this._dirty = !0, 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(e, t, n, s, r) { + const a = this.instructions[this.instructions.length - 1], o = this.getLastPoint(ge.shared); + let l = 0, u = 0; + if (!a || a.action !== "bezierCurveTo") + l = o.x, u = o.y; + else { + l = a.data[2], u = a.data[3]; + const h = o.x, c = o.y; + l = h + (h - l), u = c + (c - u); + } + return this.instructions.push({ action: "bezierCurveTo", data: [l, u, e, t, n, s, r] }), this._dirty = !0, 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() { + return this.instructions.push({ action: "closePath", data: [] }), this._dirty = !0, this; + } + ellipse(...e) { + return this.instructions.push({ action: "ellipse", data: e }), this._dirty = !0, this; + } + lineTo(...e) { + return this.instructions.push({ action: "lineTo", data: e }), this._dirty = !0, this; + } + moveTo(...e) { + return this.instructions.push({ action: "moveTo", data: e }), this; + } + quadraticCurveTo(...e) { + return this.instructions.push({ action: "quadraticCurveTo", data: e }), this._dirty = !0, 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(e, t, n) { + const s = this.instructions[this.instructions.length - 1], r = this.getLastPoint(ge.shared); + let a = 0, o = 0; + if (!s || s.action !== "quadraticCurveTo") + a = r.x, o = r.y; + else { + a = s.data[0], o = s.data[1]; + const l = r.x, u = r.y; + a = l + (l - a), o = u + (u - o); + } + return this.instructions.push({ action: "quadraticCurveTo", data: [a, o, e, t, n] }), this._dirty = !0, 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(e, t, n, s, r) { + return this.instructions.push({ action: "rect", data: [e, t, n, s, r] }), this._dirty = !0, 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(e, t, n, s) { + return this.instructions.push({ action: "circle", data: [e, t, n, s] }), this._dirty = !0, this; + } + roundRect(...e) { + return this.instructions.push({ action: "roundRect", data: e }), this._dirty = !0, this; + } + poly(...e) { + return this.instructions.push({ action: "poly", data: e }), this._dirty = !0, this; + } + regularPoly(...e) { + return this.instructions.push({ action: "regularPoly", data: e }), this._dirty = !0, this; + } + roundPoly(...e) { + return this.instructions.push({ action: "roundPoly", data: e }), this._dirty = !0, this; + } + roundShape(...e) { + return this.instructions.push({ action: "roundShape", data: e }), this._dirty = !0, this; + } + filletRect(...e) { + return this.instructions.push({ action: "filletRect", data: e }), this._dirty = !0, this; + } + chamferRect(...e) { + return this.instructions.push({ action: "chamferRect", data: e }), this._dirty = !0, 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(e, t, n, s, r, a, o) { + r || (r = s / 2); + const l = -1 * Math.PI / 2 + a, u = n * 2, h = Math.PI * 2 / u, c = []; + for (let f = 0; f < u; f++) { + const d = f % 2 ? r : s, p = f * h + l; + c.push( + e + d * Math.cos(p), + t + d * Math.sin(p) + ); + } + return this.poly(c, !0, o), 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(e = !1) { + const t = new ct(); + if (t.checkForHoles = this.checkForHoles, !e) + t.instructions = this.instructions.slice(); + else + for (let n = 0; n < this.instructions.length; n++) { + const s = this.instructions[n]; + t.instructions.push({ action: s.action, data: s.data.slice() }); + } + return t; + } + clear() { + return this.instructions.length = 0, this._dirty = !0, 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(e) { + if (e.isIdentity()) + return this; + const t = e.a, n = e.b, s = e.c, r = e.d, a = e.tx, o = e.ty; + let l = 0, u = 0, h = 0, c = 0, f = 0, d = 0, p = 0, b = 0; + for (let m = 0; m < this.instructions.length; m++) { + const x = this.instructions[m], g = x.data; + switch (x.action) { + case "moveTo": + case "lineTo": + l = g[0], u = g[1], g[0] = t * l + s * u + a, g[1] = n * l + r * u + o; + break; + case "bezierCurveTo": + h = g[0], c = g[1], f = g[2], d = g[3], l = g[4], u = g[5], g[0] = t * h + s * c + a, g[1] = n * h + r * c + o, g[2] = t * f + s * d + a, g[3] = n * f + r * d + o, g[4] = t * l + s * u + a, g[5] = n * l + r * u + o; + break; + case "quadraticCurveTo": + h = g[0], c = g[1], l = g[2], u = g[3], g[0] = t * h + s * c + a, g[1] = n * h + r * c + o, g[2] = t * l + s * u + a, g[3] = n * l + r * u + o; + break; + case "arcToSvg": + l = g[5], u = g[6], p = g[0], b = g[1], g[0] = t * p + s * b, g[1] = n * p + r * b, g[5] = t * l + s * u + a, g[6] = n * l + r * u + o; + break; + case "circle": + g[4] = Xt(g[3], e); + break; + case "rect": + g[4] = Xt(g[4], e); + break; + case "ellipse": + g[8] = Xt(g[8], e); + break; + case "roundRect": + g[5] = Xt(g[5], e); + break; + case "addPath": + g[0].transform(e); + break; + case "poly": + g[2] = Xt(g[2], e); + break; + default: + Fe("unknown transform action", x.action); + break; + } + } + return this._dirty = !0, 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(e) { + let t = this.instructions.length - 1, n = this.instructions[t]; + if (!n) + return e.x = 0, e.y = 0, e; + for (; n.action === "closePath"; ) { + if (t--, t < 0) + return e.x = 0, e.y = 0, e; + n = this.instructions[t]; + } + switch (n.action) { + case "moveTo": + case "lineTo": + e.x = n.data[0], e.y = n.data[1]; + break; + case "quadraticCurveTo": + e.x = n.data[2], e.y = n.data[3]; + break; + case "bezierCurveTo": + e.x = n.data[4], e.y = n.data[5]; + break; + case "arc": + case "arcToSvg": + e.x = n.data[5], e.y = n.data[6]; + break; + case "addPath": + n.data[0].getLastPoint(e); + break; + } + return e; + } +} +function Xt(i, e) { + return i ? i.prepend(e) : e.clone(); +} +function se(i, e, t) { + const n = i.getAttribute(e); + return n ? Number(n) : t; +} +function Cd(i, e) { + const t = i.querySelectorAll("defs"); + for (let n = 0; n < t.length; n++) { + const s = t[n]; + for (let r = 0; r < s.children.length; r++) { + const a = s.children[r]; + switch (a.nodeName.toLowerCase()) { + case "lineargradient": + e.defs[a.id] = Ad(a); + break; + case "radialgradient": + e.defs[a.id] = kd(); + break; + } + } + } +} +function Ad(i) { + const e = se(i, "x1", 0), t = se(i, "y1", 0), n = se(i, "x2", 1), s = se(i, "y2", 0), r = i.getAttribute("gradientUnits") || "objectBoundingBox", a = new xn( + e, + t, + n, + s, + r === "objectBoundingBox" ? "local" : "global" + ); + for (let o = 0; o < i.children.length; o++) { + const l = i.children[o], u = se(l, "offset", 0), h = qe.shared.setValue(l.getAttribute("stop-color")).toNumber(); + a.addColorStop(u, h); + } + return a; +} +function kd(i) { + return Fe("[SVG Parser] Radial gradients are not yet supported"), new xn(0, 0, 1, 0); +} +function Or(i) { + const e = i.match(/url\s*\(\s*['"]?\s*#([^'"\s)]+)\s*['"]?\s*\)/i); + return e ? e[1] : ""; +} +const Gr = { + // 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 ll(i, e) { + const t = i.getAttribute("style"), n = {}, s = {}, r = { + strokeStyle: n, + fillStyle: s, + useFill: !1, + useStroke: !1 + }; + for (const a in Gr) { + const o = i.getAttribute(a); + o && zr(e, r, a, o.trim()); + } + if (t) { + const a = t.split(";"); + for (let o = 0; o < a.length; o++) { + const l = a[o].trim(), [u, h] = l.split(":"); + Gr[u] && zr(e, r, u, h.trim()); + } + } + return { + strokeStyle: r.useStroke ? n : null, + fillStyle: r.useFill ? s : null, + useFill: r.useFill, + useStroke: r.useStroke + }; +} +function zr(i, e, t, n) { + switch (t) { + case "stroke": + if (n !== "none") { + if (n.startsWith("url(")) { + const s = Or(n); + e.strokeStyle.fill = i.defs[s]; + } else + e.strokeStyle.color = qe.shared.setValue(n).toNumber(); + e.useStroke = !0; + } + break; + case "stroke-width": + e.strokeStyle.width = Number(n); + break; + case "fill": + if (n !== "none") { + if (n.startsWith("url(")) { + const s = Or(n); + e.fillStyle.fill = i.defs[s]; + } else + e.fillStyle.color = qe.shared.setValue(n).toNumber(); + e.useFill = !0; + } + break; + case "fill-opacity": + e.fillStyle.alpha = Number(n); + break; + case "stroke-opacity": + e.strokeStyle.alpha = Number(n); + break; + case "opacity": + e.fillStyle.alpha = Number(n), e.strokeStyle.alpha = Number(n); + break; + } +} +function Dd(i) { + if (i.length <= 2) + return !0; + const e = i.map((o) => o.area).sort((o, l) => l - o), [t, n] = e, s = e[e.length - 1], r = t / n, a = n / s; + return !(r > 3 && a < 2); +} +function Sd(i) { + return i.split(/(?=[Mm])/).filter((n) => n.trim().length > 0); +} +function Ed(i) { + const e = i.match(/[-+]?[0-9]*\.?[0-9]+/g); + if (!e || e.length < 4) + return 0; + const t = e.map(Number), n = [], s = []; + for (let h = 0; h < t.length; h += 2) + h + 1 < t.length && (n.push(t[h]), s.push(t[h + 1])); + if (n.length === 0 || s.length === 0) + return 0; + const r = Math.min(...n), a = Math.max(...n), o = Math.min(...s), l = Math.max(...s); + return (a - r) * (l - o); +} +function qr(i, e) { + const t = new ct(i, !1); + for (const n of t.instructions) + e.instructions.push(n); +} +function Fd(i, e) { + if (typeof i == "string") { + const a = document.createElement("div"); + a.innerHTML = i.trim(), i = a.querySelector("svg"); + } + const t = { + context: e, + defs: {}, + path: new ct() + }; + Cd(i, t); + const n = i.children, { fillStyle: s, strokeStyle: r } = ll(i, t); + for (let a = 0; a < n.length; a++) { + const o = n[a]; + o.nodeName.toLowerCase() !== "defs" && ul(o, t, s, r); + } + return e; +} +function ul(i, e, t, n) { + const s = i.children, { fillStyle: r, strokeStyle: a } = ll(i, e); + r && t ? t = { ...t, ...r } : r && (t = r), a && n ? n = { ...n, ...a } : a && (n = a); + const o = !t && !n; + o && (t = { color: 0 }); + let l, u, h, c, f, d, p, b, m, x, g, _, y, C, v, w, $; + switch (i.nodeName.toLowerCase()) { + case "path": { + C = i.getAttribute("d"); + const D = i.getAttribute("fill-rule"), k = Sd(C), F = D === "evenodd", I = k.length > 1; + if (F && I) { + const G = k.map((A) => ({ + path: A, + area: Ed(A) + })); + if (G.sort((A, E) => E.area - A.area), k.length > 3 || !Dd(G)) + for (let A = 0; A < G.length; A++) { + const E = G[A], B = A === 0; + e.context.beginPath(); + const T = new ct(void 0, !0); + qr(E.path, T), e.context.path(T), B ? (t && e.context.fill(t), n && e.context.stroke(n)) : e.context.cut(); + } + else + for (let A = 0; A < G.length; A++) { + const E = G[A], B = A % 2 === 1; + e.context.beginPath(); + const T = new ct(void 0, !0); + qr(E.path, T), e.context.path(T), B ? e.context.cut() : (t && e.context.fill(t), n && e.context.stroke(n)); + } + } else { + const G = D ? D === "evenodd" : !0; + v = new ct(C, G), e.context.path(v), t && e.context.fill(t), n && e.context.stroke(n); + } + break; + } + case "circle": + p = se(i, "cx", 0), b = se(i, "cy", 0), m = se(i, "r", 0), e.context.ellipse(p, b, m, m), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "rect": + l = se(i, "x", 0), u = se(i, "y", 0), w = se(i, "width", 0), $ = se(i, "height", 0), x = se(i, "rx", 0), g = se(i, "ry", 0), x || g ? e.context.roundRect(l, u, w, $, x || g) : e.context.rect(l, u, w, $), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "ellipse": + p = se(i, "cx", 0), b = se(i, "cy", 0), x = se(i, "rx", 0), g = se(i, "ry", 0), e.context.beginPath(), e.context.ellipse(p, b, x, g), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "line": + h = se(i, "x1", 0), c = se(i, "y1", 0), f = se(i, "x2", 0), d = se(i, "y2", 0), e.context.beginPath(), e.context.moveTo(h, c), e.context.lineTo(f, d), n && e.context.stroke(n); + break; + case "polygon": + y = i.getAttribute("points"), _ = y.match(/\d+/g).map((D) => parseInt(D, 10)), e.context.poly(_, !0), t && e.context.fill(t), n && e.context.stroke(n); + break; + case "polyline": + y = i.getAttribute("points"), _ = y.match(/\d+/g).map((D) => parseInt(D, 10)), e.context.poly(_, !1), n && e.context.stroke(n); + break; + case "g": + case "svg": + break; + default: { + Fe(`[SVG parser] <${i.nodeName}> elements unsupported`); + break; + } + } + o && (t = null); + for (let D = 0; D < s.length; D++) + ul(s[D], e, t, n); +} +function $d(i) { + return qe.isColorLike(i); +} +function Ur(i) { + return i instanceof Lh; +} +function Hr(i) { + return i instanceof xn; +} +function Td(i) { + return i instanceof W; +} +function Md(i, e, t) { + const n = qe.shared.setValue(e ?? 0); + return i.color = n.toNumber(), i.alpha = n.alpha === 1 ? t.alpha : n.alpha, i.texture = W.WHITE, { ...t, ...i }; +} +function Pd(i, e, t) { + return i.texture = e, { ...t, ...i }; +} +function Vr(i, e, t) { + return i.fill = e, i.color = 16777215, i.texture = e.texture, i.matrix = e.transform, { ...t, ...i }; +} +function Yr(i, e, t) { + return e.buildGradient(), i.fill = e, i.color = 16777215, i.texture = e.texture, i.matrix = e.transform, i.textureSpace = e.textureSpace, { ...t, ...i }; +} +function Id(i, e) { + const t = { ...e, ...i }, n = qe.shared.setValue(t.color); + return t.alpha *= n.alpha, t.color = n.toNumber(), t; +} +function sn(i, e) { + if (i == null) + return null; + const t = {}, n = i; + return $d(i) ? Md(t, i, e) : Td(i) ? Pd(t, i, e) : Ur(i) ? Vr(t, i, e) : Hr(i) ? Yr(t, i, e) : n.fill && Ur(n.fill) ? Vr(n, n.fill, e) : n.fill && Hr(n.fill) ? Yr(n, n.fill, e) : Id(n, e); +} +function Xr(i, e) { + const { width: t, alignment: n, miterLimit: s, cap: r, join: a, pixelLine: o, ...l } = e, u = sn(i, l); + return u ? { + width: t, + alignment: n, + miterLimit: s, + cap: r, + join: a, + pixelLine: o, + ...u + } : null; +} +const Rd = new ge(), jr = new q(), Ts = class st extends dt { + constructor() { + super(...arguments), this.uid = re("graphicsContext"), this.dirty = !0, this.batchMode = "auto", this.instructions = [], this._activePath = new ct(), this._transform = new q(), this._fillStyle = { ...st.defaultFillStyle }, this._strokeStyle = { ...st.defaultStrokeStyle }, this._stateStack = [], this._tick = 0, this._bounds = new Je(), this._boundsDirty = !0; + } + /** + * 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 e = new st(); + return e.batchMode = this.batchMode, e.instructions = this.instructions.slice(), e._activePath = this._activePath.clone(), e._transform = this._transform.clone(), e._fillStyle = { ...this._fillStyle }, e._strokeStyle = { ...this._strokeStyle }, e._stateStack = this._stateStack.slice(), e._bounds = this._bounds.clone(), e._boundsDirty = !0, e; + } + /** + * 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(e) { + this._fillStyle = sn(e, st.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(e) { + this._strokeStyle = Xr(e, st.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(e) { + return this._fillStyle = sn(e, st.defaultFillStyle), 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(e) { + return this._strokeStyle = sn(e, st.defaultStrokeStyle), this; + } + texture(e, t, n, s, r, a) { + return this.instructions.push({ + action: "texture", + data: { + image: e, + dx: n || 0, + dy: s || 0, + dw: r || e.frame.width, + dh: a || e.frame.height, + transform: this._transform.clone(), + alpha: this._fillStyle.alpha, + style: t ? qe.shared.setValue(t).toNumber() : 16777215 + } + }), this.onUpdate(), 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() { + return this._activePath = new ct(), this; + } + fill(e, t) { + let n; + const s = this.instructions[this.instructions.length - 1]; + return this._tick === 0 && s && s.action === "stroke" ? n = s.data.path : n = this._activePath.clone(), n ? (e != null && (t !== void 0 && typeof e == "number" && (j(le, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead"), e = { color: e, alpha: t }), this._fillStyle = sn(e, st.defaultFillStyle)), this.instructions.push({ + action: "fill", + // TODO copy fill style! + data: { style: this.fillStyle, path: n } + }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this; + } + _initNextPathLocation() { + const { x: e, y: t } = this._activePath.getLastPoint(ge.shared); + this._activePath.clear(), this._activePath.moveTo(e, t); + } + /** + * 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(e) { + let t; + const n = this.instructions[this.instructions.length - 1]; + return this._tick === 0 && n && n.action === "fill" ? t = n.data.path : t = this._activePath.clone(), t ? (e != null && (this._strokeStyle = Xr(e, st.defaultStrokeStyle)), this.instructions.push({ + action: "stroke", + // TODO copy fill style! + data: { style: this.strokeStyle, path: t } + }), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : 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 e = 0; e < 2; e++) { + const t = this.instructions[this.instructions.length - 1 - e], n = this._activePath.clone(); + if (t && (t.action === "stroke" || t.action === "fill")) + if (t.data.hole) + t.data.hole.addPath(n); + else { + t.data.hole = n; + break; + } + } + return this._initNextPathLocation(), 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(e, t, n, s, r, a) { + this._tick++; + const o = this._transform; + return this._activePath.arc( + o.a * e + o.c * t + o.tx, + o.b * e + o.d * t + o.ty, + n, + s, + r, + a + ), 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(e, t, n, s, r) { + this._tick++; + const a = this._transform; + return this._activePath.arcTo( + a.a * e + a.c * t + a.tx, + a.b * e + a.d * t + a.ty, + a.a * n + a.c * s + a.tx, + a.b * n + a.d * s + a.ty, + r + ), 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(e, t, n, s, r, a, o) { + this._tick++; + const l = this._transform; + return this._activePath.arcToSvg( + e, + t, + n, + // should we rotate this with transform?? + s, + r, + l.a * a + l.c * o + l.tx, + l.b * a + l.d * o + l.ty + ), 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(e, t, n, s, r, a, o) { + this._tick++; + const l = this._transform; + return this._activePath.bezierCurveTo( + l.a * e + l.c * t + l.tx, + l.b * e + l.d * t + l.ty, + l.a * n + l.c * s + l.tx, + l.b * n + l.d * s + l.ty, + l.a * r + l.c * a + l.tx, + l.b * r + l.d * a + l.ty, + o + ), 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 e; + return this._tick++, (e = this._activePath) == null || e.closePath(), 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(e, t, n, s) { + return this._tick++, this._activePath.ellipse(e, t, n, s, this._transform.clone()), 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(e, t, n) { + return this._tick++, this._activePath.circle(e, t, n, this._transform.clone()), 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(e) { + return this._tick++, this._activePath.addPath(e, this._transform.clone()), 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(e, t) { + this._tick++; + const n = this._transform; + return this._activePath.lineTo( + n.a * e + n.c * t + n.tx, + n.b * e + n.d * t + n.ty + ), 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(e, t) { + this._tick++; + const n = this._transform, s = this._activePath.instructions, r = n.a * e + n.c * t + n.tx, a = n.b * e + n.d * t + n.ty; + return s.length === 1 && s[0].action === "moveTo" ? (s[0].data[0] = r, s[0].data[1] = a, this) : (this._activePath.moveTo( + r, + a + ), 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(e, t, n, s, r) { + this._tick++; + const a = this._transform; + return this._activePath.quadraticCurveTo( + a.a * e + a.c * t + a.tx, + a.b * e + a.d * t + a.ty, + a.a * n + a.c * s + a.tx, + a.b * n + a.d * s + a.ty, + r + ), 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(e, t, n, s) { + return this._tick++, this._activePath.rect(e, t, n, s, this._transform.clone()), 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(e, t, n, s, r) { + return this._tick++, this._activePath.roundRect(e, t, n, s, r, this._transform.clone()), 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(e, t) { + return this._tick++, this._activePath.poly(e, t, this._transform.clone()), 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(e, t, n, s, r = 0, a) { + return this._tick++, this._activePath.regularPoly(e, t, n, s, r, a), 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(e, t, n, s, r, a) { + return this._tick++, this._activePath.roundPoly(e, t, n, s, r, a), 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(e, t, n, s) { + return this._tick++, this._activePath.roundShape(e, t, n, s), 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(e, t, n, s, r) { + return this._tick++, this._activePath.filletRect(e, t, n, s, r), 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(e, t, n, s, r, a) { + return this._tick++, this._activePath.chamferRect(e, t, n, s, r, a), 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(e, t, n, s, r = 0, a = 0) { + return this._tick++, this._activePath.star(e, t, n, s, r, a, this._transform.clone()), 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(e) { + return this._tick++, Fd(e, this), 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 e = this._stateStack.pop(); + return e && (this._transform = e.transform, this._fillStyle = e.fillStyle, this._strokeStyle = e.strokeStyle), this; + } + /** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */ + save() { + return this._stateStack.push({ + transform: this._transform.clone(), + fillStyle: { ...this._fillStyle }, + strokeStyle: { ...this._strokeStyle } + }), 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() { + return this._transform.identity(), 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(e) { + return this._transform.rotate(e), 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(e, t = e) { + return this._transform.scale(e, t), this; + } + setTransform(e, t, n, s, r, a) { + return e instanceof q ? (this._transform.set(e.a, e.b, e.c, e.d, e.tx, e.ty), this) : (this._transform.set(e, t, n, s, r, a), this); + } + transform(e, t, n, s, r, a) { + return e instanceof q ? (this._transform.append(e), this) : (jr.set(e, t, n, s, r, a), this._transform.append(jr), 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(e, t = e) { + return this._transform.translate(e, t), 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() { + return this._activePath.clear(), this.instructions.length = 0, this.resetTransform(), this.onUpdate(), this; + } + onUpdate() { + this._boundsDirty = !0, !this.dirty && (this.emit("update", this, 16), this.dirty = !0); + } + /** The bounds of the graphic shape. */ + get bounds() { + if (!this._boundsDirty) + return this._bounds; + this._boundsDirty = !1; + const e = this._bounds; + e.clear(); + for (let t = 0; t < this.instructions.length; t++) { + const n = this.instructions[t], s = n.action; + if (s === "fill") { + const r = n.data; + e.addBounds(r.path.bounds); + } else if (s === "texture") { + const r = n.data; + e.addFrame(r.dx, r.dy, r.dx + r.dw, r.dy + r.dh, r.transform); + } + if (s === "stroke") { + const r = n.data, a = r.style.alignment, o = r.style.width * (1 - a), l = r.path.bounds; + e.addFrame( + l.minX - o, + l.minY - o, + l.maxX + o, + l.maxY + o + ); + } + } + return e; + } + /** + * 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(e) { + var s; + if (!this.bounds.containsPoint(e.x, e.y)) + return !1; + const t = this.instructions; + let n = !1; + for (let r = 0; r < t.length; r++) { + const a = t[r], o = a.data, l = o.path; + if (!a.action || !l) + continue; + const u = o.style, h = l.shapePath.shapePrimitives; + for (let c = 0; c < h.length; c++) { + const f = h[c].shape; + if (!u || !f) + continue; + const d = h[c].transform, p = d ? d.applyInverse(e, Rd) : e; + if (a.action === "fill") + n = f.contains(p.x, p.y); + else { + const m = u; + n = f.strokeContains(p.x, p.y, m.width, m.alignment); + } + const b = o.hole; + if (b) { + const m = (s = b.shapePath) == null ? void 0 : s.shapePrimitives; + if (m) + for (let x = 0; x < m.length; x++) + m[x].shape.contains(p.x, p.y) && (n = !1); + } + if (n) + return !0; + } + } + return n; + } + /** + * 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(e = !1) { + if (this._stateStack.length = 0, this._transform = null, this.emit("destroy", this), this.removeAllListeners(), typeof e == "boolean" ? e : e == null ? void 0 : e.texture) { + const n = typeof e == "boolean" ? e : e == null ? void 0 : e.textureSource; + this._fillStyle.texture && (this._fillStyle.fill && "uid" in this._fillStyle.fill ? this._fillStyle.fill.destroy() : this._fillStyle.texture.destroy(n)), this._strokeStyle.texture && (this._strokeStyle.fill && "uid" in this._strokeStyle.fill ? this._strokeStyle.fill.destroy() : this._strokeStyle.texture.destroy(n)); + } + this._fillStyle = null, this._strokeStyle = null, this.instructions = null, this._activePath = null, this._bounds = null, this._stateStack = null, this.customShader = null, this._transform = null; + } +}; +Ts.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: W.WHITE, + /** The matrix to apply. */ + matrix: null, + /** The fill pattern to use. */ + fill: null, + /** Whether coordinates are 'global' or 'local' */ + textureSpace: "local" +}; +Ts.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: W.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: !1 +}; +let jt = Ts; +class ei extends co { + /** + * Creates a new Graphics object. + * @param options - Options for the Graphics. + */ + constructor(e) { + e instanceof jt && (e = { context: e }); + const { context: t, roundPixels: n, ...s } = e || {}; + super({ + label: "Graphics", + ...s + }), this.renderPipeId = "graphics", t ? this._context = t : this._context = this._ownedContext = new jt(), this._context.on("update", this.onViewUpdate, this), this.didViewUpdate = !0, this.allowChildren = !1, this.roundPixels = n ?? !1; + } + set context(e) { + e !== this._context && (this._context.off("update", this.onViewUpdate, this), this._context = e, this._context.on("update", this.onViewUpdate, 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(e) { + return this._context.containsPoint(e); + } + /** + * 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(e) { + this._ownedContext && !e ? this._ownedContext.destroy(e) : (e === !0 || (e == null ? void 0 : e.context) === !0) && this._context.destroy(e), this._ownedContext = null, this._context = null, super.destroy(e); + } + _callContextMethod(e, t) { + return this.context[e](...t), 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(...e) { + return this._callContextMethod("setFillStyle", e); + } + /** + * 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(...e) { + return this._callContextMethod("setStrokeStyle", e); + } + fill(...e) { + return this._callContextMethod("fill", e); + } + /** + * 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(...e) { + return this._callContextMethod("stroke", e); + } + texture(...e) { + return this._callContextMethod("texture", e); + } + /** + * 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(...e) { + return this._callContextMethod("arc", e); + } + arcTo(...e) { + return this._callContextMethod("arcTo", e); + } + arcToSvg(...e) { + return this._callContextMethod("arcToSvg", e); + } + bezierCurveTo(...e) { + return this._callContextMethod("bezierCurveTo", e); + } + /** + * 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(...e) { + return this._callContextMethod("ellipse", e); + } + circle(...e) { + return this._callContextMethod("circle", e); + } + path(...e) { + return this._callContextMethod("path", e); + } + lineTo(...e) { + return this._callContextMethod("lineTo", e); + } + moveTo(...e) { + return this._callContextMethod("moveTo", e); + } + quadraticCurveTo(...e) { + return this._callContextMethod("quadraticCurveTo", e); + } + rect(...e) { + return this._callContextMethod("rect", e); + } + roundRect(...e) { + return this._callContextMethod("roundRect", e); + } + poly(...e) { + return this._callContextMethod("poly", e); + } + regularPoly(...e) { + return this._callContextMethod("regularPoly", e); + } + roundPoly(...e) { + return this._callContextMethod("roundPoly", e); + } + roundShape(...e) { + return this._callContextMethod("roundShape", e); + } + filletRect(...e) { + return this._callContextMethod("filletRect", e); + } + chamferRect(...e) { + return this._callContextMethod("chamferRect", e); + } + star(...e) { + return this._callContextMethod("star", e); + } + svg(...e) { + return this._callContextMethod("svg", e); + } + restore(...e) { + return this._callContextMethod("restore", e); + } + /** + * 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(...e) { + return this._callContextMethod("rotate", e); + } + scaleTransform(...e) { + return this._callContextMethod("scale", e); + } + setTransform(...e) { + return this._callContextMethod("setTransform", e); + } + transform(...e) { + return this._callContextMethod("transform", e); + } + translateTransform(...e) { + return this._callContextMethod("translate", e); + } + /** + * 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(e) { + this._context.fillStyle = e; + } + /** + * 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(e) { + this._context.strokeStyle = e; + } + /** + * 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(e = !1) { + return e ? new ei(this._context.clone()) : (this._ownedContext = null, new ei(this._context)); + } + // -------- v7 deprecations --------- + /** + * @param width + * @param color + * @param alpha + * @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead + */ + lineStyle(e, t, n) { + j(le, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style."); + const s = {}; + return e && (s.width = e), t && (s.color = t), n && (s.alpha = n), this.context.strokeStyle = s, this; + } + /** + * @param color + * @param alpha + * @deprecated since 8.0.0 Use {@link Graphics#fill} instead + */ + beginFill(e, t) { + j(le, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."); + const n = {}; + return e !== void 0 && (n.color = e), t !== void 0 && (n.alpha = t), this.context.fillStyle = n, this; + } + /** + * @deprecated since 8.0.0 Use {@link Graphics#fill} instead + */ + endFill() { + j(le, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."), this.context.fill(); + const e = this.context.strokeStyle; + return (e.width !== jt.defaultStrokeStyle.width || e.color !== jt.defaultStrokeStyle.color || e.alpha !== jt.defaultStrokeStyle.alpha) && this.context.stroke(), this; + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#circle} instead + */ + drawCircle(...e) { + return j(le, "Graphics#drawCircle has been renamed to Graphics#circle"), this._callContextMethod("circle", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead + */ + drawEllipse(...e) { + return j(le, "Graphics#drawEllipse has been renamed to Graphics#ellipse"), this._callContextMethod("ellipse", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#poly} instead + */ + drawPolygon(...e) { + return j(le, "Graphics#drawPolygon has been renamed to Graphics#poly"), this._callContextMethod("poly", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#rect} instead + */ + drawRect(...e) { + return j(le, "Graphics#drawRect has been renamed to Graphics#rect"), this._callContextMethod("rect", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead + */ + drawRoundedRect(...e) { + return j(le, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect"), this._callContextMethod("roundRect", e); + } + /** + * @param {...any} args + * @deprecated since 8.0.0 Use {@link Graphics#star} instead + */ + drawStar(...e) { + return j(le, "Graphics#drawStar has been renamed to Graphics#star"), this._callContextMethod("star", e); + } +} +Ve.add(Ul, Hl); +const { + SvelteComponent: Bd, + append_hydration: ls, + assign: Ld, + attr: pe, + binding_callbacks: Nd, + children: un, + claim_element: hl, + claim_space: cl, + claim_svg_element: Pi, + create_slot: Od, + detach: rt, + element: dl, + empty: Wr, + get_all_dirty_from_scope: Gd, + get_slot_changes: zd, + get_spread_update: qd, + init: Ud, + insert_hydration: bn, + listen: Hd, + noop: Vd, + safe_not_equal: Yd, + set_dynamic_element_data: Zr, + set_style: Y, + space: fl, + svg_element: Ii, + toggle_class: ue, + transition_in: _l, + transition_out: pl, + update_slot_base: Xd +} = window.__gradio__svelte__internal; +function Kr(i) { + let e, t, n, s, r; + return { + c() { + e = Ii("svg"), t = Ii("line"), n = Ii("line"), this.h(); + }, + l(a) { + e = Pi(a, "svg", { class: !0, xmlns: !0, viewBox: !0 }); + var o = un(e); + t = Pi(o, "line", { + x1: !0, + y1: !0, + x2: !0, + y2: !0, + stroke: !0, + "stroke-width": !0 + }), un(t).forEach(rt), n = Pi(o, "line", { + x1: !0, + y1: !0, + x2: !0, + y2: !0, + stroke: !0, + "stroke-width": !0 + }), un(n).forEach(rt), o.forEach(rt), this.h(); + }, + h() { + pe(t, "x1", "1"), pe(t, "y1", "9"), pe(t, "x2", "9"), pe(t, "y2", "1"), pe(t, "stroke", "gray"), pe(t, "stroke-width", "0.5"), pe(n, "x1", "5"), pe(n, "y1", "9"), pe(n, "x2", "9"), pe(n, "y2", "5"), pe(n, "stroke", "gray"), pe(n, "stroke-width", "0.5"), pe(e, "class", "resize-handle svelte-239wnu"), pe(e, "xmlns", "http://www.w3.org/2000/svg"), pe(e, "viewBox", "0 0 10 10"); + }, + m(a, o) { + bn(a, e, o), ls(e, t), ls(e, n), s || (r = Hd( + e, + "mousedown", + /*resize*/ + i[27] + ), s = !0); + }, + p: Vd, + d(a) { + a && rt(e), s = !1, r(); + } + }; +} +function jd(i) { + var c; + let e, t, n, s, r; + const a = ( + /*#slots*/ + i[31].default + ), o = Od( + a, + i, + /*$$scope*/ + i[30], + null + ); + let l = ( + /*resizable*/ + i[19] && Kr(i) + ), u = [ + { "data-testid": ( + /*test_id*/ + i[11] + ) }, + { id: ( + /*elem_id*/ + i[6] + ) }, + { + class: n = "block " + /*elem_classes*/ + (((c = i[7]) == null ? void 0 : c.join(" ")) || "") + " svelte-239wnu" + }, + { + dir: s = /*rtl*/ + i[20] ? "rtl" : "ltr" + } + ], h = {}; + for (let f = 0; f < u.length; f += 1) + h = Ld(h, u[f]); + return { + c() { + e = dl( + /*tag*/ + i[25] + ), o && o.c(), t = fl(), l && l.c(), this.h(); + }, + l(f) { + e = hl( + f, + /*tag*/ + (i[25] || "null").toUpperCase(), + { + "data-testid": !0, + id: !0, + class: !0, + dir: !0 + } + ); + var d = un(e); + o && o.l(d), t = cl(d), l && l.l(d), d.forEach(rt), this.h(); + }, + h() { + Zr( + /*tag*/ + i[25] + )(e, h), ue( + e, + "hidden", + /*visible*/ + i[14] === !1 || /*visible*/ + i[14] === "hidden" + ), ue( + e, + "padded", + /*padding*/ + i[10] + ), ue( + e, + "flex", + /*flex*/ + i[1] + ), ue( + e, + "border_focus", + /*border_mode*/ + i[9] === "focus" + ), ue( + e, + "border_contrast", + /*border_mode*/ + i[9] === "contrast" + ), ue(e, "hide-container", !/*explicit_call*/ + i[12] && !/*container*/ + i[13]), ue( + e, + "fullscreen", + /*fullscreen*/ + i[0] + ), ue( + e, + "animating", + /*fullscreen*/ + i[0] && /*preexpansionBoundingRect*/ + i[24] !== null + ), ue( + e, + "auto-margin", + /*scale*/ + i[17] === null + ), Y( + e, + "height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*height*/ + i[2] + ) + ) + ), Y( + e, + "min-height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*min_height*/ + i[3] + ) + ) + ), Y( + e, + "max-height", + /*fullscreen*/ + i[0] ? void 0 : ( + /*get_dimension*/ + i[26]( + /*max_height*/ + i[4] + ) + ) + ), Y( + e, + "--start-top", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].top}px` : "0px" + ), Y( + e, + "--start-left", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].left}px` : "0px" + ), Y( + e, + "--start-width", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].width}px` : "0px" + ), Y( + e, + "--start-height", + /*preexpansionBoundingRect*/ + i[24] ? `${/*preexpansionBoundingRect*/ + i[24].height}px` : "0px" + ), Y( + e, + "width", + /*fullscreen*/ + i[0] ? void 0 : typeof /*width*/ + i[5] == "number" ? `calc(min(${/*width*/ + i[5]}px, 100%))` : ( + /*get_dimension*/ + i[26]( + /*width*/ + i[5] + ) + ) + ), Y( + e, + "border-style", + /*variant*/ + i[8] + ), Y( + e, + "overflow", + /*allow_overflow*/ + i[15] ? ( + /*overflow_behavior*/ + i[16] + ) : "hidden" + ), Y( + e, + "flex-grow", + /*scale*/ + i[17] + ), Y(e, "min-width", `calc(min(${/*min_width*/ + i[18]}px, 100%))`), Y(e, "border-width", "var(--block-border-width)"); + }, + m(f, d) { + bn(f, e, d), o && o.m(e, null), ls(e, t), l && l.m(e, null), i[32](e), r = !0; + }, + p(f, d) { + var p; + o && o.p && (!r || d[0] & /*$$scope*/ + 1073741824) && Xd( + o, + a, + f, + /*$$scope*/ + f[30], + r ? zd( + a, + /*$$scope*/ + f[30], + d, + null + ) : Gd( + /*$$scope*/ + f[30] + ), + null + ), /*resizable*/ + f[19] ? l ? l.p(f, d) : (l = Kr(f), l.c(), l.m(e, null)) : l && (l.d(1), l = null), Zr( + /*tag*/ + f[25] + )(e, h = qd(u, [ + (!r || d[0] & /*test_id*/ + 2048) && { "data-testid": ( + /*test_id*/ + f[11] + ) }, + (!r || d[0] & /*elem_id*/ + 64) && { id: ( + /*elem_id*/ + f[6] + ) }, + (!r || d[0] & /*elem_classes*/ + 128 && n !== (n = "block " + /*elem_classes*/ + (((p = f[7]) == null ? void 0 : p.join(" ")) || "") + " svelte-239wnu")) && { class: n }, + (!r || d[0] & /*rtl*/ + 1048576 && s !== (s = /*rtl*/ + f[20] ? "rtl" : "ltr")) && { dir: s } + ])), ue( + e, + "hidden", + /*visible*/ + f[14] === !1 || /*visible*/ + f[14] === "hidden" + ), ue( + e, + "padded", + /*padding*/ + f[10] + ), ue( + e, + "flex", + /*flex*/ + f[1] + ), ue( + e, + "border_focus", + /*border_mode*/ + f[9] === "focus" + ), ue( + e, + "border_contrast", + /*border_mode*/ + f[9] === "contrast" + ), ue(e, "hide-container", !/*explicit_call*/ + f[12] && !/*container*/ + f[13]), ue( + e, + "fullscreen", + /*fullscreen*/ + f[0] + ), ue( + e, + "animating", + /*fullscreen*/ + f[0] && /*preexpansionBoundingRect*/ + f[24] !== null + ), ue( + e, + "auto-margin", + /*scale*/ + f[17] === null + ), d[0] & /*fullscreen, height*/ + 5 && Y( + e, + "height", + /*fullscreen*/ + f[0] ? void 0 : ( + /*get_dimension*/ + f[26]( + /*height*/ + f[2] + ) + ) + ), d[0] & /*fullscreen, min_height*/ + 9 && Y( + e, + "min-height", + /*fullscreen*/ + f[0] ? void 0 : ( + /*get_dimension*/ + f[26]( + /*min_height*/ + f[3] + ) + ) + ), d[0] & /*fullscreen, max_height*/ + 17 && Y( + e, + "max-height", + /*fullscreen*/ + f[0] ? void 0 : ( + /*get_dimension*/ + f[26]( + /*max_height*/ + f[4] + ) + ) + ), d[0] & /*preexpansionBoundingRect*/ + 16777216 && Y( + e, + "--start-top", + /*preexpansionBoundingRect*/ + f[24] ? `${/*preexpansionBoundingRect*/ + f[24].top}px` : "0px" + ), d[0] & /*preexpansionBoundingRect*/ + 16777216 && Y( + e, + "--start-left", + /*preexpansionBoundingRect*/ + f[24] ? `${/*preexpansionBoundingRect*/ + f[24].left}px` : "0px" + ), d[0] & /*preexpansionBoundingRect*/ + 16777216 && Y( + e, + "--start-width", + /*preexpansionBoundingRect*/ + f[24] ? `${/*preexpansionBoundingRect*/ + f[24].width}px` : "0px" + ), d[0] & /*preexpansionBoundingRect*/ + 16777216 && Y( + e, + "--start-height", + /*preexpansionBoundingRect*/ + f[24] ? `${/*preexpansionBoundingRect*/ + f[24].height}px` : "0px" + ), d[0] & /*fullscreen, width*/ + 33 && Y( + e, + "width", + /*fullscreen*/ + f[0] ? void 0 : typeof /*width*/ + f[5] == "number" ? `calc(min(${/*width*/ + f[5]}px, 100%))` : ( + /*get_dimension*/ + f[26]( + /*width*/ + f[5] + ) + ) + ), d[0] & /*variant*/ + 256 && Y( + e, + "border-style", + /*variant*/ + f[8] + ), d[0] & /*allow_overflow, overflow_behavior*/ + 98304 && Y( + e, + "overflow", + /*allow_overflow*/ + f[15] ? ( + /*overflow_behavior*/ + f[16] + ) : "hidden" + ), d[0] & /*scale*/ + 131072 && Y( + e, + "flex-grow", + /*scale*/ + f[17] + ), d[0] & /*min_width*/ + 262144 && Y(e, "min-width", `calc(min(${/*min_width*/ + f[18]}px, 100%))`); + }, + i(f) { + r || (_l(o, f), r = !0); + }, + o(f) { + pl(o, f), r = !1; + }, + d(f) { + f && rt(e), o && o.d(f), l && l.d(), i[32](null); + } + }; +} +function Qr(i) { + let e; + return { + c() { + e = dl("div"), this.h(); + }, + l(t) { + e = hl(t, "DIV", { class: !0 }), un(e).forEach(rt), this.h(); + }, + h() { + pe(e, "class", "placeholder svelte-239wnu"), Y( + e, + "height", + /*placeholder_height*/ + i[22] + "px" + ), Y( + e, + "width", + /*placeholder_width*/ + i[23] + "px" + ); + }, + m(t, n) { + bn(t, e, n); + }, + p(t, n) { + n[0] & /*placeholder_height*/ + 4194304 && Y( + e, + "height", + /*placeholder_height*/ + t[22] + "px" + ), n[0] & /*placeholder_width*/ + 8388608 && Y( + e, + "width", + /*placeholder_width*/ + t[23] + "px" + ); + }, + d(t) { + t && rt(e); + } + }; +} +function Wd(i) { + let e, t, n, s = ( + /*tag*/ + i[25] && jd(i) + ), r = ( + /*fullscreen*/ + i[0] && Qr(i) + ); + return { + c() { + s && s.c(), e = fl(), r && r.c(), t = Wr(); + }, + l(a) { + s && s.l(a), e = cl(a), r && r.l(a), t = Wr(); + }, + m(a, o) { + s && s.m(a, o), bn(a, e, o), r && r.m(a, o), bn(a, t, o), n = !0; + }, + p(a, o) { + /*tag*/ + a[25] && s.p(a, o), /*fullscreen*/ + a[0] ? r ? r.p(a, o) : (r = Qr(a), r.c(), r.m(t.parentNode, t)) : r && (r.d(1), r = null); + }, + i(a) { + n || (_l(s, a), n = !0); + }, + o(a) { + pl(s, a), n = !1; + }, + d(a) { + a && (rt(e), rt(t)), s && s.d(a), r && r.d(a); + } + }; +} +function Zd(i, e, t) { + let { $$slots: n = {}, $$scope: s } = e, { height: r = void 0 } = e, { min_height: a = void 0 } = e, { max_height: o = void 0 } = e, { width: l = void 0 } = e, { elem_id: u = "" } = e, { elem_classes: h = [] } = e, { variant: c = "solid" } = e, { border_mode: f = "base" } = e, { padding: d = !0 } = e, { type: p = "normal" } = e, { test_id: b = void 0 } = e, { explicit_call: m = !1 } = e, { container: x = !0 } = e, { visible: g = !0 } = e, { allow_overflow: _ = !0 } = e, { overflow_behavior: y = "auto" } = e, { scale: C = null } = e, { min_width: v = 0 } = e, { flex: w = !1 } = e, { resizable: $ = !1 } = e, { rtl: D = !1 } = e, { fullscreen: k = !1 } = e, F = k, I, z = p === "fieldset" ? "fieldset" : "div", G = 0, de = 0, A = null; + function E(S) { + k && S.key === "Escape" && t(0, k = !1); + } + const B = (S) => { + if (S !== void 0) { + if (typeof S == "number") + return S + "px"; + if (typeof S == "string") + return S; + } + }, T = (S) => { + let R = S.clientY; + const U = (Q) => { + const V = Q.clientY - R; + R = Q.clientY, t(21, I.style.height = `${I.offsetHeight + V}px`, I); + }, N = () => { + window.removeEventListener("mousemove", U), window.removeEventListener("mouseup", N); + }; + window.addEventListener("mousemove", U), window.addEventListener("mouseup", N); + }; + function O(S) { + Nd[S ? "unshift" : "push"](() => { + I = S, t(21, I); + }); + } + return i.$$set = (S) => { + "height" in S && t(2, r = S.height), "min_height" in S && t(3, a = S.min_height), "max_height" in S && t(4, o = S.max_height), "width" in S && t(5, l = S.width), "elem_id" in S && t(6, u = S.elem_id), "elem_classes" in S && t(7, h = S.elem_classes), "variant" in S && t(8, c = S.variant), "border_mode" in S && t(9, f = S.border_mode), "padding" in S && t(10, d = S.padding), "type" in S && t(28, p = S.type), "test_id" in S && t(11, b = S.test_id), "explicit_call" in S && t(12, m = S.explicit_call), "container" in S && t(13, x = S.container), "visible" in S && t(14, g = S.visible), "allow_overflow" in S && t(15, _ = S.allow_overflow), "overflow_behavior" in S && t(16, y = S.overflow_behavior), "scale" in S && t(17, C = S.scale), "min_width" in S && t(18, v = S.min_width), "flex" in S && t(1, w = S.flex), "resizable" in S && t(19, $ = S.resizable), "rtl" in S && t(20, D = S.rtl), "fullscreen" in S && t(0, k = S.fullscreen), "$$scope" in S && t(30, s = S.$$scope); + }, i.$$.update = () => { + i.$$.dirty[0] & /*fullscreen, old_fullscreen, element*/ + 538968065 && k !== F && (t(29, F = k), k ? (t(24, A = I.getBoundingClientRect()), t(22, G = I.offsetHeight), t(23, de = I.offsetWidth), window.addEventListener("keydown", E)) : (t(24, A = null), window.removeEventListener("keydown", E))), i.$$.dirty[0] & /*visible*/ + 16384 && (g || t(1, w = !1)); + }, [ + k, + w, + r, + a, + o, + l, + u, + h, + c, + f, + d, + b, + m, + x, + g, + _, + y, + C, + v, + $, + D, + I, + G, + de, + A, + z, + B, + T, + p, + F, + s, + n, + O + ]; +} +class Kd extends Bd { + constructor(e) { + super(), Ud( + this, + e, + Zd, + Wd, + Yd, + { + height: 2, + min_height: 3, + max_height: 4, + width: 5, + elem_id: 6, + elem_classes: 7, + variant: 8, + border_mode: 9, + padding: 10, + type: 28, + test_id: 11, + explicit_call: 12, + container: 13, + visible: 14, + allow_overflow: 15, + overflow_behavior: 16, + scale: 17, + min_width: 18, + flex: 1, + resizable: 19, + rtl: 20, + fullscreen: 0 + }, + null, + [-1, -1] + ); + } +} +function Ms() { + return { + async: !1, + breaks: !1, + extensions: null, + gfm: !0, + hooks: null, + pedantic: !1, + renderer: null, + silent: !1, + tokenizer: null, + walkTokens: null + }; +} +let St = Ms(); +function ml(i) { + St = i; +} +const gl = /[&<>"']/, Qd = new RegExp(gl.source, "g"), yl = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, Jd = new RegExp(yl.source, "g"), ef = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" +}, Jr = (i) => ef[i]; +function Se(i, e) { + if (e) { + if (gl.test(i)) + return i.replace(Qd, Jr); + } else if (yl.test(i)) + return i.replace(Jd, Jr); + return i; +} +const tf = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; +function nf(i) { + return i.replace(tf, (e, t) => (t = t.toLowerCase(), t === "colon" ? ":" : t.charAt(0) === "#" ? t.charAt(1) === "x" ? String.fromCharCode(parseInt(t.substring(2), 16)) : String.fromCharCode(+t.substring(1)) : "")); +} +const sf = /(^|[^\[])\^/g; +function K(i, e) { + let t = typeof i == "string" ? i : i.source; + e = e || ""; + const n = { + replace: (s, r) => { + let a = typeof r == "string" ? r : r.source; + return a = a.replace(sf, "$1"), t = t.replace(s, a), n; + }, + getRegex: () => new RegExp(t, e) + }; + return n; +} +function ea(i) { + try { + i = encodeURI(i).replace(/%25/g, "%"); + } catch { + return null; + } + return i; +} +const hn = { exec: () => null }; +function ta(i, e) { + const t = i.replace(/\|/g, (r, a, o) => { + let l = !1, u = a; + for (; --u >= 0 && o[u] === "\\"; ) + l = !l; + return l ? "|" : " |"; + }), n = t.split(/ \|/); + let s = 0; + if (n[0].trim() || n.shift(), n.length > 0 && !n[n.length - 1].trim() && n.pop(), e) + if (n.length > e) + n.splice(e); + else + for (; n.length < e; ) + n.push(""); + for (; s < n.length; s++) + n[s] = n[s].trim().replace(/\\\|/g, "|"); + return n; +} +function Nn(i, e, t) { + const n = i.length; + if (n === 0) + return ""; + let s = 0; + for (; s < n && i.charAt(n - s - 1) === e; ) + s++; + return i.slice(0, n - s); +} +function rf(i, e) { + if (i.indexOf(e[1]) === -1) + return -1; + let t = 0; + for (let n = 0; n < i.length; n++) + if (i[n] === "\\") + n++; + else if (i[n] === e[0]) + t++; + else if (i[n] === e[1] && (t--, t < 0)) + return n; + return -1; +} +function na(i, e, t, n) { + const s = e.href, r = e.title ? Se(e.title) : null, a = i[1].replace(/\\([\[\]])/g, "$1"); + if (i[0].charAt(0) !== "!") { + n.state.inLink = !0; + const o = { + type: "link", + raw: t, + href: s, + title: r, + text: a, + tokens: n.inlineTokens(a) + }; + return n.state.inLink = !1, o; + } + return { + type: "image", + raw: t, + href: s, + title: r, + text: Se(a) + }; +} +function af(i, e) { + const t = i.match(/^(\s+)(?:```)/); + if (t === null) + return e; + const n = t[1]; + return e.split(` +`).map((s) => { + const r = s.match(/^\s+/); + if (r === null) + return s; + const [a] = r; + return a.length >= n.length ? s.slice(n.length) : s; + }).join(` +`); +} +class ti { + // set by the lexer + constructor(e) { + ee(this, "options"); + ee(this, "rules"); + // set by the lexer + ee(this, "lexer"); + this.options = e || St; + } + space(e) { + const t = this.rules.block.newline.exec(e); + if (t && t[0].length > 0) + return { + type: "space", + raw: t[0] + }; + } + code(e) { + const t = this.rules.block.code.exec(e); + if (t) { + const n = t[0].replace(/^ {1,4}/gm, ""); + return { + type: "code", + raw: t[0], + codeBlockStyle: "indented", + text: this.options.pedantic ? n : Nn(n, ` +`) + }; + } + } + fences(e) { + const t = this.rules.block.fences.exec(e); + if (t) { + const n = t[0], s = af(n, t[3] || ""); + return { + type: "code", + raw: n, + lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], + text: s + }; + } + } + heading(e) { + const t = this.rules.block.heading.exec(e); + if (t) { + let n = t[2].trim(); + if (/#$/.test(n)) { + const s = Nn(n, "#"); + (this.options.pedantic || !s || / $/.test(s)) && (n = s.trim()); + } + return { + type: "heading", + raw: t[0], + depth: t[1].length, + text: n, + tokens: this.lexer.inline(n) + }; + } + } + hr(e) { + const t = this.rules.block.hr.exec(e); + if (t) + return { + type: "hr", + raw: t[0] + }; + } + blockquote(e) { + const t = this.rules.block.blockquote.exec(e); + if (t) { + let n = t[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, ` + $1`); + n = Nn(n.replace(/^ *>[ \t]?/gm, ""), ` +`); + const s = this.lexer.state.top; + this.lexer.state.top = !0; + const r = this.lexer.blockTokens(n); + return this.lexer.state.top = s, { + type: "blockquote", + raw: t[0], + tokens: r, + text: n + }; + } + } + list(e) { + let t = this.rules.block.list.exec(e); + if (t) { + let n = t[1].trim(); + const s = n.length > 1, r = { + type: "list", + raw: "", + ordered: s, + start: s ? +n.slice(0, -1) : "", + loose: !1, + items: [] + }; + n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]"); + const a = new RegExp(`^( {0,3}${n})((?:[ ][^\\n]*)?(?:\\n|$))`); + let o = "", l = "", u = !1; + for (; e; ) { + let h = !1; + if (!(t = a.exec(e)) || this.rules.block.hr.test(e)) + break; + o = t[0], e = e.substring(o.length); + let c = t[2].split(` +`, 1)[0].replace(/^\t+/, (x) => " ".repeat(3 * x.length)), f = e.split(` +`, 1)[0], d = 0; + this.options.pedantic ? (d = 2, l = c.trimStart()) : (d = t[2].search(/[^ ]/), d = d > 4 ? 1 : d, l = c.slice(d), d += t[1].length); + let p = !1; + if (!c && /^ *$/.test(f) && (o += f + ` +`, e = e.substring(f.length + 1), h = !0), !h) { + const x = new RegExp(`^ {0,${Math.min(3, d - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), g = new RegExp(`^ {0,${Math.min(3, d - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), _ = new RegExp(`^ {0,${Math.min(3, d - 1)}}(?:\`\`\`|~~~)`), y = new RegExp(`^ {0,${Math.min(3, d - 1)}}#`); + for (; e; ) { + const C = e.split(` +`, 1)[0]; + if (f = C, this.options.pedantic && (f = f.replace(/^ {1,4}(?=( {4})*[^ ])/g, " ")), _.test(f) || y.test(f) || x.test(f) || g.test(e)) + break; + if (f.search(/[^ ]/) >= d || !f.trim()) + l += ` +` + f.slice(d); + else { + if (p || c.search(/[^ ]/) >= 4 || _.test(c) || y.test(c) || g.test(c)) + break; + l += ` +` + f; + } + !p && !f.trim() && (p = !0), o += C + ` +`, e = e.substring(C.length + 1), c = f.slice(d); + } + } + r.loose || (u ? r.loose = !0 : /\n *\n *$/.test(o) && (u = !0)); + let b = null, m; + this.options.gfm && (b = /^\[[ xX]\] /.exec(l), b && (m = b[0] !== "[ ] ", l = l.replace(/^\[[ xX]\] +/, ""))), r.items.push({ + type: "list_item", + raw: o, + task: !!b, + checked: m, + loose: !1, + text: l, + tokens: [] + }), r.raw += o; + } + r.items[r.items.length - 1].raw = o.trimEnd(), r.items[r.items.length - 1].text = l.trimEnd(), r.raw = r.raw.trimEnd(); + for (let h = 0; h < r.items.length; h++) + if (this.lexer.state.top = !1, r.items[h].tokens = this.lexer.blockTokens(r.items[h].text, []), !r.loose) { + const c = r.items[h].tokens.filter((d) => d.type === "space"), f = c.length > 0 && c.some((d) => /\n.*\n/.test(d.raw)); + r.loose = f; + } + if (r.loose) + for (let h = 0; h < r.items.length; h++) + r.items[h].loose = !0; + return r; + } + } + html(e) { + const t = this.rules.block.html.exec(e); + if (t) + return { + type: "html", + block: !0, + raw: t[0], + pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", + text: t[0] + }; + } + def(e) { + const t = this.rules.block.def.exec(e); + if (t) { + const n = t[1].toLowerCase().replace(/\s+/g, " "), s = t[2] ? t[2].replace(/^<(.*)>$/, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3]; + return { + type: "def", + tag: n, + raw: t[0], + href: s, + title: r + }; + } + } + table(e) { + const t = this.rules.block.table.exec(e); + if (!t || !/[:|]/.test(t[2])) + return; + const n = ta(t[1]), s = t[2].replace(/^\||\| *$/g, "").split("|"), r = t[3] && t[3].trim() ? t[3].replace(/\n[ \t]*$/, "").split(` +`) : [], a = { + type: "table", + raw: t[0], + header: [], + align: [], + rows: [] + }; + if (n.length === s.length) { + for (const o of s) + /^ *-+: *$/.test(o) ? a.align.push("right") : /^ *:-+: *$/.test(o) ? a.align.push("center") : /^ *:-+ *$/.test(o) ? a.align.push("left") : a.align.push(null); + for (const o of n) + a.header.push({ + text: o, + tokens: this.lexer.inline(o) + }); + for (const o of r) + a.rows.push(ta(o, a.header.length).map((l) => ({ + text: l, + tokens: this.lexer.inline(l) + }))); + return a; + } + } + lheading(e) { + const t = this.rules.block.lheading.exec(e); + if (t) + return { + type: "heading", + raw: t[0], + depth: t[2].charAt(0) === "=" ? 1 : 2, + text: t[1], + tokens: this.lexer.inline(t[1]) + }; + } + paragraph(e) { + const t = this.rules.block.paragraph.exec(e); + if (t) { + const n = t[1].charAt(t[1].length - 1) === ` +` ? t[1].slice(0, -1) : t[1]; + return { + type: "paragraph", + raw: t[0], + text: n, + tokens: this.lexer.inline(n) + }; + } + } + text(e) { + const t = this.rules.block.text.exec(e); + if (t) + return { + type: "text", + raw: t[0], + text: t[0], + tokens: this.lexer.inline(t[0]) + }; + } + escape(e) { + const t = this.rules.inline.escape.exec(e); + if (t) + return { + type: "escape", + raw: t[0], + text: Se(t[1]) + }; + } + tag(e) { + const t = this.rules.inline.tag.exec(e); + if (t) + return !this.lexer.state.inLink && /^/i.test(t[0]) && (this.lexer.state.inLink = !1), !this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(t[0]) ? this.lexer.state.inRawBlock = !0 : this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0]) && (this.lexer.state.inRawBlock = !1), { + type: "html", + raw: t[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: !1, + text: t[0] + }; + } + link(e) { + const t = this.rules.inline.link.exec(e); + if (t) { + const n = t[2].trim(); + if (!this.options.pedantic && /^$/.test(n)) + return; + const a = Nn(n.slice(0, -1), "\\"); + if ((n.length - a.length) % 2 === 0) + return; + } else { + const a = rf(t[2], "()"); + if (a > -1) { + const l = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + a; + t[2] = t[2].substring(0, a), t[0] = t[0].substring(0, l).trim(), t[3] = ""; + } + } + let s = t[2], r = ""; + if (this.options.pedantic) { + const a = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(s); + a && (s = a[1], r = a[3]); + } else + r = t[3] ? t[3].slice(1, -1) : ""; + return s = s.trim(), /^$/.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), na(t, { + href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), + title: r && r.replace(this.rules.inline.anyPunctuation, "$1") + }, t[0], this.lexer); + } + } + reflink(e, t) { + let n; + if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) { + const s = (n[2] || n[1]).replace(/\s+/g, " "), r = t[s.toLowerCase()]; + if (!r) { + const a = n[0].charAt(0); + return { + type: "text", + raw: a, + text: a + }; + } + return na(n, r, n[0], this.lexer); + } + } + emStrong(e, t, n = "") { + let s = this.rules.inline.emStrongLDelim.exec(e); + if (!s || s[3] && n.match(/[\p{L}\p{N}]/u)) + return; + if (!(s[1] || s[2] || "") || !n || this.rules.inline.punctuation.exec(n)) { + const a = [...s[0]].length - 1; + let o, l, u = a, h = 0; + const c = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + for (c.lastIndex = 0, t = t.slice(-1 * e.length + a); (s = c.exec(t)) != null; ) { + if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) + continue; + if (l = [...o].length, s[3] || s[4]) { + u += l; + continue; + } else if ((s[5] || s[6]) && a % 3 && !((a + l) % 3)) { + h += l; + continue; + } + if (u -= l, u > 0) + continue; + l = Math.min(l, l + u + h); + const f = [...s[0]][0].length, d = e.slice(0, a + s.index + f + l); + if (Math.min(a, l) % 2) { + const b = d.slice(1, -1); + return { + type: "em", + raw: d, + text: b, + tokens: this.lexer.inlineTokens(b) + }; + } + const p = d.slice(2, -2); + return { + type: "strong", + raw: d, + text: p, + tokens: this.lexer.inlineTokens(p) + }; + } + } + } + codespan(e) { + const t = this.rules.inline.code.exec(e); + if (t) { + let n = t[2].replace(/\n/g, " "); + const s = /[^ ]/.test(n), r = /^ /.test(n) && / $/.test(n); + return s && r && (n = n.substring(1, n.length - 1)), n = Se(n, !0), { + type: "codespan", + raw: t[0], + text: n + }; + } + } + br(e) { + const t = this.rules.inline.br.exec(e); + if (t) + return { + type: "br", + raw: t[0] + }; + } + del(e) { + const t = this.rules.inline.del.exec(e); + if (t) + return { + type: "del", + raw: t[0], + text: t[2], + tokens: this.lexer.inlineTokens(t[2]) + }; + } + autolink(e) { + const t = this.rules.inline.autolink.exec(e); + if (t) { + let n, s; + return t[2] === "@" ? (n = Se(t[1]), s = "mailto:" + n) : (n = Se(t[1]), s = n), { + type: "link", + raw: t[0], + text: n, + href: s, + tokens: [ + { + type: "text", + raw: n, + text: n + } + ] + }; + } + } + url(e) { + var n; + let t; + if (t = this.rules.inline.url.exec(e)) { + let s, r; + if (t[2] === "@") + s = Se(t[0]), r = "mailto:" + s; + else { + let a; + do + a = t[0], t[0] = ((n = this.rules.inline._backpedal.exec(t[0])) == null ? void 0 : n[0]) ?? ""; + while (a !== t[0]); + s = Se(t[0]), t[1] === "www." ? r = "http://" + t[0] : r = t[0]; + } + return { + type: "link", + raw: t[0], + text: s, + href: r, + tokens: [ + { + type: "text", + raw: s, + text: s + } + ] + }; + } + } + inlineText(e) { + const t = this.rules.inline.text.exec(e); + if (t) { + let n; + return this.lexer.state.inRawBlock ? n = t[0] : n = Se(t[0]), { + type: "text", + raw: t[0], + text: n + }; + } + } +} +const of = /^(?: *(?:\n|$))+/, lf = /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, uf = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/, vn = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/, hf = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, bl = /(?:[*+-]|\d{1,9}[.)])/, xl = K(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g, bl).replace(/blockCode/g, / {4}/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).getRegex(), Ps = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/, cf = /^[^\n]+/, Is = /(?!\s*\])(?:\\.|[^\[\]\\])+/, df = K(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label", Is).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(), ff = K(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, bl).getRegex(), ci = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul", Rs = /|$))/, _f = K("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))", "i").replace("comment", Rs).replace("tag", ci).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(), vl = K(Ps).replace("hr", vn).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", ci).getRegex(), pf = K(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", vl).getRegex(), Bs = { + blockquote: pf, + code: lf, + def: df, + fences: uf, + heading: hf, + hr: vn, + html: _f, + lheading: xl, + list: ff, + newline: of, + paragraph: vl, + table: hn, + text: cf +}, ia = K("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", vn).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", ci).getRegex(), mf = { + ...Bs, + table: ia, + paragraph: K(Ps).replace("hr", vn).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", ia).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", ci).getRegex() +}, gf = { + ...Bs, + html: K(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", Rs).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: hn, + // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: K(Ps).replace("hr", vn).replace("heading", ` *#{1,6} *[^ +]`).replace("lheading", xl).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() +}, wl = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, yf = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, Cl = /^( {2,}|\\)\n(?!\s*$)/, bf = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g, wf = K(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/, "u").replace(/punct/g, wn).getRegex(), Cf = K("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])", "gu").replace(/punct/g, wn).getRegex(), Af = K("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])", "gu").replace(/punct/g, wn).getRegex(), kf = K(/\\([punct])/, "gu").replace(/punct/g, wn).getRegex(), Df = K(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(), Sf = K(Rs).replace("(?:-->|$)", "-->").getRegex(), Ef = K("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment", Sf).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(), ni = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/, Ff = K(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label", ni).replace("href", /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(), Al = K(/^!?\[(label)\]\[(ref)\]/).replace("label", ni).replace("ref", Is).getRegex(), kl = K(/^!?\[(ref)\](?:\[\])?/).replace("ref", Is).getRegex(), $f = K("reflink|nolink(?!\\()", "g").replace("reflink", Al).replace("nolink", kl).getRegex(), Ls = { + _backpedal: hn, + // only used for GFM url + anyPunctuation: kf, + autolink: Df, + blockSkip: vf, + br: Cl, + code: yf, + del: hn, + emStrongLDelim: wf, + emStrongRDelimAst: Cf, + emStrongRDelimUnd: Af, + escape: wl, + link: Ff, + nolink: kl, + punctuation: xf, + reflink: Al, + reflinkSearch: $f, + tag: Ef, + text: bf, + url: hn +}, Tf = { + ...Ls, + link: K(/^!?\[(label)\]\((.*?)\)/).replace("label", ni).getRegex(), + reflink: K(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", ni).getRegex() +}, us = { + ...Ls, + escape: K(wl).replace("])", "~|])").getRegex(), + url: K(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, "i").replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ l + " ".repeat(u.length)); + let n, s, r, a; + for (; e; ) + if (!(this.options.extensions && this.options.extensions.block && this.options.extensions.block.some((o) => (n = o.call({ lexer: this }, e, t)) ? (e = e.substring(n.raw.length), t.push(n), !0) : !1))) { + if (n = this.tokenizer.space(e)) { + e = e.substring(n.raw.length), n.raw.length === 1 && t.length > 0 ? t[t.length - 1].raw += ` +` : t.push(n); + continue; + } + if (n = this.tokenizer.code(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && (s.type === "paragraph" || s.type === "text") ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n); + continue; + } + if (n = this.tokenizer.fences(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.heading(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.hr(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.blockquote(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.list(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.html(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.def(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && (s.type === "paragraph" || s.type === "text") ? (s.raw += ` +` + n.raw, s.text += ` +` + n.raw, this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : this.tokens.links[n.tag] || (this.tokens.links[n.tag] = { + href: n.href, + title: n.title + }); + continue; + } + if (n = this.tokenizer.table(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.lheading(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (r = e, this.options.extensions && this.options.extensions.startBlock) { + let o = 1 / 0; + const l = e.slice(1); + let u; + this.options.extensions.startBlock.forEach((h) => { + u = h.call({ lexer: this }, l), typeof u == "number" && u >= 0 && (o = Math.min(o, u)); + }), o < 1 / 0 && o >= 0 && (r = e.substring(0, o + 1)); + } + if (this.state.top && (n = this.tokenizer.paragraph(r))) { + s = t[t.length - 1], a && s.type === "paragraph" ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue.pop(), this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n), a = r.length !== e.length, e = e.substring(n.raw.length); + continue; + } + if (n = this.tokenizer.text(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && s.type === "text" ? (s.raw += ` +` + n.raw, s.text += ` +` + n.text, this.inlineQueue.pop(), this.inlineQueue[this.inlineQueue.length - 1].src = s.text) : t.push(n); + continue; + } + if (e) { + const o = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(o); + break; + } else + throw new Error(o); + } + } + return this.state.top = !0, t; + } + inline(e, t = []) { + return this.inlineQueue.push({ src: e, tokens: t }), t; + } + /** + * Lexing/Compiling + */ + inlineTokens(e, t = []) { + let n, s, r, a = e, o, l, u; + if (this.tokens.links) { + const h = Object.keys(this.tokens.links); + if (h.length > 0) + for (; (o = this.tokenizer.rules.inline.reflinkSearch.exec(a)) != null; ) + h.includes(o[0].slice(o[0].lastIndexOf("[") + 1, -1)) && (a = a.slice(0, o.index) + "[" + "a".repeat(o[0].length - 2) + "]" + a.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex)); + } + for (; (o = this.tokenizer.rules.inline.blockSkip.exec(a)) != null; ) + a = a.slice(0, o.index) + "[" + "a".repeat(o[0].length - 2) + "]" + a.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + for (; (o = this.tokenizer.rules.inline.anyPunctuation.exec(a)) != null; ) + a = a.slice(0, o.index) + "++" + a.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + for (; e; ) + if (l || (u = ""), l = !1, !(this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some((h) => (n = h.call({ lexer: this }, e, t)) ? (e = e.substring(n.raw.length), t.push(n), !0) : !1))) { + if (n = this.tokenizer.escape(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.tag(e)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && n.type === "text" && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (n = this.tokenizer.link(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.reflink(e, this.tokens.links)) { + e = e.substring(n.raw.length), s = t[t.length - 1], s && n.type === "text" && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (n = this.tokenizer.emStrong(e, a, u)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.codespan(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.br(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.del(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (n = this.tokenizer.autolink(e)) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (!this.state.inLink && (n = this.tokenizer.url(e))) { + e = e.substring(n.raw.length), t.push(n); + continue; + } + if (r = e, this.options.extensions && this.options.extensions.startInline) { + let h = 1 / 0; + const c = e.slice(1); + let f; + this.options.extensions.startInline.forEach((d) => { + f = d.call({ lexer: this }, c), typeof f == "number" && f >= 0 && (h = Math.min(h, f)); + }), h < 1 / 0 && h >= 0 && (r = e.substring(0, h + 1)); + } + if (n = this.tokenizer.inlineText(r)) { + e = e.substring(n.raw.length), n.raw.slice(-1) !== "_" && (u = n.raw.slice(-1)), l = !0, s = t[t.length - 1], s && s.type === "text" ? (s.raw += n.raw, s.text += n.text) : t.push(n); + continue; + } + if (e) { + const h = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(h); + break; + } else + throw new Error(h); + } + } + return t; + } +} +class ii { + constructor(e) { + ee(this, "options"); + this.options = e || St; + } + code(e, t, n) { + var r; + const s = (r = (t || "").match(/^\S*/)) == null ? void 0 : r[0]; + return e = e.replace(/\n$/, "") + ` +`, s ? '
' + (n ? e : Se(e, !0)) + `
+` : "
" + (n ? e : Se(e, !0)) + `
+`; + } + blockquote(e) { + return `
+${e}
+`; + } + html(e, t) { + return e; + } + heading(e, t, n) { + return `${e} +`; + } + hr() { + return `
+`; + } + list(e, t, n) { + const s = t ? "ol" : "ul", r = t && n !== 1 ? ' start="' + n + '"' : ""; + return "<" + s + r + `> +` + e + " +`; + } + listitem(e, t, n) { + return `
  • ${e}
  • +`; + } + checkbox(e) { + return "'; + } + paragraph(e) { + return `

    ${e}

    +`; + } + table(e, t) { + return t && (t = `${t}`), ` + +` + e + ` +` + t + `
    +`; + } + tablerow(e) { + return ` +${e} +`; + } + tablecell(e, t) { + const n = t.header ? "th" : "td"; + return (t.align ? `<${n} align="${t.align}">` : `<${n}>`) + e + ` +`; + } + /** + * span level renderer + */ + strong(e) { + return `${e}`; + } + em(e) { + return `${e}`; + } + codespan(e) { + return `${e}`; + } + br() { + return "
    "; + } + del(e) { + return `${e}`; + } + link(e, t, n) { + const s = ea(e); + if (s === null) + return n; + e = s; + let r = '
    ", r; + } + image(e, t, n) { + const s = ea(e); + if (s === null) + return n; + e = s; + let r = `${n} 0 && f.tokens[0].type === "paragraph" ? (f.tokens[0].text = m + " " + f.tokens[0].text, f.tokens[0].tokens && f.tokens[0].tokens.length > 0 && f.tokens[0].tokens[0].type === "text" && (f.tokens[0].tokens[0].text = m + " " + f.tokens[0].tokens[0].text)) : f.tokens.unshift({ + type: "text", + text: m + " " + }) : b += m + " "; + } + b += this.parse(f.tokens, u), h += this.renderer.listitem(b, p, !!d); + } + n += this.renderer.list(h, o, l); + continue; + } + case "html": { + const a = r; + n += this.renderer.html(a.text, a.block); + continue; + } + case "paragraph": { + const a = r; + n += this.renderer.paragraph(this.parseInline(a.tokens)); + continue; + } + case "text": { + let a = r, o = a.tokens ? this.parseInline(a.tokens) : a.text; + for (; s + 1 < e.length && e[s + 1].type === "text"; ) + a = e[++s], o += ` +` + (a.tokens ? this.parseInline(a.tokens) : a.text); + n += t ? this.renderer.paragraph(o) : o; + continue; + } + default: { + const a = 'Token with "' + r.type + '" type was not found.'; + if (this.options.silent) + return console.error(a), ""; + throw new Error(a); + } + } + } + return n; + } + /** + * Parse Inline Tokens + */ + parseInline(e, t) { + t = t || this.renderer; + let n = ""; + for (let s = 0; s < e.length; s++) { + const r = e[s]; + if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[r.type]) { + const a = this.options.extensions.renderers[r.type].call({ parser: this }, r); + if (a !== !1 || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) { + n += a || ""; + continue; + } + } + switch (r.type) { + case "escape": { + const a = r; + n += t.text(a.text); + break; + } + case "html": { + const a = r; + n += t.html(a.text); + break; + } + case "link": { + const a = r; + n += t.link(a.href, a.title, this.parseInline(a.tokens, t)); + break; + } + case "image": { + const a = r; + n += t.image(a.href, a.title, a.text); + break; + } + case "strong": { + const a = r; + n += t.strong(this.parseInline(a.tokens, t)); + break; + } + case "em": { + const a = r; + n += t.em(this.parseInline(a.tokens, t)); + break; + } + case "codespan": { + const a = r; + n += t.codespan(a.text); + break; + } + case "br": { + n += t.br(); + break; + } + case "del": { + const a = r; + n += t.del(this.parseInline(a.tokens, t)); + break; + } + case "text": { + const a = r; + n += t.text(a.text); + break; + } + default: { + const a = 'Token with "' + r.type + '" type was not found.'; + if (this.options.silent) + return console.error(a), ""; + throw new Error(a); + } + } + } + return n; + } +} +class cn { + constructor(e) { + ee(this, "options"); + this.options = e || St; + } + /** + * Process markdown before marked + */ + preprocess(e) { + return e; + } + /** + * Process HTML after marked is finished + */ + postprocess(e) { + return e; + } + /** + * Process all tokens before walk tokens + */ + processAllTokens(e) { + return e; + } +} +ee(cn, "passThroughHooks", /* @__PURE__ */ new Set([ + "preprocess", + "postprocess", + "processAllTokens" +])); +var kt, hs, Dl; +class Pf { + constructor(...e) { + Hs(this, kt); + ee(this, "defaults", Ms()); + ee(this, "options", this.setOptions); + ee(this, "parse", Cn(this, kt, hs).call(this, at.lex, ot.parse)); + ee(this, "parseInline", Cn(this, kt, hs).call(this, at.lexInline, ot.parseInline)); + ee(this, "Parser", ot); + ee(this, "Renderer", ii); + ee(this, "TextRenderer", Ns); + ee(this, "Lexer", at); + ee(this, "Tokenizer", ti); + ee(this, "Hooks", cn); + this.use(...e); + } + /** + * Run callback for every token + */ + walkTokens(e, t) { + var s, r; + let n = []; + for (const a of e) + switch (n = n.concat(t.call(this, a)), a.type) { + case "table": { + const o = a; + for (const l of o.header) + n = n.concat(this.walkTokens(l.tokens, t)); + for (const l of o.rows) + for (const u of l) + n = n.concat(this.walkTokens(u.tokens, t)); + break; + } + case "list": { + const o = a; + n = n.concat(this.walkTokens(o.items, t)); + break; + } + default: { + const o = a; + (r = (s = this.defaults.extensions) == null ? void 0 : s.childTokens) != null && r[o.type] ? this.defaults.extensions.childTokens[o.type].forEach((l) => { + const u = o[l].flat(1 / 0); + n = n.concat(this.walkTokens(u, t)); + }) : o.tokens && (n = n.concat(this.walkTokens(o.tokens, t))); + } + } + return n; + } + use(...e) { + const t = this.defaults.extensions || { renderers: {}, childTokens: {} }; + return e.forEach((n) => { + const s = { ...n }; + if (s.async = this.defaults.async || s.async || !1, n.extensions && (n.extensions.forEach((r) => { + if (!r.name) + throw new Error("extension name required"); + if ("renderer" in r) { + const a = t.renderers[r.name]; + a ? t.renderers[r.name] = function(...o) { + let l = r.renderer.apply(this, o); + return l === !1 && (l = a.apply(this, o)), l; + } : t.renderers[r.name] = r.renderer; + } + if ("tokenizer" in r) { + if (!r.level || r.level !== "block" && r.level !== "inline") + throw new Error("extension level must be 'block' or 'inline'"); + const a = t[r.level]; + a ? a.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start])); + } + "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens); + }), s.extensions = t), n.renderer) { + const r = this.defaults.renderer || new ii(this.defaults); + for (const a in n.renderer) { + if (!(a in r)) + throw new Error(`renderer '${a}' does not exist`); + if (a === "options") + continue; + const o = a, l = n.renderer[o], u = r[o]; + r[o] = (...h) => { + let c = l.apply(r, h); + return c === !1 && (c = u.apply(r, h)), c || ""; + }; + } + s.renderer = r; + } + if (n.tokenizer) { + const r = this.defaults.tokenizer || new ti(this.defaults); + for (const a in n.tokenizer) { + if (!(a in r)) + throw new Error(`tokenizer '${a}' does not exist`); + if (["options", "rules", "lexer"].includes(a)) + continue; + const o = a, l = n.tokenizer[o], u = r[o]; + r[o] = (...h) => { + let c = l.apply(r, h); + return c === !1 && (c = u.apply(r, h)), c; + }; + } + s.tokenizer = r; + } + if (n.hooks) { + const r = this.defaults.hooks || new cn(); + for (const a in n.hooks) { + if (!(a in r)) + throw new Error(`hook '${a}' does not exist`); + if (a === "options") + continue; + const o = a, l = n.hooks[o], u = r[o]; + cn.passThroughHooks.has(a) ? r[o] = (h) => { + if (this.defaults.async) + return Promise.resolve(l.call(r, h)).then((f) => u.call(r, f)); + const c = l.call(r, h); + return u.call(r, c); + } : r[o] = (...h) => { + let c = l.apply(r, h); + return c === !1 && (c = u.apply(r, h)), c; + }; + } + s.hooks = r; + } + if (n.walkTokens) { + const r = this.defaults.walkTokens, a = n.walkTokens; + s.walkTokens = function(o) { + let l = []; + return l.push(a.call(this, o)), r && (l = l.concat(r.call(this, o))), l; + }; + } + this.defaults = { ...this.defaults, ...s }; + }), this; + } + setOptions(e) { + return this.defaults = { ...this.defaults, ...e }, this; + } + lexer(e, t) { + return at.lex(e, t ?? this.defaults); + } + parser(e, t) { + return ot.parse(e, t ?? this.defaults); + } +} +kt = new WeakSet(), hs = function(e, t) { + return (n, s) => { + const r = { ...s }, a = { ...this.defaults, ...r }; + this.defaults.async === !0 && r.async === !1 && (a.silent || console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."), a.async = !0); + const o = Cn(this, kt, Dl).call(this, !!a.silent, !!a.async); + if (typeof n > "u" || n === null) + return o(new Error("marked(): input parameter is undefined or null")); + if (typeof n != "string") + return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected")); + if (a.hooks && (a.hooks.options = a), a.async) + return Promise.resolve(a.hooks ? a.hooks.preprocess(n) : n).then((l) => e(l, a)).then((l) => a.hooks ? a.hooks.processAllTokens(l) : l).then((l) => a.walkTokens ? Promise.all(this.walkTokens(l, a.walkTokens)).then(() => l) : l).then((l) => t(l, a)).then((l) => a.hooks ? a.hooks.postprocess(l) : l).catch(o); + try { + a.hooks && (n = a.hooks.preprocess(n)); + let l = e(n, a); + a.hooks && (l = a.hooks.processAllTokens(l)), a.walkTokens && this.walkTokens(l, a.walkTokens); + let u = t(l, a); + return a.hooks && (u = a.hooks.postprocess(u)), u; + } catch (l) { + return o(l); + } + }; +}, Dl = function(e, t) { + return (n) => { + if (n.message += ` +Please report this to https://github.com/markedjs/marked.`, e) { + const s = "

    An error occurred:

    " + Se(n.message + "", !0) + "
    "; + return t ? Promise.resolve(s) : s; + } + if (t) + return Promise.reject(n); + throw n; + }; +}; +const At = new Pf(); +function Z(i, e) { + return At.parse(i, e); +} +Z.options = Z.setOptions = function(i) { + return At.setOptions(i), Z.defaults = At.defaults, ml(Z.defaults), Z; +}; +Z.getDefaults = Ms; +Z.defaults = St; +Z.use = function(...i) { + return At.use(...i), Z.defaults = At.defaults, ml(Z.defaults), Z; +}; +Z.walkTokens = function(i, e) { + return At.walkTokens(i, e); +}; +Z.parseInline = At.parseInline; +Z.Parser = ot; +Z.parser = ot.parse; +Z.Renderer = ii; +Z.TextRenderer = Ns; +Z.Lexer = at; +Z.lexer = at.lex; +Z.Tokenizer = ti; +Z.Hooks = cn; +Z.parse = Z; +Z.options; +Z.setOptions; +Z.use; +Z.walkTokens; +Z.parseInline; +ot.parse; +at.lex; +const If = /[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g, Rf = Object.hasOwnProperty; +class Sl { + /** + * Create a new slug class. + */ + constructor() { + this.occurrences, this.reset(); + } + /** + * Generate a unique slug. + * + * Tracks previously generated slugs: repeated calls with the same value + * will result in different slugs. + * Use the `slug` function to get same slugs. + * + * @param {string} value + * String of text to slugify + * @param {boolean} [maintainCase=false] + * Keep the current case, otherwise make all lowercase + * @return {string} + * A unique slug string + */ + slug(e, t) { + const n = this; + let s = Bf(e, t === !0); + const r = s; + for (; Rf.call(n.occurrences, s); ) + n.occurrences[r]++, s = r + "-" + n.occurrences[r]; + return n.occurrences[s] = 0, s; + } + /** + * Reset - Forget all previous slugs + * + * @return void + */ + reset() { + this.occurrences = /* @__PURE__ */ Object.create(null); + } +} +function Bf(i, e) { + return typeof i != "string" ? "" : (e || (i = i.toLowerCase()), i.replace(If, "").replace(/ /g, "-")); +} +new Sl(); +var Lf = { exports: {} }; +(function(i) { + var e = typeof window < "u" ? window : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? self : {}; + /** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */ + var t = function(n) { + var s = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i, r = 0, a = {}, o = { + /** + * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the + * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load + * additional languages or plugins yourself. + * + * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. + * + * You obviously have to change this value before the automatic highlighting started. To do this, you can add an + * empty Prism object into the global scope before loading the Prism script like this: + * + * ```js + * window.Prism = window.Prism || {}; + * Prism.manual = true; + * // add a new