evotars
Version:
Show animated characters on stream
14,290 lines • 517 kB
JavaScript
var bn = Object.defineProperty;
var wn = (i, t, e) => t in i ? bn(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
var w = (i, t, e) => (wn(i, typeof t != "symbol" ? t + "" : t, e), e);
var B = /* @__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))(B || {});
const Pi = (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;
}, Ue = (i, t) => Pi(i).priority ?? t, dt = {
/** @ignore */
_addHandlers: {},
/** @ignore */
_removeHandlers: {},
/** @ignore */
_queue: {},
/**
* Remove extensions from PixiJS.
* @param extensions - Extensions to be removed.
* @returns {extensions} For chaining.
*/
remove(...i) {
return i.map(Pi).forEach((t) => {
t.type.forEach((e) => {
var s, r;
return (r = (s = this._removeHandlers)[e]) == null ? void 0 : r.call(s, t);
});
}), this;
},
/**
* Register new extensions with PixiJS.
* @param extensions - The spread of extensions to add to PixiJS.
* @returns {extensions} For chaining.
*/
add(...i) {
return i.map(Pi).forEach((t) => {
t.type.forEach((e) => {
var n, a;
const s = this._addHandlers, r = this._queue;
s[e] ? (a = s[e]) == null || a.call(s, t) : (r[e] = r[e] || [], (n = r[e]) == null || n.push(t));
});
}), 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 {extensions} For chaining.
*/
handle(i, t, e) {
var a;
const s = this._addHandlers, r = this._removeHandlers;
if (s[i] || r[i])
throw new Error(`Extension type ${i} already has a handler`);
s[i] = t, r[i] = e;
const n = this._queue;
return n[i] && ((a = n[i]) == null || a.forEach((o) => t(o)), delete n[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 {extensions} For chaining.
*/
handleByMap(i, t) {
return this.handle(
i,
(e) => {
e.name && (t[e.name] = e.ref);
},
(e) => {
e.name && delete t[e.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 {extensions} For chaining.
*/
handleByNamedList(i, t, e = -1) {
return this.handle(
i,
(s) => {
t.findIndex((n) => n.name === s.name) >= 0 || (t.push({ name: s.name, value: s.ref }), t.sort((n, a) => Ue(a.value, e) - Ue(n.value, e)));
},
(s) => {
const r = t.findIndex((n) => n.name === s.name);
r !== -1 && t.splice(r, 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 {extensions} For chaining.
*/
handleByList(i, t, e = -1) {
return this.handle(
i,
(s) => {
t.includes(s.ref) || (t.push(s.ref), t.sort((r, n) => Ue(n, e) - Ue(r, e)));
},
(s) => {
const r = t.indexOf(s.ref);
r !== -1 && t.splice(r, 1);
}
);
}
}, vn = {
extension: {
type: B.Environment,
name: "browser",
priority: -1
},
test: () => !0,
load: async () => {
await import("./browserAll-Djz7wsJX.js");
}
}, An = {
extension: {
type: B.Environment,
name: "webworker",
priority: 0
},
test: () => typeof self < "u" && self.WorkerGlobalScope !== void 0,
load: async () => {
await import("./webworkerAll-Bj2vcYLu.js");
}
};
class nt {
/**
* 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(t, e, s) {
this._x = e || 0, this._y = s || 0, this._observer = t;
}
/**
* Creates a clone of this point.
* @param observer - Optional observer to pass to the new observable point.
* @returns a copy of this observable point
*/
clone(t) {
return new nt(t ?? 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`.
* @param {number} [x=0] - position of the point on the x axis
* @param {number} [y=x] - position of the point on the y axis
* @returns The observable point instance itself
*/
set(t = 0, e = t) {
return (this._x !== t || this._y !== e) && (this._x = t, this._y = e, this._observer._onUpdate(this)), this;
}
/**
* Copies x and y from the given point (`p`)
* @param p - The point to copy from. Can be any of type that is or extends `PointData`
* @returns The observable point instance itself
*/
copyFrom(t) {
return (this._x !== t.x || this._y !== t.y) && (this._x = t.x, this._y = t.y, this._observer._onUpdate(this)), this;
}
/**
* Copies this point's x and y into that of the given point (`p`)
* @param p - The point to copy to. Can be any of type that is or extends `PointData`
* @returns The point (`p`) with values updated
*/
copyTo(t) {
return t.set(this._x, this._y), t;
}
/**
* Accepts another point (`p`) and returns `true` if the given point is equal to this point
* @param p - The point to check
* @returns Returns `true` if both `x` and `y` are equal
*/
equals(t) {
return t.x === this._x && t.y === this._y;
}
toString() {
return `[pixi.js/math:ObservablePoint x=0 y=0 scope=${this._observer}]`;
}
/** Position of the observable point on the x axis. */
get x() {
return this._x;
}
set x(t) {
this._x !== t && (this._x = t, this._observer._onUpdate(this));
}
/** Position of the observable point on the y axis. */
get y() {
return this._y;
}
set y(t) {
this._y !== t && (this._y = t, this._observer._onUpdate(this));
}
}
function Xi(i) {
return i && i.__esModule && Object.prototype.hasOwnProperty.call(i, "default") ? i.default : i;
}
var rr = { exports: {} };
(function(i) {
var t = Object.prototype.hasOwnProperty, e = "~";
function s() {
}
Object.create && (s.prototype = /* @__PURE__ */ Object.create(null), new s().__proto__ || (e = !1));
function r(h, c, l) {
this.fn = h, this.context = c, this.once = l || !1;
}
function n(h, c, l, u, d) {
if (typeof l != "function")
throw new TypeError("The listener must be a function");
var p = new r(l, u || h, d), f = e ? e + c : c;
return h._events[f] ? h._events[f].fn ? h._events[f] = [h._events[f], p] : h._events[f].push(p) : (h._events[f] = p, h._eventsCount++), h;
}
function a(h, c) {
--h._eventsCount === 0 ? h._events = new s() : delete h._events[c];
}
function o() {
this._events = new s(), this._eventsCount = 0;
}
o.prototype.eventNames = function() {
var c = [], l, u;
if (this._eventsCount === 0)
return c;
for (u in l = this._events)
t.call(l, u) && c.push(e ? u.slice(1) : u);
return Object.getOwnPropertySymbols ? c.concat(Object.getOwnPropertySymbols(l)) : c;
}, o.prototype.listeners = function(c) {
var l = e ? e + c : c, u = this._events[l];
if (!u)
return [];
if (u.fn)
return [u.fn];
for (var d = 0, p = u.length, f = new Array(p); d < p; d++)
f[d] = u[d].fn;
return f;
}, o.prototype.listenerCount = function(c) {
var l = e ? e + c : c, u = this._events[l];
return u ? u.fn ? 1 : u.length : 0;
}, o.prototype.emit = function(c, l, u, d, p, f) {
var g = e ? e + c : c;
if (!this._events[g])
return !1;
var m = this._events[g], y = arguments.length, _, x;
if (m.fn) {
switch (m.once && this.removeListener(c, m.fn, void 0, !0), y) {
case 1:
return m.fn.call(m.context), !0;
case 2:
return m.fn.call(m.context, l), !0;
case 3:
return m.fn.call(m.context, l, u), !0;
case 4:
return m.fn.call(m.context, l, u, d), !0;
case 5:
return m.fn.call(m.context, l, u, d, p), !0;
case 6:
return m.fn.call(m.context, l, u, d, p, f), !0;
}
for (x = 1, _ = new Array(y - 1); x < y; x++)
_[x - 1] = arguments[x];
m.fn.apply(m.context, _);
} else {
var b = m.length, S;
for (x = 0; x < b; x++)
switch (m[x].once && this.removeListener(c, m[x].fn, void 0, !0), y) {
case 1:
m[x].fn.call(m[x].context);
break;
case 2:
m[x].fn.call(m[x].context, l);
break;
case 3:
m[x].fn.call(m[x].context, l, u);
break;
case 4:
m[x].fn.call(m[x].context, l, u, d);
break;
default:
if (!_)
for (S = 1, _ = new Array(y - 1); S < y; S++)
_[S - 1] = arguments[S];
m[x].fn.apply(m[x].context, _);
}
}
return !0;
}, o.prototype.on = function(c, l, u) {
return n(this, c, l, u, !1);
}, o.prototype.once = function(c, l, u) {
return n(this, c, l, u, !0);
}, o.prototype.removeListener = function(c, l, u, d) {
var p = e ? e + c : c;
if (!this._events[p])
return this;
if (!l)
return a(this, p), this;
var f = this._events[p];
if (f.fn)
f.fn === l && (!d || f.once) && (!u || f.context === u) && a(this, p);
else {
for (var g = 0, m = [], y = f.length; g < y; g++)
(f[g].fn !== l || d && !f[g].once || u && f[g].context !== u) && m.push(f[g]);
m.length ? this._events[p] = m.length === 1 ? m[0] : m : a(this, p);
}
return this;
}, o.prototype.removeAllListeners = function(c) {
var l;
return c ? (l = e ? e + c : c, this._events[l] && a(this, l)) : (this._events = new s(), this._eventsCount = 0), this;
}, o.prototype.off = o.prototype.removeListener, o.prototype.addListener = o.prototype.on, o.prefixed = e, o.EventEmitter = o, i.exports = o;
})(rr);
var Sn = rr.exports;
const Bt = /* @__PURE__ */ Xi(Sn), Cn = Math.PI * 2, Mn = 180 / Math.PI, Tn = Math.PI / 180;
class st {
/**
* 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(t = 0, e = 0) {
this.x = 0, this.y = 0, this.x = t, this.y = e;
}
/**
* Creates a clone of this point
* @returns A clone of this point
*/
clone() {
return new st(this.x, this.y);
}
/**
* Copies `x` and `y` from the given point into this point
* @param p - The point to copy from
* @returns The point instance itself
*/
copyFrom(t) {
return this.set(t.x, t.y), this;
}
/**
* Copies this point's x and y into the given point (`p`).
* @param p - The point to copy to. Can be any of type that is or extends `PointData`
* @returns The point (`p`) with values updated
*/
copyTo(t) {
return t.set(this.x, this.y), t;
}
/**
* Accepts another point (`p`) and returns `true` if the given point is equal to this point
* @param p - The point to check
* @returns Returns `true` if both `x` and `y` are equal
*/
equals(t) {
return t.x === this.x && t.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`.
* @param {number} [x=0] - position of the point on the `x` axis
* @param {number} [y=x] - position of the point on the `y` axis
* @returns The point instance itself
*/
set(t = 0, e = t) {
return this.x = t, this.y = e, this;
}
toString() {
return `[pixi.js/math:Point x=${this.x} y=${this.y}]`;
}
/**
* A static Point object with `x` and `y` values of `0`. Can be used to avoid creating new objects multiple times.
* @readonly
*/
static get shared() {
return li.x = 0, li.y = 0, li;
}
}
const li = new st();
class D {
/**
* @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(t = 1, e = 0, s = 0, r = 1, n = 0, a = 0) {
this.array = null, this.a = t, this.b = e, this.c = s, this.d = r, this.tx = n, this.ty = a;
}
/**
* Creates a Matrix object based on the given array. The Element to Matrix mapping order is as follows:
*
* a = array[0]
* b = array[1]
* c = array[3]
* d = array[4]
* tx = array[2]
* ty = array[5]
* @param array - The array that the matrix will be populated from.
*/
fromArray(t) {
this.a = t[0], this.b = t[1], this.c = t[3], this.d = t[4], this.tx = t[2], this.ty = t[5];
}
/**
* Sets the matrix properties.
* @param a - Matrix component
* @param b - Matrix component
* @param c - Matrix component
* @param d - Matrix component
* @param tx - Matrix component
* @param ty - Matrix component
* @returns This matrix. Good for chaining method calls.
*/
set(t, e, s, r, n, a) {
return this.a = t, this.b = e, this.c = s, this.d = r, this.tx = n, this.ty = a, this;
}
/**
* Creates an array from the current Matrix object.
* @param transpose - Whether we need to transpose the matrix or not
* @param [out=new Float32Array(9)] - If provided the array will be assigned to out
* @returns The newly created array which contains the matrix
*/
toArray(t, e) {
this.array || (this.array = new Float32Array(9));
const s = e || this.array;
return t ? (s[0] = this.a, s[1] = this.b, s[2] = 0, s[3] = this.c, s[4] = this.d, s[5] = 0, s[6] = this.tx, s[7] = this.ty, s[8] = 1) : (s[0] = this.a, s[1] = this.c, s[2] = this.tx, s[3] = this.b, s[4] = this.d, s[5] = this.ty, s[6] = 0, s[7] = 0, s[8] = 1), s;
}
/**
* 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)
* @param pos - The origin
* @param {Point} [newPos] - The point that the new position is assigned to (allowed to be same as input)
* @returns {Point} The new point, transformed through this matrix
*/
apply(t, e) {
e = e || new st();
const s = t.x, r = t.y;
return e.x = this.a * s + this.c * r + this.tx, e.y = this.b * s + this.d * r + this.ty, e;
}
/**
* 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)
* @param pos - The origin
* @param {Point} [newPos] - The point that the new position is assigned to (allowed to be same as input)
* @returns {Point} The new point, inverse-transformed through this matrix
*/
applyInverse(t, e) {
e = e || new st();
const s = this.a, r = this.b, n = this.c, a = this.d, o = this.tx, h = this.ty, c = 1 / (s * a + n * -r), l = t.x, u = t.y;
return e.x = a * c * l + -n * c * u + (h * n - o * a) * c, e.y = s * c * u + -r * c * l + (-h * s + o * r) * c, e;
}
/**
* Translates the matrix on the x and y.
* @param x - How much to translate x by
* @param y - How much to translate y by
* @returns This matrix. Good for chaining method calls.
*/
translate(t, e) {
return this.tx += t, this.ty += e, this;
}
/**
* Applies a scale transformation to the matrix.
* @param x - The amount to scale horizontally
* @param y - The amount to scale vertically
* @returns This matrix. Good for chaining method calls.
*/
scale(t, e) {
return this.a *= t, this.d *= e, this.c *= t, this.b *= e, this.tx *= t, this.ty *= e, this;
}
/**
* Applies a rotation transformation to the matrix.
* @param angle - The angle in radians.
* @returns This matrix. Good for chaining method calls.
*/
rotate(t) {
const e = Math.cos(t), s = Math.sin(t), r = this.a, n = this.c, a = this.tx;
return this.a = r * e - this.b * s, this.b = r * s + this.b * e, this.c = n * e - this.d * s, this.d = n * s + this.d * e, this.tx = a * e - this.ty * s, this.ty = a * s + this.ty * e, this;
}
/**
* Appends the given Matrix to this Matrix.
* @param matrix - The matrix to append.
* @returns This matrix. Good for chaining method calls.
*/
append(t) {
const e = this.a, s = this.b, r = this.c, n = this.d;
return this.a = t.a * e + t.b * r, this.b = t.a * s + t.b * n, this.c = t.c * e + t.d * r, this.d = t.c * s + t.d * n, this.tx = t.tx * e + t.ty * r + this.tx, this.ty = t.tx * s + t.ty * n + this.ty, this;
}
/**
* Appends two matrix's and sets the result to this matrix. AB = A * B
* @param a - The matrix to append.
* @param b - The matrix to append.
* @returns This matrix. Good for chaining method calls.
*/
appendFrom(t, e) {
const s = t.a, r = t.b, n = t.c, a = t.d, o = t.tx, h = t.ty, c = e.a, l = e.b, u = e.c, d = e.d;
return this.a = s * c + r * u, this.b = s * l + r * d, this.c = n * c + a * u, this.d = n * l + a * d, this.tx = o * c + h * u + e.tx, this.ty = o * l + h * d + e.ty, this;
}
/**
* Sets the matrix based on all the available properties
* @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.
*/
setTransform(t, e, s, r, n, a, o, h, c) {
return this.a = Math.cos(o + c) * n, this.b = Math.sin(o + c) * n, this.c = -Math.sin(o - h) * a, this.d = Math.cos(o - h) * a, this.tx = t - (s * this.a + r * this.c), this.ty = e - (s * this.b + r * this.d), this;
}
/**
* Prepends the given Matrix to this Matrix.
* @param matrix - The matrix to prepend
* @returns This matrix. Good for chaining method calls.
*/
prepend(t) {
const e = this.tx;
if (t.a !== 1 || t.b !== 0 || t.c !== 0 || t.d !== 1) {
const s = this.a, r = this.c;
this.a = s * t.a + this.b * t.c, this.b = s * t.b + this.b * t.d, this.c = r * t.a + this.d * t.c, this.d = r * t.b + this.d * t.d;
}
return this.tx = e * t.a + this.ty * t.c + t.tx, this.ty = e * t.b + this.ty * t.d + t.ty, this;
}
/**
* Decomposes the matrix (x, y, scaleX, scaleY, and rotation) and sets the properties on to a transform.
* @param transform - The transform to apply the properties to.
* @returns The transform with the newly applied properties
*/
decompose(t) {
const e = this.a, s = this.b, r = this.c, n = this.d, a = t.pivot, o = -Math.atan2(-r, n), h = Math.atan2(s, e), c = Math.abs(o + h);
return c < 1e-5 || Math.abs(Cn - c) < 1e-5 ? (t.rotation = h, t.skew.x = t.skew.y = 0) : (t.rotation = 0, t.skew.x = o, t.skew.y = h), t.scale.x = Math.sqrt(e * e + s * s), t.scale.y = Math.sqrt(r * r + n * n), t.position.x = this.tx + (a.x * e + a.y * r), t.position.y = this.ty + (a.x * s + a.y * n), t;
}
/**
* Inverts this matrix
* @returns This matrix. Good for chaining method calls.
*/
invert() {
const t = this.a, e = this.b, s = this.c, r = this.d, n = this.tx, a = t * r - e * s;
return this.a = r / a, this.b = -e / a, this.c = -s / a, this.d = t / a, this.tx = (s * this.ty - r * n) / a, this.ty = -(t * this.ty - e * n) / a, this;
}
/** Checks if this matrix is an 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.
* @returns This matrix. Good for chaining method calls.
*/
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 t = new D();
return t.a = this.a, t.b = this.b, t.c = this.c, t.d = this.d, t.tx = this.tx, t.ty = this.ty, t;
}
/**
* Changes the values of the given matrix to be the same as the ones in this matrix
* @param matrix - The matrix to copy to.
* @returns The matrix given in parameter with its values updated.
*/
copyTo(t) {
return t.a = this.a, t.b = this.b, t.c = this.c, t.d = this.d, t.tx = this.tx, t.ty = this.ty, t;
}
/**
* Changes the values of the matrix to be the same as the ones in given matrix
* @param matrix - The matrix to copy from.
* @returns this
*/
copyFrom(t) {
return this.a = t.a, this.b = t.b, this.c = t.c, this.d = t.d, this.tx = t.tx, this.ty = t.ty, this;
}
/**
* check to see if two matrices are the same
* @param matrix - The matrix to compare to.
*/
equals(t) {
return t.a === this.a && t.b === this.b && t.c === this.c && t.d === this.d && t.tx === this.tx && t.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.
*
* This is a shared object, if you want to modify it consider creating a new `Matrix`
* @readonly
*/
static get IDENTITY() {
return kn.identity();
}
/**
* A static Matrix that can be used to avoid creating new objects.
* Will always ensure the matrix is reset to identity when requested.
* Use this object for fast but temporary calculations, as it may be mutated later on.
* This is a different object to the `IDENTITY` object and so can be modified without changing `IDENTITY`.
* @readonly
*/
static get shared() {
return Pn.identity();
}
}
const Pn = new D(), kn = new D(), Yt = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1], Vt = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1], jt = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1], Xt = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1], ki = [], nr = [], Oe = Math.sign;
function In() {
for (let i = 0; i < 16; i++) {
const t = [];
ki.push(t);
for (let e = 0; e < 16; e++) {
const s = Oe(Yt[i] * Yt[e] + jt[i] * Vt[e]), r = Oe(Vt[i] * Yt[e] + Xt[i] * Vt[e]), n = Oe(Yt[i] * jt[e] + jt[i] * Xt[e]), a = Oe(Vt[i] * jt[e] + Xt[i] * Xt[e]);
for (let o = 0; o < 16; o++)
if (Yt[o] === s && Vt[o] === r && jt[o] === n && Xt[o] === a) {
t.push(o);
break;
}
}
}
for (let i = 0; i < 16; i++) {
const t = new D();
t.set(Yt[i], Vt[i], jt[i], Xt[i], 0, 0), nr.push(t);
}
}
In();
const H = {
/**
* | Rotation | Direction |
* |----------|-----------|
* | 0° | East |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
E: 0,
/**
* | Rotation | Direction |
* |----------|-----------|
* | 45°↻ | Southeast |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
SE: 1,
/**
* | Rotation | Direction |
* |----------|-----------|
* | 90°↻ | South |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
S: 2,
/**
* | Rotation | Direction |
* |----------|-----------|
* | 135°↻ | Southwest |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
SW: 3,
/**
* | Rotation | Direction |
* |----------|-----------|
* | 180° | West |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
W: 4,
/**
* | Rotation | Direction |
* |-------------|--------------|
* | -135°/225°↻ | Northwest |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
NW: 5,
/**
* | Rotation | Direction |
* |-------------|--------------|
* | -90°/270°↻ | North |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
N: 6,
/**
* | Rotation | Direction |
* |-------------|--------------|
* | -45°/315°↻ | Northeast |
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
NE: 7,
/**
* Reflection about Y-axis.
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
MIRROR_VERTICAL: 8,
/**
* Reflection about the main diagonal.
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
MAIN_DIAGONAL: 10,
/**
* Reflection about X-axis.
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
MIRROR_HORIZONTAL: 12,
/**
* Reflection about reverse diagonal.
* @memberof maths.groupD8
* @constant {GD8Symmetry}
*/
REVERSE_DIAGONAL: 14,
/**
* @memberof maths.groupD8
* @param {GD8Symmetry} ind - sprite rotation angle.
* @returns {GD8Symmetry} The X-component of the U-axis
* after rotating the axes.
*/
uX: (i) => Yt[i],
/**
* @memberof maths.groupD8
* @param {GD8Symmetry} ind - sprite rotation angle.
* @returns {GD8Symmetry} The Y-component of the U-axis
* after rotating the axes.
*/
uY: (i) => Vt[i],
/**
* @memberof maths.groupD8
* @param {GD8Symmetry} ind - sprite rotation angle.
* @returns {GD8Symmetry} The X-component of the V-axis
* after rotating the axes.
*/
vX: (i) => jt[i],
/**
* @memberof maths.groupD8
* @param {GD8Symmetry} ind - sprite rotation angle.
* @returns {GD8Symmetry} The Y-component of the V-axis
* after rotating the axes.
*/
vY: (i) => Xt[i],
/**
* @memberof maths.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}
* @memberof maths.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, t) => ki[i][t],
/**
* Reverse of `add`.
* @memberof maths.groupD8
* @param {GD8Symmetry} rotationSecond - Second operation
* @param {GD8Symmetry} rotationFirst - First operation
* @returns {GD8Symmetry} Result
*/
sub: (i, t) => ki[i][H.inv(t)],
/**
* Adds 180 degrees to rotation, which is a commutative
* operation.
* @memberof maths.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.
* @memberof maths.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`.
* @memberof maths.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, t) => Math.abs(i) * 2 <= Math.abs(t) ? t >= 0 ? H.S : H.N : Math.abs(t) * 2 <= Math.abs(i) ? i > 0 ? H.E : H.W : t > 0 ? i > 0 ? H.SE : H.SW : i > 0 ? H.NE : H.NW,
/**
* Helps sprite to compensate texture packer rotation.
* @memberof maths.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, t, e = 0, s = 0) => {
const r = nr[H.inv(t)];
r.tx = e, r.ty = s, i.append(r);
}
}, Ge = [new st(), new st(), new st(), new st()];
class tt {
/**
* @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(t = 0, e = 0, s = 0, r = 0) {
this.type = "rectangle", this.x = Number(t), this.y = Number(e), this.width = Number(s), this.height = Number(r);
}
/** Returns the left edge of the rectangle. */
get left() {
return this.x;
}
/** Returns the right edge of the rectangle. */
get right() {
return this.x + this.width;
}
/** Returns the top edge of the rectangle. */
get top() {
return this.y;
}
/** Returns the bottom edge of the rectangle. */
get bottom() {
return this.y + this.height;
}
/** Determines whether the Rectangle is empty. */
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 */
static get EMPTY() {
return new tt(0, 0, 0, 0);
}
/**
* Creates a clone of this Rectangle
* @returns a copy of the rectangle
*/
clone() {
return new tt(this.x, this.y, this.width, this.height);
}
/**
* Converts a Bounds object to a Rectangle object.
* @param bounds - The bounds to copy and convert to a rectangle.
* @returns Returns itself.
*/
copyFromBounds(t) {
return this.x = t.minX, this.y = t.minY, this.width = t.maxX - t.minX, this.height = t.maxY - t.minY, this;
}
/**
* Copies another rectangle to this one.
* @param rectangle - The rectangle to copy from.
* @returns Returns itself.
*/
copyFrom(t) {
return this.x = t.x, this.y = t.y, this.width = t.width, this.height = t.height, this;
}
/**
* Copies this rectangle to another one.
* @param rectangle - The rectangle to copy to.
* @returns Returns given parameter.
*/
copyTo(t) {
return t.copyFrom(this), t;
}
/**
* Checks whether the x and y coordinates given are contained within this Rectangle
* @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
*/
contains(t, e) {
return this.width <= 0 || this.height <= 0 ? !1 : t >= this.x && t < this.x + this.width && e >= this.y && e < this.y + this.height;
}
/**
* Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
* @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
* @returns Whether the x/y coordinates are within this rectangle
*/
strokeContains(t, e, s) {
const { width: r, height: n } = this;
if (r <= 0 || n <= 0)
return !1;
const a = this.x, o = this.y, h = a - s / 2, c = a + r + s / 2, l = o - s / 2, u = o + n + s / 2, d = a + s / 2, p = a + r - s / 2, f = o + s / 2, g = o + n - s / 2;
return t >= h && t <= c && e >= l && e <= u && !(t > d && t < p && e > f && e < 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`.
*/
intersects(t, e) {
if (!e) {
const C = this.x < t.x ? t.x : this.x;
if ((this.right > t.right ? t.right : this.right) <= C)
return !1;
const A = this.y < t.y ? t.y : this.y;
return (this.bottom > t.bottom ? t.bottom : this.bottom) > A;
}
const s = this.left, r = this.right, n = this.top, a = this.bottom;
if (r <= s || a <= n)
return !1;
const o = Ge[0].set(t.left, t.top), h = Ge[1].set(t.left, t.bottom), c = Ge[2].set(t.right, t.top), l = Ge[3].set(t.right, t.bottom);
if (c.x <= o.x || h.y <= o.y)
return !1;
const u = Math.sign(e.a * e.d - e.b * e.c);
if (u === 0 || (e.apply(o, o), e.apply(h, h), e.apply(c, c), e.apply(l, l), Math.max(o.x, h.x, c.x, l.x) <= s || Math.min(o.x, h.x, c.x, l.x) >= r || Math.max(o.y, h.y, c.y, l.y) <= n || Math.min(o.y, h.y, c.y, l.y) >= a))
return !1;
const d = u * (h.y - o.y), p = u * (o.x - h.x), f = d * s + p * n, g = d * r + p * n, m = d * s + p * a, y = d * r + p * a;
if (Math.max(f, g, m, y) <= d * o.x + p * o.y || Math.min(f, g, m, y) >= d * l.x + p * l.y)
return !1;
const _ = u * (o.y - c.y), x = u * (c.x - o.x), b = _ * s + x * n, S = _ * r + x * n, k = _ * s + x * a, M = _ * r + x * a;
return !(Math.max(b, S, k, M) <= _ * o.x + x * o.y || Math.min(b, S, k, M) >= _ * l.x + x * l.y);
}
/**
* Pads the rectangle making it grow in all directions.
* If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
* @param paddingX - The horizontal padding amount.
* @param paddingY - The vertical padding amount.
* @returns Returns itself.
*/
pad(t = 0, e = t) {
return this.x -= t, this.y -= e, this.width += t * 2, this.height += e * 2, this;
}
/**
* Fits this rectangle around the passed one.
* @param rectangle - The rectangle to fit.
* @returns Returns itself.
*/
fit(t) {
const e = Math.max(this.x, t.x), s = Math.min(this.x + this.width, t.x + t.width), r = Math.max(this.y, t.y), n = Math.min(this.y + this.height, t.y + t.height);
return this.x = e, this.width = Math.max(s - e, 0), this.y = r, this.height = Math.max(n - r, 0), this;
}
/**
* Enlarges rectangle that way its corners lie on grid
* @param resolution - resolution
* @param eps - precision
* @returns Returns itself.
*/
ceil(t = 1, e = 1e-3) {
const s = Math.ceil((this.x + this.width - e) * t) / t, r = Math.ceil((this.y + this.height - e) * t) / t;
return this.x = Math.floor((this.x + e) * t) / t, this.y = Math.floor((this.y + e) * t) / t, this.width = s - this.x, this.height = r - this.y, this;
}
/**
* Enlarges this rectangle to include the passed rectangle.
* @param rectangle - The rectangle to include.
* @returns Returns itself.
*/
enlarge(t) {
const e = Math.min(this.x, t.x), s = Math.max(this.x + this.width, t.x + t.width), r = Math.min(this.y, t.y), n = Math.max(this.y + this.height, t.y + t.height);
return this.x = e, this.width = s - e, this.y = r, this.height = n - r, this;
}
/**
* Returns the framing rectangle of the rectangle as a Rectangle object
* @param out - optional rectangle to store the result
* @returns The framing rectangle
*/
getBounds(t) {
return t = t || new tt(), t.copyFrom(this), t;
}
toString() {
return `[pixi.js/math:Rectangle x=${this.x} y=${this.y} width=${this.width} height=${this.height}]`;
}
}
const ci = {
default: -1
};
function et(i = "default") {
return ci[i] === void 0 && (ci[i] = -1), ++ci[i];
}
const fs = {}, $ = "8.0.0";
function q(i, t, e = 3) {
if (fs[t])
return;
let s = new Error().stack;
typeof s > "u" ? console.warn("PixiJS Deprecation Warning: ", `${t}
Deprecated since v${i}`) : (s = s.split(`
`).splice(e).join(`
`), console.groupCollapsed ? (console.groupCollapsed(
"%cPixiJS Deprecation Warning: %c%s",
"color:#614108;background:#fffbe6",
"font-weight:normal;color:#614108;background:#fffbe6",
`${t}
Deprecated since v${i}`
), console.warn(s), console.groupEnd()) : (console.warn("PixiJS Deprecation Warning: ", `${t}
Deprecated since v${i}`), console.warn(s))), fs[t] = !0;
}
const ar = () => {
};
function uc(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 ps(i) {
return !(i & i - 1) && !!i;
}
function En(i) {
const t = {};
for (const e in i)
i[e] !== void 0 && (t[e] = i[e]);
return t;
}
const ms = /* @__PURE__ */ Object.create(null);
function Rn(i) {
const t = ms[i];
return t === void 0 && (ms[i] = et("resource")), t;
}
const or = class hr extends Bt {
/**
* @param options - options for the style
*/
constructor(t = {}) {
super(), this._resourceType = "textureSampler", this._touched = 0, this._maxAnisotropy = 1, this.destroyed = !1, t = { ...hr.defaultOptions, ...t }, this.addressMode = t.addressMode, this.addressModeU = t.addressModeU ?? this.addressModeU, this.addressModeV = t.addressModeV ?? this.addressModeV, this.addressModeW = t.addressModeW ?? this.addressModeW, this.scaleMode = t.scaleMode, this.magFilter = t.magFilter ?? this.magFilter, this.minFilter = t.minFilter ?? this.minFilter, this.mipmapFilter = t.mipmapFilter ?? this.mipmapFilter, this.lodMinClamp = t.lodMinClamp, this.lodMaxClamp = t.lodMaxClamp, this.compare = t.compare, this.maxAnisotropy = t.maxAnisotropy ?? 1;
}
set addressMode(t) {
this.addressModeU = t, this.addressModeV = t, this.addressModeW = t;
}
/** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */
get addressMode() {
return this.addressModeU;
}
set wrapMode(t) {
q($, "TextureStyle.wrapMode is now TextureStyle.addressMode"), this.addressMode = t;
}
get wrapMode() {
return this.addressMode;
}
set scaleMode(t) {
this.magFilter = t, this.minFilter = t, this.mipmapFilter = t;
}
/** 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(t) {
this._maxAnisotropy = Math.min(t, 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 t = `${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`;
return this._sharedResourceId = Rn(t), this._resourceId;
}
/** Destroys the style */
destroy() {
this.destroyed = !0, this.emit("destroy", this), this.emit("change", this), this.removeAllListeners();
}
};
or.defaultOptions = {
addressMode: "clamp-to-edge",
scaleMode: "linear"
};
let Bn = or;
const lr = class cr extends Bt {
/**
* @param options - options for creating a new TextureSource
*/
constructor(t = {}) {
super(), this.options = t, this.uid = et("textureSource"), this._resourceType = "textureSource", this._resourceId = et("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, t = { ...cr.defaultOptions, ...t }, this.label = t.label ?? "", this.resource = t.resource, this.autoGarbageCollect = t.autoGarbageCollect, this._resolution = t.resolution, t.width ? this.pixelWidth = t.width * this._resolution : this.pixelWidth = this.resource ? this.resourceWidth ?? 1 : 1, t.height ? this.pixelHeight = t.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 = t.format, this.dimension = t.dimensions, this.mipLevelCount = t.mipLevelCount, this.autoGenerateMipmaps = t.autoGenerateMipmaps, this.sampleCount = t.sampleCount, this.antialias = t.antialias, this.alphaMode = t.alphaMode, this.style = new Bn(En(t)), this.destroyed = !1, this._refreshPOT();
}
/** returns itself */
get source() {
return this;
}
/** the style of the texture */
get style() {
return this._style;
}
set style(t) {
var e, s;
this.style !== t && ((e = this._style) == null || e.off("change", this._onStyleChange, this), this._style = t, (s = this._style) == null || s.on("change", this._onStyleChange, this), this._onStyleChange());
}
/** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */
get addressMode() {
return this._style.addressMode;
}
set addressMode(t) {
this._style.addressMode = t;
}
/** setting this will set wrapModeU,wrapModeV and wrapModeW all at once! */
get repeatMode() {
return this._style.addressMode;
}
set repeatMode(t) {
this._style.addressMode = t;
}
/** Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel. */
get magFilter() {
return this._style.magFilter;
}
set magFilter(t) {
this._style.magFilter = t;
}
/** Specifies the sampling behavior when the sample footprint is larger than one texel. */
get minFilter() {
return this._style.minFilter;
}
set minFilter(t) {
this._style.minFilter = t;
}
/** Specifies behavior for sampling between mipmap levels. */
get mipmapFilter() {
return this._style.mipmapFilter;
}
set mipmapFilter(t) {
this._style.mipmapFilter = t;
}
/** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
get lodMinClamp() {
return this._style.lodMinClamp;
}
set lodMinClamp(t) {
this._style.lodMinClamp = t;
}
/** Specifies the minimum and maximum levels of detail, respectively, used internally when sampling a texture. */
get lodMaxClamp() {
return this._style.lodMaxClamp;
}
set lodMaxClamp(t) {
this._style.lodMaxClamp = t;
}
_onStyleChange() {
this.emit("styleChange", this);
}
/** call this if you have modified the texture outside of the constructor */
update() {
if (this.resource) {
const t = this._resolution;
if (this.resize(this.resourceWidth / t, this.resourceHeight / t))
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 = et("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: t } = this;
return t.naturalWidth || t.videoWidth || t.displayWidth || t.width;
}
/** the height of the resource. This is the REAL pure number, not accounting resolution */
get resourceHeight() {
const { resource: t } = this;
return t.naturalHeight || t.videoHeight || t.displayHeight || t.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(t) {
this._resolution !== t && (this._resolution = t, this.width = this.pixelWidth / t, this.height = this.pixelHeight / t);
}
/**
* 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(t, e, s) {
s = s || this._resolution, t = t || this.width, e = e || this.height;
const r = Math.round(t * s), n = Math.round(e * s);
return this.width = r / s, this.height = n / s, this._resolution = s, this.pixelWidth === r && this.pixelHeight === n ? !1 : (this._refreshPOT(), this.pixelWidth = r, this.pixelHeight = n, this.emit("resize", this), this._resourceId = et("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(t) {
this._style.wrapMode = t;
}
get wrapMode() {
return this._style.wrapMode;
}
set scaleMode(t) {
this._style.scaleMode = t;
}
/** 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 = ps(this.pixelWidth) && ps(this.pixelHeight);
}
static test(t) {
throw new Error("Unimplemented");
}
};
lr.defaultOptions = {
resolution: 1,
format: "bgra8unorm",
alphaMode: "premultiply-alpha-on-upload",
dimensions: "2d",
mipLevelCount: 1,
autoGenerateMipmaps: !1,
sampleCount: 1,
antialias: !1,
autoGarbageCollect: !1
};
let Ot = lr;
class $i extends Ot {
constructor(t) {
const e = t.resource || new Float32Array(t.width * t.height * 4);
let s = t.format;
s || (e instanceof Float32Array ? s = "rgba32float" : e instanceof Int32Array || e instanceof Uint32Array ? s = "rgba32uint" : e instanceof Int16Array || e instanceof Uint16Array ? s = "rgba16uint" : (e instanceof Int8Array, s = "bgra8unorm")), super({
...t,
resource: e,
format: s
}), this.uploadMethodId = "buffer";
}
static test(t) {
return t instanceof Int8Array || t instanceof Uint8Array || t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array;
}
}
$i.extension = B.TextureSource;
const gs = new D();
class Fn {
/**
* @param texture - observed texture
* @param clampMargin - Changes frame clamping, 0.5 by default. Use -0.5 for extra border.
*/
constructor(t, e) {
this.mapCoord = new D(), this.uClampFrame = new Float32Array(4), this.uClampOffset = new Float32Array(2), this._textureID = -1, this._updateID = 0, this.clampOffset = 0, typeof e > "u" ? this.clampMargin = t.width < 10 ? 0 : 0.5 : this.clampMargin = e, this.isSimple = !1, this.texture = t;
}
/** Texture property. */
get texture() {
return this._texture;
}
set texture(t) {
var e;
this.texture !== t && ((e = this._texture) == null || e.removeListener("update", this.update, this), this._texture = t, 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(t, e) {
e === void 0 && (e = t);
const s = this.mapCoord;
for (let r = 0; r < t.length; r += 2) {
const n = t[r], a = t[r + 1];
e[r] = n * s.a + a * s.c + s.tx, e[r + 1] = n * s.b + a * s.d + s.ty;
}
return e;
}
/**
* Updates matrices if texture was changed
* @returns - whether or not it was updated
*/
update() {
const t = this._texture;
this._updateID++;
const e = t.uvs;
this.mapCoord.set(e.x1 - e.x0, e.y1 - e.y0, e.x3 - e.x0, e.y3 - e.y0, e.x0, e.y0);
const s = t.orig, r = t.trim;
r && (gs.set(
s.width / r.width,
0,
0,
s.height / r.height,
-r.x / r.width,
-r.y / r.height
), this.mapCoord.append(gs));
const n = t.source, a = this.uClampFrame, o = this.clampMargin / n._resolution, h = this.clampOffset;
return a[0] = (t.frame.x + o + h) / n.width, a[1] = (t.frame.y + o + h) / n.height, a[2] = (t.frame.x + t.frame.width - o + h) / n.width, a[3] = (t.frame.y + t.frame.height - o + h) / n.height, this.uClampOffset[0] = h / n.pixelWidth, this.uClampOffset[1] = h / n.pixelHeight, this.isSimple = t.frame.width === n.width && t.frame.height === n.height && t.rotate === 0, !0;
}
}
class L extends Bt {
/**
* @param {TextureOptions} param0 - Options for the texture
*/
constructor({
source: t,
label: e,
frame: s,
orig: r,
trim: n,
defaultAnchor: a,
defaultBorders: o,
rotate: h,
dynamic: c
} = {}) {
if (super(), this.uid = et("texture"), this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 }, this.frame = new tt(), this.noFrame = !1, this.dynamic = !1, this.isTexture = !0, this.label = e, this.source = (t == null ? void 0 : t.source) ?? new Ot(), this.noFrame = !s, s)
this.frame.copyFrom(s);
else {
const { width: l, height: u } = this._source;
this.frame.width = l, this.frame.height = u;
}
this.orig = r || this.frame, this.trim = n, this.rotate = h ?? 0, this.defaultAnchor = a, this.defaultBorders = o, this.destroyed = !1, this.dynamic = c || !1, this.updateUvs();
}
set source(t) {
this._source && this._source.off("resize", this.update, this), this._source = t, t.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 Fn(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: t, frame: e } = this, { width: s, height: r } = this._source, n = e.x / s, a = e.y / r, o = e.width / s, h = e.height / r;
let c = this.rotate;
if (c) {
const l = o / 2, u = h / 2, d = n + l, p = a + u;
c = H.add(c, H.NW), t.x0 = d + l * H.uX(c), t.y0 = p + u * H.uY(c), c = H.add(c, 2), t.x1 = d + l * H.uX(c), t.y1 = p + u * H.uY(c), c = H.add(c, 2), t.x2 = d + l * H.uX(c), t.y2 = p + u * H.uY(c), c = H.add(c, 2), t.x3 = d + l * H.uX(c), t.y3 = p + u * H.uY(c);
} else
t.x0 = n, t.y0 = a, t.x1 = n + o, t.y1 = a, t.x2 = n + o, t.y2 = a + h, t.x3 = n, t.y3 = a + h;
}
/**
* Destroys this texture
* @param destroySource - Destroy the source when the texture is destroyed.
*/
destroy(t = !1) {
this._source && t && (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 */
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 q($, "Texture.baseTexture is now Texture.source"), this._source;
}
}
L.EMPTY = new L({
label: "EMPTY",
source: new Ot({
label: "EMPTY"
})
});
L.EMPTY.destroy = ar;
L.WHITE = new L({
source: new $i({
resource: new Uint8Array([255, 255, 255, 255]),
width: 1,
height: 1,
alphaMode: "premultiply-alpha-on-upload",
label: "WHITE"
}),
label: "WHITE"
});
L.WHITE.destroy = ar;
function Ln(i, t, e, s) {
const { width: r, height: n } = e.orig, a = e.trim;
if (a) {
const o = a.width, h = a.height;
i.minX = a.x - t._x * r - s, i.maxX = i.minX + o, i.minY = a.y - t._y * n - s, i.maxY = i.minY + h;
} else
i.minX = -t._x * r - s, i.maxX = i.minX + r, i.minY = -t._y * n - s, i.maxY = i.minY + n;
}
var Dn = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, Tt = function(i) {
return typeof i == "string" ? i.length > 0 : typeof i == "number";
}, Z = function(i, t, e) {
return t === void 0 && (t = 0), e === void 0 && (e = Math.pow(10, t)), Math.round(e * i) / e + 0;
}, ut = function(i, t, e) {
return t === void 0 && (t = 0), e === void 0 && (e = 1), i > e ? e : i > t ? i : t;
}, ur = function(i) {
return (i = isFinite(i) ? i % 360 : 0) > 0 ? i : i + 360;
}, ys = function(i) {
return { r: ut(i.r, 0, 255), g: ut(i.g, 0, 255), b: ut(i.b, 0, 255), a: ut(i.a) };
}, ui = function(i) {
return { r: Z(i.r), g: Z(i.g), b: Z(i.b), a: Z(i.a, 3) };
}, Un = /^#([0-9a-f]{3,8})$/i, ze = function(i) {
var t = i.toString(16);
return t.length < 2 ? "0" + t : t;
}, dr = function(i) {
var t = i.r, e = i.g, s = i.b, r = i.a, n = Math.max(t, e, s), a = n - Math.min(t, e, s), o = a ? n === t ? (e - s) / a : n === e ? 2 + (s - t) / a : 4 + (t - e) / a : 0;
return { h: 60 * (o < 0 ? o + 6 : o), s: n ? a / n * 100 : 0, v: n / 255 * 100, a: r };
}, fr = function(i) {
var t = i.h, e = i.s, s = i.v, r = i.a;
t = t / 360 * 6, e /= 100, s /= 100;
var n = Math.floor(t), a = s * (1 - e), o = s * (1 - (t - n) * e), h = s * (1 - (1 - t + n) * e), c = n % 6;
return { r: 255 * [s, o, a, a, h, s][c], g: 255 * [h, s, s, o, a, a][c], b: 255 * [a, a, h, s, s, o][c], a: r };
}, _s = function(i) {
return { h: ur(i.h), s: ut(i.s, 0, 100), l: ut(i.l, 0, 100), a: ut(i.a) };
}, xs = function(i) {
return { h: Z(i.h), s: Z(i.s), l: Z(i.l), a: Z(i.a, 3) };
}, bs = function(i) {
return fr((e = (t = i).s, { h: t.h, s: (e *= ((s = t.l) < 50 ? s : 100 - s) / 100) > 0 ? 2 * e / (s + e) * 100 : 0, v: s + e, a: t.a }));
var t, e, s;
}, Ae = function(i) {
return { h: (t = dr(i)).h, s: (r = (200 - (e = t.s)) * (s = t.v) / 100) > 0 && r < 200 ? e * s / 100 / (r <= 100 ? r : 200 - r) * 100 : 0, l: r / 2, a: t.a };
var t, e, s, r;
}, On = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Gn = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, zn = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Hn = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Ii = { string: [[function(i) {
var t = Un.exec(i);
return t ? (i = t[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 ? Z(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 ? Z(parseInt(i.substr(6, 2), 16) / 255, 2) : 1 } : null : null;
}, "hex"], [function(i) {
var t = zn.exec(i) || Hn.exec(i);
return t ? t[2] !== t[4] || t[4] !== t[6] ? null : ys({ r: Number(t[1]) / (t[2] ? 100 / 255 : 1), g: Number(t[3]) / (t[4] ? 100 / 255 : 1), b: Number(t[5]) / (t[6] ? 100 / 255 : 1), a: t[7] === void 0 ? 1 : Number(t[7]) / (t[8] ? 100 : 1) }) : null;
}, "rgb"], [function(i) {
var t = On.exec(i) || Gn.exec(i);
if (!t)
return null;
var e, s, r = _s({ h: (e = t[1], s = t[2], s === void 0 && (s = "deg"), Number(e) * (Dn[s] || 1)), s: Number(t[3]), l: Number(t[4]), a: t[5] === void 0 ? 1 : Number(t[5]) / (t[6] ? 100 : 1) });
return bs(r);
}, "hsl"]], object: [[function(i) {
var t = i.r, e = i.g, s = i.b, r = i.a, n = r === void 0 ? 1 : r;
return Tt(t) && Tt(e) && Tt(s) ? ys({ r: Number(t), g: Number(e), b: Number(s), a: Number(n) }) : null;
}, "rgb"], [function(i) {
var t = i.h, e = i.s, s = i.l, r = i.a, n = r === void 0 ? 1 : r;
if (!Tt(t) || !Tt(e) || !Tt(s))
return null;
var a = _s({ h: Number(t), s: Number(e), l: Number(s), a: Number(n) });
return bs(a);
}, "hsl"], [function(i) {
var t = i.h, e = i.s, s = i.v, r = i.a, n = r === void 0 ? 1 : r;
if (!Tt(t) || !Tt(e) || !Tt(s))
return null;
var a = function(o) {
return { h: ur(o.h), s: ut(o.s, 0, 100), v: ut(o.v, 0, 100), a: ut(o.a) };
}({ h: Number(t), s: Number(e), v: Number(s), a: Number(n) });
return fr(a);
}, "hsv"]] }, ws = function(i, t) {
for (var e = 0; e < t.length; e++) {
var s = t[e][0](i);
if (s)
return [s, t[e][1]];
}
return [null, void 0];
}, Wn = function(i) {
return typeof i == "string" ? ws(i.trim(), Ii.string) : typeof i == "object" && i !== null ? ws(i, Ii.object) : [null, void 0];
}, di = function(i, t) {
var e = Ae(i);
return { h: e.h, s: ut(e.s + 100 * t, 0, 100), l: e.l, a: e.a };
}, fi = function(i) {
return (299 * i.r + 587 * i.g + 114 * i.b) / 1e3 / 255;
}, vs = function(i, t) {
var e = Ae(i);
return { h: e.h, s: e.s, l: ut(e.l + 100 * t, 0, 100), a: e.a };
}, Ei = function() {
function i(t) {
this.parsed = Wn(t)[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 Z(fi(this.rgba), 2);
}, i.prototype.isDark = function() {
return fi(this.rgba) < 0.5;
}, i.prototype.isLight = function() {
return fi(this.rgba) >= 0.5;
}, i.prototype.toHex = function() {
return t = ui(this.rgba), e = t.r, s = t.g, r = t.b, a = (n = t.a) < 1 ? ze(Z(255 * n)) : "", "#" + ze(e) + ze(s) + ze(r) + a;
var t, e, s, r, n, a;
}, i.prototype.toRgb = function() {
return ui(this.rgba);
}, i.prototype.toRgbString = function() {
return t = ui(this.rgba), e = t.r, s = t.g, r = t.b, (n = t.a) < 1 ? "rgba(" + e + ", " + s + ", " + r + ", " + n + ")" : "rgb(" + e + ", " + s + ", " + r + ")";
var t, e, s, r, n;
}, i.prototype.toHsl = function() {
return xs(Ae(this.rgba));
}, i.prototype.toHslString = function() {
return t = xs(Ae(this.rgba)), e = t.h, s = t.s, r = t.l, (n = t.a) < 1 ? "hsla(" + e + ", " + s + "%, " + r + "%, " + n + ")" : "hsl(" + e + ", " + s + "%, " + r + "%)";
var t, e, s, r, n;
}, i.prototype.toHsv = function() {
return t = dr(this.rgba), { h: Z(t.h), s: Z(t.s), v: Z(t.v), a: Z(t.a, 3) };
var t;
}, i.prototype.invert = function() {
return vt({ r: 255 - (t = this.rgba).r, g: 255 - t.g, b: 255 - t.b, a: t.a });
var t;
}, i.prototype.saturate = function(t) {
return t === void 0 && (t = 0.1), vt(di(this.rgba, t));
}, i.prototype.desaturate = function(t) {
return t === void 0 && (t = 0.1), vt(di(this.rgba, -t));
}, i.prototype.grayscale = function() {
return vt(di(this.rgba, -1));
}, i.prototype.lighten = function(t) {
return t === void 0 && (t = 0.1), vt(vs(this.rgba, t));
}, i.prototype.darken = function(t) {
return t === void 0 && (t = 0.1), vt(vs(this.rgba, -t));
}, i.prototype.rotate = function(t) {
return t === void 0 && (t = 15), this.hue(this.hue() + t);
}, i.prototype.alpha = function(t) {
return typeof t == "number" ? vt({ r: (e = this.rgba).r, g: e.g, b: e.b, a: t }) : Z(this.rgba.a, 3);
var e;
}, i.prototype.hue = function(t) {
var e = Ae(this.rgba);
return typeof t == "number" ? vt({ h: t, s: e.s, l: e.l, a: e.a }) : Z(e.h);
}, i.prototype.isEqual = function(t) {
return this.toHex() === vt(t).toHex();
}, i;
}(), vt = function(i) {
return i instanceof Ei ? i : new Ei(i);
}, As = [], Nn = function(i) {
i.forEach(function(t) {
As.indexOf(t) < 0 && (t(Ei, Ii), As.push(t));
});
};
function Yn(i, t) {
var e = { 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" }, s = {};
for (var r in e)
s[e[r]] = r;
var n = {};
i.prototype.toName = function(a) {
if (!(this.rgba.a || this.rgba.r || this.rgba.g || this.rgba.b))
return "transparent";
var o, h, c = s[this.toHex()];
if (c)
return c;
if (a != null && a.closest) {
var l = this.toRgb(), u = 1 / 0, d = "black";
if (!n.length)
for (var p in e)
n[p] = new i(e[p]).toRgb();
for (var f in e) {
var g = (o = l, h = n[f], Math.pow(o.r - h.r, 2) + Math.pow(o.g - h.g, 2) + Math.pow(o.b - h.b, 2));
g < u && (u = g, d = f);
}
return d;
}
}, t.string.push([function(a) {
var o = a.toLowerCase(), h = o === "transparent" ? "#0000" : e[o];
return h ? new i(h).toRgb() : null;
}, "name"]);
}
Nn([Yn]);
const re = class _e {
/**
* @param {ColorSource} value - Optional value to use, if not provided, white is used.
*/
constructor(t = 16777215) {
this._value = null, this._components = new Float32Array(4), this._components.fill(1), this._int = 16777215, this.value = t;
}
/** Get red component (0 - 1) */
get red() {
return this._components[0];
}
/** Get green component (0 - 1) */
get green() {
return this._components[1];
}
/** Get blue component (0 - 1) */
get blue() {
return this._components[2];
}
/** Get alpha component (0 - 1) */
get alpha() {
return this._components[3];
}
/**
* Set the value, suitable for chaining
* @param value
* @see Color.value
*/
setValue(t) {
return this.value = t, this;
}
/**
* The current color source.
*
* When setting:
* - Setting to an instance of `Color` will copy its color source and components.
* - Otherwise, `Color` will try to normalize the color source and set the components.
* If the color source is invalid, an `Error` will be thrown and the `Color` will left unchanged.
*
* Note: The `null` in the setter's parameter type is added to match the TypeScript rule: return type of getter
* must be assignable to its setter's parameter type. Setting `value` to `null` will throw an `Error`.
*
* When getting:
* - A return value of `null` means the previous value was overridden (e.g., {@link Color.multiply multiply},
* {@link Color.premultiply premultiply} or {@link Color.round round}).
* - Otherwise, the color source used when setting is returned.
*/
set value(t) {
if (t instanceof _e)
this._value = this._cloneSource(t._value), this._int = t._int, this._components.set(t._components);
else {
if (t === null)
throw new Error("Cannot set Color#value to null");
(this._value === null || !this._isSourceEqual(this._value, t)) && (this._normalize(t), this._value = this._cloneSource(t));
}
}
get value() {
return this._value;
}
/**
* Copy a color source internally.
* @param value - Color source
*/
_cloneSource(t) {
return typeof t == "string" || typeof t == "number" || t instanceof Number || t === null ? t : Array.isArray(t) || ArrayBuffer.isView(t) ? t.slice(0) : typeof t == "object" && t !== null ? { ...t } : t;
}
/**
* 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(t, e) {
const s = typeof t;
if (s !== typeof e)
return !1;
if (s === "number" || s === "string" || t instanceof Number)
return t === e;
if (Array.isArray(t) && Array.isArray(e) || ArrayBuffer.isView(t) && ArrayBuffer.isView(e))
return t.length !== e.length ? !1 : t.every((n, a) => n === e[a]);
if (t !== null && e !== null) {
const n = Object.keys(t), a = Object.keys(e);
return n.length !== a.length ? !1 : n.every((o) => t[o] === e[o]);
}
return t === e;
}
/**
* Convert to a RGBA color object.
* @example
* import { Color } from 'pixi.js';
* new Color('white').toRgb(); // returns { r: 1, g: 1, b: 1, a: 1 }
*/
toRgba() {
const [t, e, s, r] = this._components;
return { r: t, g: e, b: s, a: r };
}
/**
* Convert to a RGB color object.
* @example
* import { Color } from 'pixi.js';
* new Color('white').toRgb(); // returns { r: 1, g: 1, b: 1 }
*/
toRgb() {
const [t, e, s] = this._components;
return { r: t, g: e, b: s };
}
/** Convert to a CSS-style rgba string: `rgba(255,255,255,1.0)`. */
toRgbaString() {
const [t, e, s] = this.toUint8RgbArray();
return `rgba(${t},${e},${s},${this.alpha})`;
}
toUint8RgbArray(t) {
const [e, s, r] = this._components;
return this._arrayRgb || (this._arrayRgb = []), t = t || this._arrayRgb, t[0] = Math.round(e * 255), t[1] = Math.round(s * 255), t[2] = Math.round(r * 255), t;
}
toArray(t) {
this._arrayRgba || (this._arrayRgba = []), t = t || this._arrayRgba;
const [e, s, r, n] = this._components;
return t[0] = e, t[1] = s, t[2] = r, t[3] = n, t;
}
toRgbArray(t) {
this._arrayRgb || (this._arrayRgb = []), t = t || this._arrayRgb;
const [e, s, r] = this._components;
return t[0] = e, t[1] = s, t[2] = r, t;
}
/**
* Convert to a hexadecimal number.
* @example
* import { Color } from 'pixi.js';
* new Color('white').toNumber(); // returns 16777215
*/
toNumber() {
return this._int;
}
/**
* Convert to a BGR number
* @example
* import { Color } from 'pixi.js';
* new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff
*/
toBgrNumber() {
const [t, e, s] = this.toUint8RgbArray();
return (s << 16) + (e << 8) + t;
}
/**
* Convert to a hexadecimal number in little endian format (e.g., BBGGRR).
* @example
* import { Color } from 'pixi.js';
* new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff
* @returns {number} - The color as a number in little endian format.
*/
toLittleEndianNumber() {
const t = this._int;
return (t >> 16) + (t & 65280) + ((t & 255) << 16);
}
/**
* Multiply with another color. This action is destructive, and will
* override the previous `value` property to be `null`.
* @param {ColorSource} value - The color to multiply by.
*/
multiply(t) {
const [e, s, r, n] = _e._temp.setValue(t)._components;
return this._components[0] *= e, this._components[1] *= s, this._components[2] *= r, this._components[3] *= n, this._refreshInt(), this._value = null, this;
}
/**
* Converts color to a premultiplied alpha format. This action is destructive, and will
* override the previous `value` property to be `null`.
* @param alpha - The alpha to multiply by.
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels.
* @returns {Color} - Itself.
*/
premultiply(t, e = !0) {
return e && (this._components[0] *= t, this._components[1] *= t, this._components[2] *= t), this._components[3] = t, this._refreshInt(), this._value = null, this;
}
/**
* Premultiplies alpha with current color.
* @param {number} alpha - The alpha to multiply by.
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels.
* @returns {number} tint multiplied by alpha
*/
toPremultiplied(t, e = !0) {
if (t === 1)
return (255 << 24) + this._int;
if (t === 0)
return e ? 0 : this._int;
let s = this._int >> 16 & 255, r = this._int >> 8 & 255, n = this._int & 255;
return e && (s = s * t + 0.5 | 0, r = r * t + 0.5 | 0, n = n * t + 0.5 | 0), (t * 255 << 24) + (s << 16) + (r << 8) + n;
}
/**
* Convert to a hexidecimal string.
* @example
* import { Color } from 'pixi.js';
* new Color('white').toHex(); // returns "#ffffff"
*/
toHex() {
const t = this._int.toString(16);
return `#${"000000".substring(0, 6 - t.length) + t}`;
}
/**
* Convert to a hexidecimal string with alpha.
* @example
* import { Color } from 'pixi.js';
* new Color('white').toHexa(); // returns "#ffffffff"
*/
toHexa() {
const e = Math.round(this._components[3] * 255).toString(16);
return this.toHex() + "00".substring(0, 2 - e.length) + e;
}
/**
* Set alpha, suitable for chaining.
* @param alpha
*/
setAlpha(t) {
return this._components[3] = this._clamp(t), this;
}
/**
* Normalize the input value into rgba
* @param value - Input value
*/
_normalize(t) {
let e, s, r, n;
if ((typeof t == "number" || t instanceof Number) && t >= 0 && t <= 16777215) {
const a = t;
e = (a >> 16 & 255) / 255, s = (a >> 8 & 255) / 255, r = (a & 255) / 255, n = 1;
} else if ((Array.isArray(t) || t instanceof Float32Array) && t.length >= 3 && t.length <= 4)
t = this._clamp(t), [e, s, r, n = 1] = t;
else if ((t instanceof Uint8Array || t instanceof Uint8ClampedArray) && t.length >= 3 && t.length <= 4)
t = this._clamp(t, 0, 255), [e, s, r, n = 255] = t, e /= 255, s /= 255, r /= 255, n /= 255;
else if (typeof t == "string" || typeof t == "object") {
if (typeof t == "string") {
const o = _e.HEX_PATTERN.exec(t);
o && (t = `#${o[2]}`);
}
const a = vt(t);
a.isValid() && ({ r: e, g: s, b: r, a: n } = a.rgba, e /= 255, s /= 255, r /= 255);
}
if (e !== void 0)
this._components[0] = e, this._components[1] = s, this._components[2] = r, this._components[3] = n, this._refreshInt();
else
throw new Error(`Unable to convert color ${t}`);
}
/** Refresh the internal color rgb number */
_refreshInt() {
this._clamp(this._components);
const [t, e, s] = this._components;
this._int = (t * 255 << 16) + (e * 255 << 8) + (s * 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(t, e = 0, s = 1) {
return typeof t == "number" ? Math.min(Math.max(t, e), s) : (t.forEach((r, n) => {
t[n] = Math.min(Math.max(r, e), s);
}), t);
}
/**
* Check if the value is a color-like object
* @param value - Value to check
* @returns True if the value is a color-like object
* @static
* @example
* import { Color } from 'pixi.js';
* Color.isColorLike('white'); // returns true
* Color.isColorLike(0xffffff); // returns true
* Color.isColorLike([1, 1, 1]); // returns true
*/
static isColorLike(t) {
return typeof t == "number" || typeof t == "string" || t instanceof Number || t instanceof _e || Array.isArray(t) || t instanceof Uint8Array || t instanceof Uint8ClampedArray || t instanceof Float32Array || t.r !== void 0 && t.g !== void 0 && t.b !== void 0 || t.r !== void 0 && t.g !== void 0 && t.b !== void 0 && t.a !== void 0 || t.h !== void 0 && t.s !== void 0 && t.l !== void 0 || t.h !== void 0 && t.s !== void 0 && t.l !== void 0 && t.a !== void 0 || t.h !== void 0 && t.s !== void 0 && t.v !== void 0 || t.h !== void 0 && t.s !== void 0 && t.v !== void 0 && t.a !== void 0;
}
};
re.shared = new re();
re._temp = new re();
re.HEX_PATTERN = /^(#|0x)?(([a-f0-9]{3}){1,2}([a-f0-9]{2})?)$/i;
let J = re;
const Vn = {
cullArea: null,
cullable: !1,
cullableChildren: !0
};
function jn(i, t, e) {
const s = i.length;
let r;
if (t >= s || e === 0)
return;
e = t + e > s ? s - t : e;
const n = s - e;
for (r = t; r < n; ++r)
i[r] = i[r + e];
i.length = n;
}
const Xn = {
allowChildren: !0,
/**
* Removes all children from this container that are within the begin and end indexes.
* @param beginIndex - The beginning position.
* @param endIndex - The ending position. Default value is size of the container.
* @returns - List of removed children
* @memberof scene.Container#
*/
removeChildren(i = 0, t) {
const e = t ?? this.children.length, s = e - i, r = [];
if (s > 0 && s <= e) {
for (let a = e - 1; a >= i; a--) {
const o = this.children[a];
o && (r.push(o), o.parent = null);
}
jn(this.children, i, e);
const n = this.renderGroup || this.parentRenderGroup;
n && n.removeChildren(r);
for (let a = 0; a < r.length; ++a)
this.emit("childRemoved", r[a], this, a), r[a].emit("removed", this);
return r;
} else if (s === 0 && this.children.length === 0)
return r;
throw new RangeError("removeChildren: numeric values are outside the acceptable range.");
},
/**
* Removes a child from the specified index position.
* @param index - The index to get the child from
* @returns The child that was removed.
* @memberof scene.Container#
*/
removeChildAt(i) {
const t = this.getChildAt(i);
return this.removeChild(t);
},
/**
* Returns the child at the specified index
* @param index - The index to get the child at
* @returns - The child at the given index, if any.
* @memberof scene.Container#
*/
getChildAt(i) {
if (i < 0 || i >= this.children.length)
throw new Error(`getChildAt: Index (${i}) does not exist.`);
return this.children[i];
},
/**
* Changes the position of an existing child in the container container
* @param child - The child Container instance for which you want to change the index number
* @param index - The resulting index number for the child container
* @memberof scene.Container#
*/
setChildIndex(i, t) {
if (t < 0 || t >= this.children.length)
throw new Error(`The index ${t} supplied is out of bounds ${this.children.length}`);
this.getChildIndex(i), this.addChildAt(i, t);
},
/**
* Returns the index position of a child Container instance
* @param child - The Container instance to identify
* @returns - The index position of the child container to identify
* @memberof scene.Container#
*/
getChildIndex(i) {
const t = this.children.indexOf(i);
if (t === -1)
throw new Error("The supplied Container must be a child of the caller");
return t;
},
/**
* Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown.
* If the child is already in this container, it will be moved to the specified index.
* @param {Container} child - The child to add.
* @param {number} index - The absolute index where the child will be positioned at the end of the operation.
* @returns {Container} The child that was added.
* @memberof scene.Container#
*/
addChildAt(i, t) {
this.allowChildren || q($, "addChildAt: Only Containers will be allowed to add children in v8.0.0");
const { children: e } = this;
if (t < 0 || t > e.length)
throw new Error(`${i}addChildAt: The index ${t} supplied is out of bounds ${e.length}`);
if (i.parent) {
const r = i.parent.children.indexOf(i);
if (i.parent === this && r === t)
return i;
r !== -1 && i.parent.children.splice(r, 1);
}
t === e.length ? e.push(i) : e.splice(t, 0, i), i.parent = this, i.didChange = !0, i.didViewUpdate = !1, i._updateFlags = 15;
const s = this.renderGroup || this.parentRenderGroup;
return s && s.addChild(i), this.sortableChildren && (this.sortDirty = !0), this.emit("childAdded", i, this, t), i.emit("added", this), i;
},
/**
* Swaps the position of 2 Containers within this container.
* @param child - First container to swap
* @param child2 - Second container to swap
*/
swapChildren(i, t) {
if (i === t)
return;
const e = this.getChildIndex(i), s = this.getChildIndex(t);
this.children[e] = t, this.children[s] = i;
},
/**
* Remove the Container from its parent Container. If the Container has no parent, do nothing.
* @memberof scene.Container#
*/
removeFromParent() {
var i;
(i = this.parent) == null || i.removeChild(this);
}
};
class Ss {
constructor() {
this.pipe = "filter", this.priority = 1;
}
destroy() {
for (let t = 0; t < this.filters.length; t++)
this.filters[t].destroy();
this.filters = null, this.filterArea = null;
}
}
class qi {
/**
* Constructs a new Pool.
* @param ClassType - The constructor of the items in the pool.
* @param {number} [initialSize] - The initial size of the pool.
*/
constructor(t, e) {
this._pool = [], this._count = 0, this._index = 0, this._classType = t, e && this.prepopulate(e);
}
/**
* Prepopulates the pool with a given number of items.
* @param total - The number of items to add to the pool.
*/
prepopulate(t) {
for (let e = 0; e < t; e++)
this._pool[this._index++] = new this._classType();
this._count += t;
}
/**
* 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(t) {
var s;
let e;
return this._index > 0 ? e = this._pool[--this._index] : e = new this._classType(), (s = e.init) == null || s.call(e, t), e;
}
/**
* 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(t) {
var e;
(e = t.reset) == null || e.call(t), this._pool[this._index++] = t;
}
/**
* Gets the number of items in the pool.
* @readonly
* @member {number}
*/
get totalSize() {
return this._count;
}
/**
* Gets the number of items in the pool that are free to use without needing to create more.
* @readonly
* @member {number}
*/
get totalFree() {
return this._index;
}
/**
* Gets the number of items in the pool that are currently in use.
* @readonly
* @member {number}
*/
get totalUsed() {
return this._count - this._index;
}
}
class $n {
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<T>} Class - The constructor of the items in the pool.
* @param {number} total - The number of items to add to the pool.
*/
prepopulate(t, e) {
this.getPool(t).prepopulate(e);
}
/**
* Gets an item from a specific pool.
* @template T The type of items in the pool. Must extend PoolItem.
* @param {PoolItemConstructor<T>} Class - The constructor of the items in the pool.
* @param {unknown} [data] - Optional data to pass to the item's constructor.
* @returns {T} The item from the pool.
*/
get(t, e) {
return this.getPool(t).get(e);
}
/**
* Returns an item to its respective pool.
* @param {PoolItem} item - The item to return to the pool.
*/
return(t) {
this.getPool(t.constructor).return(t);
}
/**
* Gets a specific pool based on the class type.
* @template T The type of items in the pool. Must extend PoolItem.
* @param {PoolItemConstructor<T>} ClassType - The constructor of the items in the pool.
* @returns {Pool<T>} The pool of the given class type.
*/
getPool(t) {
return this._poolsByClass.has(t) || this._poolsByClass.set(t, new qi(t)), this._poolsByClass.get(t);
}
/** gets the usage stats of each pool in the system */
stats() {
const t = {};
return this._poolsByClass.forEach((e) => {
const s = t[e._classType.name] ? e._classType.name + e._classType.ID : e._classType.name;
t[s] = {
free: e.totalFree,
used: e.totalUsed,
size: e.totalSize
};
}), t;
}
}
const kt = new $n();
class qn {
constructor() {
this._effectClasses = [], this._tests = [], this._initialized = !1;
}
init() {
this._initialized || (this._initialized = !0, this._effectClasses.forEach((t) => {
this.add({
test: t.test,
maskClass: t
});
}));
}
add(t) {
this._tests.push(t);
}
getMaskEffect(t) {
this._initialized || this.init();
for (let e = 0; e < this._tests.length; e++) {
const s = this._tests[e];
if (s.test(t))
return kt.get(s.maskClass, t);
}
return t;
}
returnMaskEffect(t) {
kt.return(t);
}
}
const Ri = new qn();
dt.handleByList(B.MaskEffect, Ri._effectClasses);
const Kn = {
_maskEffect: null,
_filterEffect: null,
/**
* @todo Needs docs.
* @memberof scene.Container#
* @type {Array<Effect>}
*/
effects: [],
/**
* @todo Needs docs.
* @param effect - The effect to add.
* @memberof scene.Container#
* @ignore
*/
addEffect(i) {
if (this.effects.indexOf(i) !== -1)
return;
this.effects.push(i), this.effects.sort((s, r) => s.priority - r.priority);
const e = this.renderGroup || this.parentRenderGroup;
e && (e.structureDidChange = !0), this._updateIsSimple();
},
/**
* @todo Needs docs.
* @param effect - The effect to remove.
* @memberof scene.Container#
* @ignore
*/
removeEffect(i) {
const t = this.effects.indexOf(i);
t !== -1 && (this.effects.splice(t, 1), this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateIsSimple());
},
set mask(i) {
const t = this._maskEffect;
(t == null ? void 0 : t.mask) !== i && (t && (this.removeEffect(t), Ri.returnMaskEffect(t), this._maskEffect = null), i != null && (this._maskEffect = Ri.getMaskEffect(i), this.addEffect(this._maskEffect)));
},
/**
* Sets a mask for the displayObject. A mask is an object that limits the visibility of an
* object to the shape of the mask applied to it. In PixiJS a regular mask must be a
* {@link Graphics} or a {@link Sprite} object. This allows for much faster masking in canvas as it
* utilities shape clipping. Furthermore, a mask of an object must be in the subtree of its parent.
* Otherwise, `getLocalBounds` may calculate incorrect bounds, which makes the container's width and height wrong.
* To remove a mask, set this property to `null`.
*
* For sprite mask both alpha and red channel are used. Black mask is the same as transparent mask.
* @example
* import { Graphics, Sprite } from 'pixi.js';
*
* const graphics = new Graphics();
* graphics.beginFill(0xFF3300);
* graphics.drawRect(50, 250, 100, 100);
* graphics.endFill();
*
* const sprite = new Sprite(texture);
* sprite.mask = graphics;
* @memberof scene.Container#
*/
get mask() {
var i;
return (i = this._maskEffect) == null ? void 0 : i.mask;
},
set filters(i) {
var n;
!Array.isArray(i) && i && (i = [i]);
const t = this._filterEffect || (this._filterEffect = new Ss());
i = i;
const e = (i == null ? void 0 : i.length) > 0, s = ((n = t.filters) == null ? void 0 : n.length) > 0, r = e !== s;
i = Array.isArray(i) ? i.slice(0) : i, t.filters = Object.freeze(i), r && (e ? this.addEffect(t) : (this.removeEffect(t), t.filters = i ?? null));
},
/**
* Sets the filters for the displayObject.
* IMPORTANT: This is a WebGL only feature and will be ignored by the canvas renderer.
* To remove filters simply set this property to `'null'`.
* @memberof scene.Container#
*/
get filters() {
var i;
return (i = this._filterEffect) == null ? void 0 : i.filters;
},
set filterArea(i) {
this._filterEffect || (this._filterEffect = new Ss()), this._filterEffect.filterArea = i;
},
/**
* The area the filter is applied to. This is used as more of an optimization
* rather than figuring out the dimensions of the displayObject each frame you can set this rectangle.
*
* Also works as an interaction mask.
* @memberof scene.Container#
*/
get filterArea() {
var i;
return (i = this._filterEffect) == null ? void 0 : i.filterArea;
}
}, Zn = {
/**
* The instance label of the object.
* @memberof scene.Container#
* @member {string} label
*/
label: null,
/**
* The instance name of the object.
* @deprecated since 8.0.0
* @see scene.Container#label
* @member {string} name
* @memberof scene.Container#
*/
get name() {
return q($, "Container.name property has been removed, use Container.label instead"), this.label;
},
set name(i) {
q($, "Container.name property has been removed, use Container.label instead"), this.label = i;
},
/**
* @method getChildByName
* @deprecated since 8.0.0
* @param {string} name - Instance name.
* @param {boolean}[deep=false] - Whether to search recursively
* @returns {Container} The child with the specified name.
* @see scene.Container#getChildByLabel
* @memberof scene.Container#
*/
getChildByName(i, t = !1) {
return this.getChildByLabel(i, t);
},
/**
* Returns the first child in the container with the specified label.
*
* Recursive searches are done in a pre-order traversal.
* @memberof scene.Container#
* @param {string|RegExp} label - Instance label.
* @param {boolean}[deep=false] - Whether to search recursively
* @returns {Container} The child with the specified label.
*/
getChildByLabel(i, t = !1) {
const e = this.children;
for (let s = 0; s < e.length; s++) {
const r = e[s];
if (r.label === i || i instanceof RegExp && i.test(r.label))
return r;
}
if (t)
for (let s = 0; s < e.length; s++) {
const n = e[s].getChildByLabel(i, !0);
if (n)
return n;
}
return null;
},
/**
* Returns all children in the container with the specified label.
* @memberof scene.Container#
* @param {string|RegExp} label - Instance label.
* @param {boolean}[deep=false] - Whether to search recursively
* @param {Container[]} [out=[]] - The array to store matching children in.
* @returns {Container[]} An array of children with the specified label.
*/
getChildrenByLabel(i, t = !1, e = []) {
const s = this.children;
for (let r = 0; r < s.length; r++) {
const n = s[r];
(n.label === i || i instanceof RegExp && i.test(n.label)) && e.push(n);
}
if (t)
for (let r = 0; r < s.length; r++)
s[r].getChildrenByLabel(i, !0, e);
return e;
}
}, Cs = new D();
class St {
constructor(t = 1 / 0, e = 1 / 0, s = -1 / 0, r = -1 / 0) {
this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Cs, this.minX = t, this.minY = e, this.maxX = s, this.maxY = r;
}
/**
* Checks if bounds are empty.
* @returns - True if empty.
*/
isEmpty() {
return this.minX > this.maxX || this.minY > this.maxY;
}
/** The bounding rectangle of the bounds. */
get rectangle() {
this._rectangle || (this._rectangle = new tt());
const t = this._rectangle;
return this.minX > this.maxX || this.minY > this.maxY ? (t.x = 0, t.y = 0, t.width = 0, t.height = 0) : t.copyFromBounds(this), t;
}
/** Clears the bounds and resets. */
clear() {
return this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, this.matrix = Cs, this;
}
/**
* Sets the bounds.
* @param x0 - left X of frame
* @param y0 - top Y of frame
* @param x1 - right X of frame
* @param y1 - bottom Y of frame
*/
set(t, e, s, r) {
this.minX = t, this.minY = e, this.maxX = s, this.maxY = r;
}
/**
* Adds sprite frame
* @param x0 - left X of frame
* @param y0 - top Y of frame
* @param x1 - right X of frame
* @param y1 - bottom Y of frame
* @param matrix
*/
addFrame(t, e, s, r, n) {
n || (n = this.matrix);
const a = n.a, o = n.b, h = n.c, c = n.d, l = n.tx, u = n.ty;
let d = this.minX, p = this.minY, f = this.maxX, g = this.maxY, m = a * t + h * e + l, y = o * t + c * e + u;
m < d && (d = m), y < p && (p = y), m > f && (f = m), y > g && (g = y), m = a * s + h * e + l, y = o * s + c * e + u, m < d && (d = m), y < p && (p = y), m > f && (f = m), y > g && (g = y), m = a * t + h * r + l, y = o * t + c * r + u, m < d && (d = m), y < p && (p = y), m > f && (f = m), y > g && (g = y), m = a * s + h * r + l, y = o * s + c * r + u, m < d && (d = m), y < p && (p = y), m > f && (f = m), y > g && (g = y), this.minX = d, this.minY = p, this.maxX = f, this.maxY = g;
}
/**
* Adds a rectangle to the bounds.
* @param rect - The rectangle to be added.
* @param matrix - The matrix to apply to the bounds.
*/
addRect(t, e) {
this.addFrame(t.x, t.y, t.x + t.width, t.y + t.height, e);
}
/**
* Adds other {@link Bounds}.
* @param bounds - The Bounds to be added
* @param matrix
*/
addBounds(t, e) {
this.addFrame(t.minX, t.minY, t.maxX, t.maxY, e);
}
/**
* Adds other Bounds, masked with Bounds.
* @param mask - The Bounds to be added.
*/
addBoundsMask(t) {
this.minX = this.minX > t.minX ? this.minX : t.minX, this.minY = this.minY > t.minY ? this.minY : t.minY, this.maxX = this.maxX < t.maxX ? this.maxX : t.maxX, this.maxY = this.maxY < t.maxY ? this.maxY : t.maxY;
}
/**
* Adds other Bounds, multiplied with matrix.
* @param matrix - The matrix to apply to the bounds.
*/
applyMatrix(t) {
const e = this.minX, s = this.minY, r = this.maxX, n = this.maxY, { a, b: o, c: h, d: c, tx: l, ty: u } = t;
let d = a * e + h * s + l, p = o * e + c * s + u;
this.minX = d, this.minY = p, this.maxX = d, this.maxY = p, d = a * r + h * s + l, p = o * r + c * s + u, this.minX = d < this.minX ? d : this.minX, this.minY = p < this.minY ? p : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = p > this.maxY ? p : this.maxY, d = a * e + h * n + l, p = o * e + c * n + u, this.minX = d < this.minX ? d : this.minX, this.minY = p < this.minY ? p : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = p > this.maxY ? p : this.maxY, d = a * r + h * n + l, p = o * r + c * n + u, this.minX = d < this.minX ? d : this.minX, this.minY = p < this.minY ? p : this.minY, this.maxX = d > this.maxX ? d : this.maxX, this.maxY = p > this.maxY ? p : this.maxY;
}
/**
* Resizes the bounds object to include the given rectangle.
* @param rect - The rectangle to be included.
*/
fit(t) {
return this.minX < t.left && (this.minX = t.left), this.maxX > t.right && (this.maxX = t.right), this.minY < t.top && (this.minY = t.top), this.maxY > t.bottom && (this.maxY = t.bottom), this;
}
/**
* Resizes the bounds object to include the given bounds.
* @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.
*/
fitBounds(t, e, s, r) {
return this.minX < t && (this.minX = t), this.maxX > e && (this.maxX = e), this.minY < s && (this.minY = s), this.maxY > r && (this.maxY = r), this;
}
/**
* Pads bounds object, making it grow in all directions.
* If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
* @param paddingX - The horizontal padding amount.
* @param paddingY - The vertical padding amount.
*/
pad(t, e = t) {
return this.minX -= t, this.maxX += t, this.minY -= e, this.maxY += e, this;
}
/** Ceils the 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;
}
/** Clones the bounds. */
clone() {
return new St(this.minX, this.minY, this.maxX, this.maxY);
}
/**
* Scales the bounds by the given values
* @param x - The X value to scale by.
* @param y - The Y value to scale by.
*/
scale(t, e = t) {
return this.minX *= t, this.minY *= e, this.maxX *= t, this.maxY *= e, this;
}
/** the x value of the bounds. */
get x() {
return this.minX;
}
set x(t) {
const e = this.maxX - this.minX;
this.minX = t, this.maxX = t + e;
}
/** the y value of the bounds. */
get y() {
return this.minY;
}
set y(t) {
const e = this.maxY - this.minY;
this.minY = t, this.maxY = t + e;
}
/** the width value of the bounds. */
get width() {
return this.maxX - this.minX;
}
set width(t) {
this.maxX = this.minX + t;
}
/** the height value of the bounds. */
get height() {
return this.maxY - this.minY;
}
set height(t) {
this.maxY = this.minY + t;
}
/** the left value of the bounds. */
get left() {
return this.minX;
}
/** the right value of the bounds. */
get right() {
return this.maxX;
}
/** the top value of the bounds. */
get top() {
return this.minY;
}
/** the bottom value of the bounds. */
get bottom() {
return this.maxY;
}
/** Is the bounds positive. */
get isPositive() {
return this.maxX - this.minX > 0 && this.maxY - this.minY > 0;
}
get isValid() {
return this.minX + this.minY !== 1 / 0;
}
/**
* Adds screen vertices from array
* @param vertexData - calculated vertices
* @param beginOffset - begin offset
* @param endOffset - end offset, excluded
* @param matrix
*/
addVertexData(t, e, s, r) {
let n = this.minX, a = this.minY, o = this.maxX, h = this.maxY;
r || (r = this.matrix);
const c = r.a, l = r.b, u = r.c, d = r.d, p = r.tx, f = r.ty;
for (let g = e; g < s; g += 2) {
const m = t[g], y = t[g + 1], _ = c * m + u * y + p, x = l * m + d * y + f;
n = _ < n ? _ : n, a = x < a ? x : a, o = _ > o ? _ : o, h = x > h ? x : h;
}
this.minX = n, this.minY = a, this.maxX = o, this.maxY = h;
}
/**
* Checks if the point is contained within the bounds.
* @param x - x coordinate
* @param y - y coordinate
*/
containsPoint(t, e) {
return this.minX <= t && this.minY <= e && this.maxX >= t && this.maxY >= e;
}
toString() {
return `[pixi.js:Bounds minX=${this.minX} minY=${this.minY} maxX=${this.maxX} maxY=${this.maxY} width=${this.width} height=${this.height}]`;
}
}
const Et = new qi(D), ne = new qi(St);
function pr(i, t, e) {
e.clear();
let s, r;
return i.parent ? t ? s = i.parent.worldTransform : (r = Et.get().identity(), s = qe(i, r)) : s = D.IDENTITY, mr(i, e, s, t), r && Et.return(r), e.isValid || e.set(0, 0, 0, 0), e;
}
function mr(i, t, e, s) {
var o, h;
if (!i.visible || !i.measurable)
return;
let r;
s ? r = i.worldTransform : (i.updateLocalTransform(), r = Et.get(), r.appendFrom(i.localTransform, e));
const n = t, a = !!i.effects.length;
if (a && (t = ne.get().clear()), i.boundsArea)
t.addRect(i.boundsArea, r);
else {
i.addBounds && (t.matrix = r, i.addBounds(t));
for (let c = 0; c < i.children.length; c++)
mr(i.children[c], t, r, s);
}
if (a) {
for (let c = 0; c < i.effects.length; c++)
(h = (o = i.effects[c]).addBounds) == null || h.call(o, t);
n.addBounds(t, D.IDENTITY), ne.return(t);
}
s || Et.return(r);
}
function qe(i, t) {
const e = i.parent;
return e && (qe(e, t), e.updateLocalTransform(), t.append(e.localTransform)), t;
}
let pi = 0;
const Ms = 500;
function it(...i) {
pi !== Ms && (pi++, pi === Ms ? console.warn("PixiJS Warning: too many warnings, no more warnings will be reported to the console by PixiJS.") : console.warn("PixiJS Warning: ", ...i));
}
function gr(i, t, e) {
return t.clear(), e || (e = D.IDENTITY), yr(i, t, e, i, !0), t.isValid || t.set(0, 0, 0, 0), t;
}
function yr(i, t, e, s, r) {
var h, c;
let n;
if (r)
n = Et.get(), n = e.copyTo(n);
else {
if (!i.visible || !i.measurable)
return;
i.updateLocalTransform();
const l = i.localTransform;
n = Et.get(), n.appendFrom(l, e);
}
const a = t, o = !!i.effects.length;
if (o && (t = ne.get().clear()), i.boundsArea)
t.addRect(i.boundsArea, n);
else {
i.renderPipeId && (t.matrix = n, i.addBounds(t));
const l = i.children;
for (let u = 0; u < l.length; u++)
yr(l[u], t, n, s, !1);
}
if (o) {
for (let l = 0; l < i.effects.length; l++)
(c = (h = i.effects[l]).addLocalBounds) == null || c.call(h, t, s);
a.addBounds(t, D.IDENTITY), ne.return(t);
}
Et.return(n);
}
function _r(i, t) {
const e = i.children;
for (let s = 0; s < e.length; s++) {
const r = e[s], n = (r.uid & 255) << 24 | r._didChangeId & 16777215;
t.data[t.index] !== n && (t.data[t.index] = n, t.didChange = !0), t.index++, r.children.length && _r(r, t);
}
return t.didChange;
}
const Jn = new D(), Qn = {
_localBoundsCacheId: -1,
_localBoundsCacheData: null,
_setWidth(i, t) {
const e = Math.sign(this.scale.x) || 1;
t !== 0 ? this.scale.x = i / t * e : this.scale.x = e;
},
_setHeight(i, t) {
const e = Math.sign(this.scale.y) || 1;
t !== 0 ? this.scale.y = i / t * e : this.scale.y = e;
},
/**
* Retrieves the local bounds of the container as a Bounds object.
* @returns - The bounding area.
* @memberof scene.Container#
*/
getLocalBounds() {
this._localBoundsCacheData || (this._localBoundsCacheData = {
data: [],
index: 1,
didChange: !1,
localBounds: new St()
});
const i = this._localBoundsCacheData;
return i.index = 1, i.didChange = !1, i.data[0] !== this._didChangeId >> 12 && (i.didChange = !0, i.data[0] = this._didChangeId >> 12), _r(this, i), i.didChange && gr(this, i.localBounds, Jn), i.localBounds;
},
/**
* Calculates and returns the (world) bounds of the display object as a [Rectangle]{@link Rectangle}.
* @param skipUpdate - Setting to `true` will stop the transforms of the scene graph from
* being updated. This means the calculation returned MAY be out of date BUT will give you a
* nice performance boost.
* @param bounds - Optional bounds to store the result of the bounds calculation.
* @returns - The minimum axis-aligned rectangle in world space that fits around this object.
* @memberof scene.Container#
*/
getBounds(i, t) {
return pr(this, i, t || new St());
}
}, ta = {
_onRender: null,
set onRender(i) {
const t = this.renderGroup || this.parentRenderGroup;
if (!i) {
this._onRender && (t == null || t.removeOnRender(this)), this._onRender = null;
return;
}
this._onRender || t == null || t.addOnRender(this), this._onRender = i;
},
/**
* This callback is used when the container is rendered. This is where you should add your custom
* logic that is needed to be run every frame.
*
* In v7 many users used `updateTransform` for this, however the way v8 renders objects is different
* and "updateTransform" is no longer called every frame
* @example
* const container = new Container();
* container.onRender = () => {
* container.rotation += 0.01;
* };
* @memberof scene.Container#
*/
get onRender() {
return this._onRender;
}
}, ea = {
_zIndex: 0,
/**
* Should children be sorted by zIndex at the next render call.
*
* Will get automatically set to true if a new child is added, or if a child's zIndex changes.
* @type {boolean}
* @memberof scene.Container#
*/
sortDirty: !1,
/**
* If set to true, the container will sort its children by `zIndex` value
* when the next render is called, or manually if `sortChildren()` is called.
*
* This actually changes the order of elements in the array, so should be treated
* as a basic solution that is not performant compared to other solutions,
* such as {@link https://github.com/pixijs/layers PixiJS Layers}
*
* Also be aware of that this may not work nicely with the `addChildAt()` function,
* as the `zIndex` sorting may cause the child to automatically sorted to another position.
* @type {boolean}
* @memberof scene.Container#
*/
sortableChildren: !1,
/**
* The zIndex of the container.
*
* Setting this value, will automatically set the parent to be sortable. Children will be automatically
* sorted by zIndex value; a higher value will mean it will be moved towards the end of the array,
* and thus rendered on top of other display objects within the same container.
* @see scene.Container#sortableChildren
* @memberof scene.Container#
*/
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);
},
/**
* Sorts children by zIndex.
* @memberof scene.Container#
*/
sortChildren() {
this.sortDirty && (this.sortDirty = !1, this.children.sort(ia));
}
};
function ia(i, t) {
return i._zIndex - t._zIndex;
}
const sa = {
/**
* Returns the global position of the container.
* @param point - The optional point to write the global value to.
* @param skipUpdate - Should we skip the update transform.
* @returns - The updated point.
* @memberof scene.Container#
*/
getGlobalPosition(i = new st(), t = !1) {
return this.parent ? this.parent.toGlobal(this._position, i, t) : (i.x = this._position.x, i.y = this._position.y), i;
},
/**
* Calculates the global position of the container.
* @param position - The world origin to calculate from.
* @param point - A Point object in which to store the value, optional
* (otherwise will create a new Point).
* @param skipUpdate - Should we skip the update transform.
* @returns - A point object representing the position of this object.
* @memberof scene.Container#
*/
toGlobal(i, t, e = !1) {
if (!e) {
this.updateLocalTransform();
const s = qe(this, new D());
return s.append(this.localTransform), s.apply(i, t);
}
return this.worldTransform.apply(i, t);
},
/**
* Calculates the local position of the container relative to another point.
* @param position - The world origin to calculate from.
* @param from - The Container to calculate the global position from.
* @param point - A Point object in which to store the value, optional
* (otherwise will create a new Point).
* @param skipUpdate - Should we skip the update transform
* @returns - A point object representing the position of this object
* @memberof scene.Container#
*/
toLocal(i, t, e, s) {
if (t && (i = t.toGlobal(i, e, s)), !s) {
this.updateLocalTransform();
const r = qe(this, new D());
return r.append(this.localTransform), r.applyInverse(i, e);
}
return this.worldTransform.applyInverse(i, e);
}
};
class xr {
constructor() {
this.uid = et("instructionSet"), this.instructions = [], this.instructionSize = 0;
}
/** reset the instruction set so it can be reused set size back to 0 */
reset() {
this.instructionSize = 0;
}
/**
* Add an instruction to the set
* @param instruction - add an instruction to the set
*/
add(t) {
this.instructions[this.instructionSize++] = t;
}
/**
* Log the instructions to the console (for debugging)
* @internal
* @ignore
*/
log() {
this.instructions.length = this.instructionSize, console.table(this.instructions, ["type", "action"]);
}
}
class ra {
constructor(t) {
this.renderPipeId = "renderGroup", this.root = null, this.canBundle = !1, this.renderGroupParent = null, this.renderGroupChildren = [], this.worldTransform = new D(), this.worldColorAlpha = 4294967295, this.worldColor = 16777215, this.worldAlpha = 1, this.childrenToUpdate = /* @__PURE__ */ Object.create(null), this.updateTick = 0, this.childrenRenderablesToUpdate = { list: [], index: 0 }, this.structureDidChange = !0, this.instructionSet = new xr(), this._onRenderContainers = [], this.root = t, t._onRender && this.addOnRender(t), t.didChange = !0;
const e = t.children;
for (let s = 0; s < e.length; s++)
this.addChild(e[s]);
}
get localTransform() {
return this.root.localTransform;
}
addRenderGroupChild(t) {
t.renderGroupParent && t.renderGroupParent._removeRenderGroupChild(t), t.renderGroupParent = this, this.renderGroupChildren.push(t);
}
_removeRenderGroupChild(t) {
const e = this.renderGroupChildren.indexOf(t);
e > -1 && this.renderGroupChildren.splice(e, 1), t.renderGroupParent = null;
}
addChild(t) {
if (this.structureDidChange = !0, t.parentRenderGroup = this, t.updateTick = -1, t.parent === this.root ? t.relativeRenderGroupDepth = 1 : t.relativeRenderGroupDepth = t.parent.relativeRenderGroupDepth + 1, t.didChange = !0, this.onChildUpdate(t), t.renderGroup) {
this.addRenderGroupChild(t.renderGroup);
return;
}
t._onRender && this.addOnRender(t);
const e = t.children;
for (let s = 0; s < e.length; s++)
this.addChild(e[s]);
}
removeChild(t) {
if (this.structureDidChange = !0, t._onRender && (t.renderGroup || this.removeOnRender(t)), t.parentRenderGroup = null, t.renderGroup) {
this._removeRenderGroupChild(t.renderGroup);
return;
}
const e = t.children;
for (let s = 0; s < e.length; s++)
this.removeChild(e[s]);
}
removeChildren(t) {
for (let e = 0; e < t.length; e++)
this.removeChild(t[e]);
}
onChildUpdate(t) {
let e = this.childrenToUpdate[t.relativeRenderGroupDepth];
e || (e = this.childrenToUpdate[t.relativeRenderGroupDepth] = {
index: 0,
list: []
}), e.list[e.index++] = t;
}
// SHOULD THIS BE HERE?
updateRenderable(t) {
t.globalDisplayStatus < 7 || (t.didViewUpdate = !1, this.instructionSet.renderPipes[t.renderPipeId].updateRenderable(t));
}
onChildViewUpdate(t) {
this.childrenRenderablesToUpdate.list[this.childrenRenderablesToUpdate.index++] = t;
}
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(t) {
this._onRenderContainers.push(t);
}
removeOnRender(t) {
this._onRenderContainers.splice(this._onRenderContainers.indexOf(t), 1);
}
runOnRender() {
for (let t = 0; t < this._onRenderContainers.length; t++)
this._onRenderContainers[t]._onRender();
}
getChildren(t = []) {
const e = this.root.children;
for (let s = 0; s < e.length; s++)
this._getChildren(e[s], t);
return t;
}
_getChildren(t, e = []) {
if (e.push(t), t.renderGroup)
return e;
const s = t.children;
for (let r = 0; r < s.length; r++)
this._getChildren(s[r], e);
return e;
}
}
function na(i, t, e = {}) {
for (const s in t)
!e[s] && t[s] !== void 0 && (i[s] = t[s]);
}
const mi = new nt(null), gi = new nt(null), yi = new nt(null, 1, 1), Ts = 1, aa = 2, _i = 4;
class O extends Bt {
constructor(t = {}) {
var e, s;
super(), this.uid = et("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 D(), this.relativeGroupTransform = new D(), this.groupTransform = this.relativeGroupTransform, this.destroyed = !1, this._position = new nt(this, 0, 0), this._scale = yi, this._pivot = gi, this._skew = mi, 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._didChangeId = 0, this._didLocalTransformChangeId = -1, na(this, t, {
children: !0,
parent: !0,
effects: !0
}), (e = t.children) == null || e.forEach((r) => this.addChild(r)), this.effects = [], (s = t.parent) == null || s.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.
*/
static mixin(t) {
Object.defineProperties(O.prototype, Object.getOwnPropertyDescriptors(t));
}
/**
* Adds one or more children to the container.
*
* Multiple items can be added like so: `myContainer.addChild(thingOne, thingTwo, thingThree)`
* @param {...Container} children - The Container(s) to add to the container
* @returns {Container} - The first child that was added.
*/
addChild(...t) {
if (this.allowChildren || q($, "addChild: Only Containers will be allowed to add children in v8.0.0"), t.length > 1) {
for (let r = 0; r < t.length; r++)
this.addChild(t[r]);
return t[0];
}
const e = t[0];
if (e.parent === this)
return this.children.splice(this.children.indexOf(e), 1), this.children.push(e), this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), e;
e.parent && e.parent.removeChild(e), this.children.push(e), this.sortableChildren && (this.sortDirty = !0), e.parent = this, e.didChange = !0, e.didViewUpdate = !1, e._updateFlags = 15;
const s = this.renderGroup || this.parentRenderGroup;
return s && s.addChild(e), this.emit("childAdded", e, this, this.children.length - 1), e.emit("added", this), this._didChangeId += 4096, e._zIndex !== 0 && e.depthOfChildModified(), e;
}
/**
* Removes one or more children from the container.
* @param {...Container} children - The Container(s) to remove
* @returns {Container} The first child that was removed.
*/
removeChild(...t) {
if (t.length > 1) {
for (let r = 0; r < t.length; r++)
this.removeChild(t[r]);
return t[0];
}
const e = t[0], s = this.children.indexOf(e);
return s > -1 && (this._didChangeId += 4096, this.children.splice(s, 1), this.renderGroup ? this.renderGroup.removeChild(e) : this.parentRenderGroup && this.parentRenderGroup.removeChild(e), e.parent = null, this.emit("childRemoved", e, this, s), e.emit("removed", this)), e;
}
/** @ignore */
_onUpdate(t) {
t && t === this._skew && this._updateSkew(), this._didChangeId++, !this.didChange && (this.didChange = !0, this.parentRenderGroup && this.parentRenderGroup.onChildUpdate(this));
}
set isRenderGroup(t) {
if (this.renderGroup && t === !1)
throw new Error("[Pixi] cannot undo a render group just yet");
t && this.enableRenderGroup();
}
/**
* 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
*/
get isRenderGroup() {
return !!this.renderGroup;
}
/** This enables the container to be rendered as a render group. */
enableRenderGroup() {
if (this.renderGroup)
return;
const t = this.parentRenderGroup;
t && t.removeChild(this), this.renderGroup = new ra(this), t && t.addChild(this), this._updateIsSimple(), this.groupTransform = D.IDENTITY;
}
/** @ignore */
_updateIsSimple() {
this.isSimple = !this.renderGroup && this.effects.length === 0;
}
/**
* Current transform of the object based on world (parent) factors.
* @readonly
*/
get worldTransform() {
return this._worldTransform || (this._worldTransform = new D()), this.renderGroup ? this._worldTransform.copyFrom(this.renderGroup.worldTransform) : this.parentRenderGroup && this._worldTransform.appendFrom(this.relativeGroupTransform, this.parentRenderGroup.worldTransform), this._worldTransform;
}
// / ////// transform related stuff
/**
* The position of the container on the x axis relative to the local coordinates of the parent.
* An alias to position.x
*/
get x() {
return this._position.x;
}
set x(t) {
this._position.x = t;
}
/**
* The position of the container on the y axis relative to the local coordinates of the parent.
* An alias to position.y
*/
get y() {
return this._position.y;
}
set y(t) {
this._position.y = t;
}
/**
* The coordinate of the object relative to the local coordinates of the parent.
* @since 4.0.0
*/
get position() {
return this._position;
}
set position(t) {
this._position.copyFrom(t);
}
/**
* The rotation of the object in radians.
* 'rotation' and 'angle' have the same effect on a display object; rotation is in radians, angle is in degrees.
*/
get rotation() {
return this._rotation;
}
set rotation(t) {
this._rotation !== t && (this._rotation = t, this._onUpdate(this._skew));
}
/**
* The angle of the object in degrees.
* 'rotation' and 'angle' have the same effect on a display object; rotation is in radians, angle is in degrees.
*/
get angle() {
return this.rotation * Mn;
}
set angle(t) {
this.rotation = t * Tn;
}
/**
* 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).
* @since 4.0.0
*/
get pivot() {
return this._pivot === gi && (this._pivot = new nt(this, 0, 0)), this._pivot;
}
set pivot(t) {
this._pivot === gi && (this._pivot = new nt(this, 0, 0)), typeof t == "number" ? this._pivot.set(t) : this._pivot.copyFrom(t);
}
/**
* The skew factor for the object in radians.
* @since 4.0.0
*/
get skew() {
return this._skew === mi && (this._skew = new nt(this, 0, 0)), this._skew;
}
set skew(t) {
this._skew === mi && (this._skew = new nt(this, 0, 0)), this._skew.copyFrom(t);
}
/**
* The scale factors of this object along the local coordinate axes.
*
* The default scale is (1, 1).
* @since 4.0.0
*/
get scale() {
return this._scale === yi && (this._scale = new nt(this, 1, 1)), this._scale;
}
set scale(t) {
this._scale === yi && (this._scale = new nt(this, 0, 0)), typeof t == "number" ? this._scale.set(t) : this._scale.copyFrom(t);
}
/**
* The width of the Container, setting this will actually modify the scale to achieve the value set.
* @memberof scene.Container#
*/
get width() {
return Math.abs(this.scale.x * this.getLocalBounds().width);
}
set width(t) {
const e = this.getLocalBounds().width;
this._setWidth(t, e);
}
/**
* The height of the Container, setting this will actually modify the scale to achieve the value set.
* @memberof scene.Container#
*/
get height() {
return Math.abs(this.scale.y * this.getLocalBounds().height);
}
set height(t) {
const e = this.getLocalBounds().height;
this._setHeight(t, e);
}
/**
* Retrieves the size of the container as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the container.
* @memberof scene.Container#
*/
getSize(t) {
t || (t = {});
const e = this.getLocalBounds();
return t.width = Math.abs(this.scale.x * e.width), t.height = Math.abs(this.scale.y * e.height), t;
}
/**
* Sets the size of the container to the specified width and height.
* This is faster than setting the width and height separately.
* @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.
* @memberof scene.Container#
*/
setSize(t, e) {
const s = this.getLocalBounds();
let r, n;
typeof t != "object" ? (r = t, n = e ?? t) : (r = t.width, n = t.height ?? t.width), r !== void 0 && this._setWidth(r, s.width), n !== void 0 && this._setHeight(n, s.height);
}
/** Called when the skew or the rotation changes. */
_updateSkew() {
const t = this._rotation, e = this._skew;
this._cx = Math.cos(t + e._y), this._sx = Math.sin(t + e._y), this._cy = -Math.sin(t - e._x), this._sy = Math.cos(t - e._x);
}
/**
* Updates the transform properties of the container (accepts partial values).
* @param {object} opts - The options for updating the transform.
* @param {number} opts.x - The x position of the container.
* @param {number} opts.y - The y position of the container.
* @param {number} opts.scaleX - The scale factor on the x-axis.
* @param {number} opts.scaleY - The scale factor on the y-axis.
* @param {number} opts.rotation - The rotation of the container, in radians.
* @param {number} opts.skewX - The skew factor on the x-axis.
* @param {number} opts.skewY - The skew factor on the y-axis.
* @param {number} opts.pivotX - The x coordinate of the pivot point.
* @param {number} opts.pivotY - The y coordinate of the pivot point.
*/
updateTransform(t) {
return this.position.set(
typeof t.x == "number" ? t.x : this.position.x,
typeof t.y == "number" ? t.y : this.position.y
), this.scale.set(
typeof t.scaleX == "number" ? t.scaleX || 1 : this.scale.x,
typeof t.scaleY == "number" ? t.scaleY || 1 : this.scale.y
), this.rotation = typeof t.rotation == "number" ? t.rotation : this.rotation, this.skew.set(
typeof t.skewX == "number" ? t.skewX : this.skew.x,
typeof t.skewY == "number" ? t.skewY : this.skew.y
), this.pivot.set(
typeof t.pivotX == "number" ? t.pivotX : this.pivot.x,
typeof t.pivotY == "number" ? t.pivotY : this.pivot.y
), this;
}
/**
* Updates the local transform using the given matrix.
* @param matrix - The matrix to use for updating the transform.
*/
setFromMatrix(t) {
t.decompose(this);
}
/** Updates the local transform. */
updateLocalTransform() {
if ((this._didLocalTransformChangeId & 15) === this._didChangeId)
return;
this._didLocalTransformChangeId = this._didChangeId;
const t = this.localTransform, e = this._scale, s = this._pivot, r = this._position, n = e._x, a = e._y, o = s._x, h = s._y;
t.a = this._cx * n, t.b = this._sx * n, t.c = this._cy * a, t.d = this._sy * a, t.tx = r._x - (o * t.a + h * t.c), t.ty = r._y - (o * t.b + h * t.d);
}
// / ///// color related stuff
set alpha(t) {
t !== this.localAlpha && (this.localAlpha = t, this._updateFlags |= Ts, this._onUpdate());
}
/** The opacity of the object. */
get alpha() {
return this.localAlpha;
}
set tint(t) {
const s = J.shared.setValue(t ?? 16777215).toBgrNumber();
s !== this.localColor && (this.localColor = s, this._updateFlags |= Ts, this._onUpdate());
}
/**
* The tint applied to the sprite. This is a hex value.
*
* A value of 0xFFFFFF will remove any tint effect.
* @default 0xFFFFFF
*/
get tint() {
const t = this.localColor;
return ((t & 255) << 16) + (t & 65280) + (t >> 16 & 255);
}
// / //////////////// blend related stuff
set blendMode(t) {
this.localBlendMode !== t && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= aa, this.localBlendMode = t, this._onUpdate());
}
/**
* The blend mode to be applied to the sprite. Apply a value of `'normal'` to reset the blend mode.
* @default 'normal'
*/
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. */
get visible() {
return !!(this.localDisplayStatus & 2);
}
set visible(t) {
const e = t ? 1 : 0;
(this.localDisplayStatus & 2) >> 1 !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= _i, this.localDisplayStatus ^= 2, this._onUpdate());
}
/** @ignore */
get culled() {
return !(this.localDisplayStatus & 4);
}
/** @ignore */
set culled(t) {
const e = t ? 1 : 0;
(this.localDisplayStatus & 4) >> 2 !== e && (this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._updateFlags |= _i, this.localDisplayStatus ^= 4, this._onUpdate());
}
/** Can this object be rendered, if false the object will not be drawn but the transform will still be updated. */
get renderable() {
return !!(this.localDisplayStatus & 1);
}
set renderable(t) {
const e = t ? 1 : 0;
(this.localDisplayStatus & 1) !== e && (this._updateFlags |= _i, this.localDisplayStatus ^= 1, this.parentRenderGroup && (this.parentRenderGroup.structureDidChange = !0), this._onUpdate());
}
/** Whether or not the object should be rendered. */
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
* @param {boolean} [options.children=false] - if set to true, all the children will have their destroy
* method called as well. 'options' will be passed on to those calls.
* @param {boolean} [options.texture=false] - Only used for children with textures e.g. Sprites. If options.children
* is set to true it should destroy the texture of the child sprite
* @param {boolean} [options.textureSource=false] - Only used for children with textures e.g. Sprites.
* If options.children is set to true it should destroy the texture source of the child sprite
* @param {boolean} [options.context=false] - Only used for children with graphicsContexts e.g. Graphics.
* If options.children is set to true it should destroy the context of the child graphics
*/
destroy(t = !1) {
if (this.destroyed)
return;
this.destroyed = !0;
const e = this.removeChildren(0, this.children.length);
if (this.removeFromParent(), this.parent = null, this._maskEffect = null, this._filterEffect = null, this.effects = null, this._position = null, this._scale = null, this._pivot = null, this._skew = null, this.emit("destroyed", this), this.removeAllListeners(), typeof t == "boolean" ? t : t == null ? void 0 : t.children)
for (let r = 0; r < e.length; ++r)
e[r].destroy(t);
}
}
O.mixin(Xn);
O.mixin(sa);
O.mixin(ta);
O.mixin(Qn);
O.mixin(Kn);
O.mixin(Zn);
O.mixin(ea);
O.mixin(Vn);
class xt extends O {
/**
* @param options - The options for creating the sprite.
*/
constructor(t = L.EMPTY) {
t instanceof L && (t = { texture: t });
const { texture: e = L.EMPTY, anchor: s, roundPixels: r, width: n, height: a, ...o } = t;
super({
label: "Sprite",
...o
}), this.renderPipeId = "sprite", this.batched = !0, this._didSpriteUpdate = !1, this._bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 }, this._sourceBounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 }, this._boundsDirty = !0, this._sourceBoundsDirty = !0, this._roundPixels = 0, this._anchor = new nt(
{
_onUpdate: () => {
this.onViewUpdate();
}
}
), s ? this.anchor = s : e.defaultAnchor && (this.anchor = e.defaultAnchor), this.texture = e, this.allowChildren = !1, this.roundPixels = r ?? !1, n && (this.width = n), a && (this.height = a);
}
/**
* Helper function that creates a new sprite based on the source you provide.
* The source can be - frame id, image, video, canvas element, video element, texture
* @param source - Source to create texture from
* @param [skipCache] - Whether to skip the cache or not
* @returns The newly created sprite
*/
static from(t, e = !1) {
return t instanceof L ? new xt(t) : new xt(L.from(t, e));
}
set texture(t) {
t || (t = L.EMPTY);
const e = this._texture;
e !== t && (e && e.dynamic && e.off("update", this.onViewUpdate, this), t.dynamic && t.on("update", this.onViewUpdate, this), this._texture = t, this.onViewUpdate());
}
/** The texture that the sprite is using. */
get texture() {
return this._texture;
}
/**
* The local bounds of the sprite.
* @type {rendering.Bounds}
*/
get bounds() {
return this._boundsDirty && (this._updateBounds(), this._boundsDirty = !1), this._bounds;
}
/**
* The bounds of the sprite, taking the texture's trim into account.
* @type {rendering.Bounds}
*/
get sourceBounds() {
return this._sourceBoundsDirty && (this._updateSourceBounds(), this._sourceBoundsDirty = !1), this._sourceBounds;
}
/**
* Checks if the object contains the given point.
* @param point - The point to check
*/
containsPoint(t) {
const e = this.sourceBounds;
return t.x >= e.maxX && t.x <= e.minX && t.y >= e.maxY && t.y <= e.minY;
}
/**
* Adds the bounds of this object to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(t) {
const e = this._texture.trim ? this.sourceBounds : this.bounds;
t.addFrame(e.minX, e.minY, e.maxX, e.maxY);
}
onViewUpdate() {
if (this._didChangeId += 4096, this._didSpriteUpdate = !0, this._sourceBoundsDirty = this._boundsDirty = !0, this.didViewUpdate)
return;
this.didViewUpdate = !0;
const t = this.renderGroup || this.parentRenderGroup;
t && t.onChildViewUpdate(this);
}
_updateBounds() {
Ln(this._bounds, this._anchor, this._texture, 0);
}
_updateSourceBounds() {
const t = this._anchor, e = this._texture, s = this._sourceBounds, { width: r, height: n } = e.orig;
s.maxX = -t._x * r, s.minX = s.maxX + r, s.maxY = -t._y * n, s.minY = s.maxY + n;
}
/**
* 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
* @param {boolean} [options.texture=false] - Should it destroy the current texture of the renderable as well
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the renderable as well
*/
destroy(t = !1) {
if (super.destroy(t), typeof t == "boolean" ? t : t == null ? void 0 : t.texture) {
const s = typeof t == "boolean" ? t : t == null ? void 0 : t.textureSource;
this._texture.destroy(s);
}
this._texture = null, this._bounds = null, this._sourceBounds = null, this._anchor = null;
}
/**
* The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
* and passed to the constructor.
*
* The default is `(0,0)`, this means the sprite's origin is the top left.
*
* Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
*
* Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
*
* If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
* @example
* import { Sprite } from 'pixi.js';
*
* const sprite = new Sprite({texture: Texture.WHITE});
* sprite.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
*/
get anchor() {
return this._anchor;
}
set anchor(t) {
typeof t == "number" ? this._anchor.set(t) : this._anchor.copyFrom(t);
}
/**
* Whether or not to round the x/y position of the sprite.
* @type {boolean}
*/
get roundPixels() {
return !!this._roundPixels;
}
set roundPixels(t) {
this._roundPixels = t ? 1 : 0;
}
/** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
get width() {
return Math.abs(this.scale.x) * this._texture.orig.width;
}
set width(t) {
this._setWidth(t, this._texture.orig.width);
}
/** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
get height() {
return Math.abs(this.scale.y) * this._texture.orig.height;
}
set height(t) {
this._setHeight(t, this._texture.orig.height);
}
/**
* Retrieves the size of the Sprite as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the Sprite.
*/
getSize(t) {
return t || (t = {}), t.width = Math.abs(this.scale.x) * this._texture.orig.width, t.height = Math.abs(this.scale.y) * this._texture.orig.height, t;
}
/**
* Sets the size of the Sprite to the specified width and height.
* This is faster than setting the width and height separately.
* @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(t, e) {
let s, r;
typeof t != "object" ? (s = t, r = e ?? t) : (s = t.width, r = t.height ?? t.width), s !== void 0 && this._setWidth(s, this._texture.orig.width), r !== void 0 && this._setHeight(r, this._texture.orig.height);
}
}
const oa = new St();
function br(i, t, e) {
const s = oa;
i.measurable = !0, pr(i, e, s), t.addBoundsMask(s), i.measurable = !1;
}
function wr(i, t, e) {
const s = ne.get();
i.measurable = !0;
const r = Et.get().identity(), n = vr(i, e, r);
gr(i, s, n), i.measurable = !1, t.addBoundsMask(s), Et.return(r), ne.return(s);
}
function vr(i, t, e) {
return i ? (i !== t && (vr(i.parent, t, e), i.updateLocalTransform(), e.append(i.localTransform)), e) : (it("Mask bounds, renderable is not inside the root container"), e);
}
class Ar {
constructor(t) {
this.priority = 0, this.pipe = "alphaMask", t != null && t.mask && this.init(t.mask);
}
init(t) {
this.mask = t, this.renderMaskToTexture = !(t instanceof xt), this.mask.renderable = this.renderMaskToTexture, this.mask.includeInBuild = !this.renderMaskToTexture, this.mask.measurable = !1;
}
reset() {
this.mask.measurable = !0, this.mask = null;
}
addBounds(t, e) {
br(this.mask, t, e);
}
addLocalBounds(t, e) {
wr(this.mask, t, e);
}
containsPoint(t, e) {
const s = this.mask;
return e(s, t);
}
destroy() {
this.reset();
}
static test(t) {
return t instanceof xt;
}
}
Ar.extension = B.MaskEffect;
class Sr {
constructor(t) {
this.priority = 0, this.pipe = "colorMask", t != null && t.mask && this.init(t.mask);
}
init(t) {
this.mask = t;
}
destroy() {
}
static test(t) {
return typeof t == "number";
}
}
Sr.extension = B.MaskEffect;
class Cr {
constructor(t) {
this.priority = 0, this.pipe = "stencilMask", t != null && t.mask && this.init(t.mask);
}
init(t) {
this.mask = t, this.mask.includeInBuild = !1, this.mask.measurable = !1;
}
reset() {
this.mask.measurable = !0, this.mask.includeInBuild = !0, this.mask = null;
}
addBounds(t, e) {
br(this.mask, t, e);
}
addLocalBounds(t, e) {
wr(this.mask, t, e);
}
containsPoint(t, e) {
const s = this.mask;
return e(s, t);
}
destroy() {
this.reset();
}
static test(t) {
return t instanceof O;
}
}
Cr.extension = B.MaskEffect;
const ha = {
createCanvas: (i, t) => {
const e = document.createElement("canvas");
return e.width = i, e.height = t, e;
},
getCanvasRenderingContext2D: () => CanvasRenderingContext2D,
getWebGLRenderingContext: () => WebGLRenderingContext,
getNavigator: () => navigator,
getBaseUrl: () => document.baseURI ?? window.location.href,
getFontFaceSet: () => document.fonts,
fetch: (i, t) => fetch(i, t),
parseXML: (i) => new DOMParser().parseFromString(i, "text/xml")
};
let Ps = ha;
const Y = {
/**
* Returns the current adapter.
* @returns {environment.Adapter} The current adapter.
*/
get() {
return Ps;
},
/**
* Sets the current adapter.
* @param adapter - The new adapter.
*/
set(i) {
Ps = i;
}
};
class Mr extends Ot {
constructor(t) {
t.resource || (t.resource = Y.get().createCanvas()), t.width || (t.width = t.resource.width, t.autoDensity || (t.width /= t.resolution)), t.height || (t.height = t.resource.height, t.autoDensity || (t.height /= t.resolution)), super(t), this.uploadMethodId = "image", this.autoDensity = t.autoDensity;
const e = t.resource;
(this.pixelWidth !== e.width || this.pixelWidth !== e.height) && this.resizeCanvas(), this.transparent = !!t.transparent;
}
resizeCanvas() {
this.autoDensity && (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(t = this.width, e = this.height, s = this._resolution) {
const r = super.resize(t, e, s);
return r && this.resizeCanvas(), r;
}
static test(t) {
return globalThis.HTMLCanvasElement && t instanceof HTMLCanvasElement || globalThis.OffscreenCanvas && t instanceof OffscreenCanvas;
}
}
Mr.extension = B.TextureSource;
class Be extends Ot {
constructor(t) {
if (t.resource && globalThis.HTMLImageElement && t.resource instanceof HTMLImageElement) {
const e = Y.get().createCanvas(t.resource.width, t.resource.height);
e.getContext("2d").drawImage(t.resource, 0, 0), t.resource = e, it("ImageSource: Image element passed, converting to canvas. Use CanvasSource instead.");
}
super(t), this.uploadMethodId = "image", this.autoGarbageCollect = !0;
}
static test(t) {
return globalThis.HTMLImageElement && t instanceof HTMLImageElement || typeof ImageBitmap < "u" && t instanceof ImageBitmap;
}
}
Be.extension = B.TextureSource;
var Te = /* @__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))(Te || {});
class xi {
/**
* 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(t, e = null, s = 0, r = !1) {
this.next = null, this.previous = null, this._destroyed = !1, this._fn = t, this._context = e, this.priority = s, this._once = r;
}
/**
* 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(t, e = null) {
return this._fn === t && this._context === e;
}
/**
* Emit by calling the current function.
* @param ticker - The ticker emitting.
* @returns Next ticker
*/
emit(t) {
this._fn && (this._context ? this._fn.call(this._context, t) : this._fn(t));
const e = this.next;
return this._once && this.destroy(!0), this._destroyed && (this.next = null), e;
}
/**
* Connect to the list.
* @param previous - Input node, previous listener
*/
connect(t) {
this.previous = t, t.next && (t.next.previous = this), this.next = t.next, t.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(t = !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 e = this.next;
return this.next = t ? null : e, this.previous = null, e;
}
}
const Tr = class ht {
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 xi(null, null, 1 / 0), this.deltaMS = 1 / ht.targetFPMS, this.elapsedMS = 1 / ht.targetFPMS, this._tick = (t) => {
this._requestId = null, this.started && (this.update(t), 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.
* @private
*/
_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.
* @private
*/
_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.
* @private
*/
_startIfPossible() {
this.started ? this._requestIfNeeded() : this.autoStart && this.start();
}
/**
* Register a handler for tick events. Calls continuously unless
* it is removed or the ticker is stopped.
* @param fn - The listener function to be added for updates
* @param context - The listener context
* @param {number} [priority=UPDATE_PRIORITY.NORMAL] - The priority for emitting
* @returns This instance of a ticker
*/
add(t, e, s = Te.NORMAL) {
return this._addListener(new xi(t, e, s));
}
/**
* Add a handler for the tick event which is only execute once.
* @param fn - The listener function to be added for one update
* @param context - The listener context
* @param {number} [priority=UPDATE_PRIORITY.NORMAL] - The priority for emitting
* @returns This instance of a ticker
*/
addOnce(t, e, s = Te.NORMAL) {
return this._addListener(new xi(t, e, s, !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(t) {
let e = this._head.next, s = this._head;
if (!e)
t.connect(s);
else {
for (; e; ) {
if (t.priority > e.priority) {
t.connect(s);
break;
}
s = e, e = e.next;
}
t.previous || t.connect(s);
}
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.
* @param fn - The listener function to be removed
* @param context - The listener context to be removed
* @returns This instance of a ticker
*/
remove(t, e) {
let s = this._head.next;
for (; s; )
s.match(t, e) ? s = s.destroy() : s = s.next;
return this._head.next || this._cancelIfNeeded(), this;
}
/**
* The number of listeners on this ticker, calculated by walking through linked list
* @readonly
* @member {number}
*/
get count() {
if (!this._head)
return 0;
let t = 0, e = this._head;
for (; e = e.next; )
t++;
return t;
}
/** Starts the ticker. If the ticker has listeners a new animation frame is requested at this point. */
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. */
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. */
destroy() {
if (!this._protected) {
this.stop();
let t = this._head.next;
for (; t; )
t = t.destroy(!0);
this._head.destroy(), this._head = null;
}
}
/**
* Triggers an update. An update entails setting the
* current {@link ticker.Ticker#elapsedMS|elapsedMS},
* the current {@link ticker.Ticker#deltaTime|deltaTime},
* invoking all listeners with current deltaTime,
* and then finally setting {@link ticker.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.
* @param {number} [currentTime=performance.now()] - the current time of execution
*/
update(t = performance.now()) {
let e;
if (t > this.lastTime) {
if (e = this.elapsedMS = t - this.lastTime, e > this._maxElapsedMS && (e = this._maxElapsedMS), e *= this.speed, this._minElapsedMS) {
const n = t - this._lastFrame | 0;
if (n < this._minElapsedMS)
return;
this._lastFrame = t - n % this._minElapsedMS;
}
this.deltaMS = e, this.deltaTime = this.deltaMS * ht.targetFPMS;
const s = this._head;
let r = s.next;
for (; r; )
r = r.emit(this);
s.next || this._cancelIfNeeded();
} else
this.deltaTime = this.deltaMS = this.elapsedMS = 0;
this.lastTime = t;
}
/**
* 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.Ticker#speed|speed}, which is specific
* to scaling {@link ticker.Ticker#deltaTime|deltaTime}.
* @member {number}
* @readonly
*/
get FPS() {
return 1e3 / this.elapsedMS;
}
/**
* Manages the maximum amount of milliseconds allowed to
* elapse between invoking {@link ticker.Ticker#update|update}.
* This value is used to cap {@link ticker.Ticker#deltaTime|deltaTime},
* but does not effect the measured value of {@link ticker.Ticker#FPS|FPS}.
* When setting this property it is clamped to a value between
* `0` and `Ticker.targetFPMS * 1000`.
* @member {number}
* @default 10
*/
get minFPS() {
return 1e3 / this._maxElapsedMS;
}
set minFPS(t) {
const e = Math.min(this.maxFPS, t), s = Math.min(Math.max(0, e) / 1e3, ht.targetFPMS);
this._maxElapsedMS = 1 / s;
}
/**
* Manages the minimum amount of milliseconds required to
* elapse between invoking {@link ticker.Ticker#update|update}.
* This will effect the measured value of {@link ticker.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`
* @member {number}
* @default 0
*/
get maxFPS() {
return this._minElapsedMS ? Math.round(1e3 / this._minElapsedMS) : 0;
}
set maxFPS(t) {
if (t === 0)
this._minElapsedMS = 0;
else {
const e = Math.max(this.minFPS, t);
this._minElapsedMS = 1 / (e / 1e3);
}
}
/**
* The shared ticker instance used by {@link AnimatedSprite} and by
* {@link VideoResource} 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.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());
* @member {ticker.Ticker}
* @readonly
* @static
*/
static get shared() {
if (!ht._shared) {
const t = ht._shared = new ht();
t.autoStart = !0, t._protected = !0;
}
return ht._shared;
}
/**
* The system ticker instance used by {@link BasePrepare} 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.Ticker#autoStart|autoStart} is set to `true` for this instance.
* @member {ticker.Ticker}
* @readonly
* @static
*/
static get system() {
if (!ht._system) {
const t = ht._system = new ht();
t.autoStart = !0, t._protected = !0;
}
return ht._system;
}
};
Tr.targetFPMS = 0.06;
let ot = Tr, bi;
async function Pr() {
return bi ?? (bi = (async () => {
var a;
const t = document.createElement("canvas").getContext("webgl");
if (!t)
return "premultiply-alpha-on-upload";
const e = await new Promise((o) => {
const h = document.createElement("video");
h.onloadeddata = () => o(h), h.onerror = () => o(null), h.autoplay = !1, h.crossOrigin = "anonymous", h.preload = "auto", h.src = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHTEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggEXTbuMU6uEHFO7a1OsggG97AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQkBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua8yuAQAAAAAAAEPXgQFzxYgAAAAAAAAAAZyBACK1nIN1bmSIgQCGhVZfVlA5g4EBI+ODhAJiWgDglLCBArqBApqBAlPAgQFVsIRVuYEBElTDZ9Vzc9JjwItjxYgAAAAAAAAAAWfInEWjh0VOQ09ERVJEh49MYXZjIGxpYnZweC12cDlnyKJFo4hEVVJBVElPTkSHlDAwOjAwOjAwLjA0MDAwMDAwMAAAH0O2dcfngQCgwqGggQAAAIJJg0IAABAAFgA4JBwYSgAAICAAEb///4r+AAB1oZ2mm+6BAaWWgkmDQgAAEAAWADgkHBhKAAAgIABIQBxTu2uRu4+zgQC3iveBAfGCAXHwgQM=", h.load();
});
if (!e)
return "premultiply-alpha-on-upload";
const s = t.createTexture();
t.bindTexture(t.TEXTURE_2D, s);
const r = t.createFramebuffer();
t.bindFramebuffer(t.FRAMEBUFFER, r), t.framebufferTexture2D(
t.FRAMEBUFFER,
t.COLOR_ATTACHMENT0,
t.TEXTURE_2D,
s,
0
), t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL, t.NONE), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e);
const n = new Uint8Array(4);
return t.readPixels(0, 0, 1, 1, t.RGBA, t.UNSIGNED_BYTE, n), t.deleteFramebuffer(r), t.deleteTexture(s), (a = t.getExtension("WEBGL_lose_context")) == null || a.loseContext(), n[0] <= n[3] ? "premultiplied-alpha" : "premultiply-alpha-on-upload";
})()), bi;
}
const ei = class kr extends Ot {
constructor(t) {
super(t), this.isReady = !1, this.uploadMethodId = "video", t = {
...kr.defaultOptions,
...t
}, this._autoUpdate = !0, this._isConnectedToTicker = !1, this._updateFPS = t.updateFPS || 0, this._msToNextUpdate = 0, this.autoPlay = t.autoPlay !== !1, this.alphaMode = t.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), t.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 t = ot.shared.elapsedMS * this.resource.playbackRate;
this._msToNextUpdate = Math.floor(this._msToNextUpdate - t);
}
(!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<this>} Handle the validate event
*/
async load() {
if (this._load)
return this._load;
const t = this.resource, e = this.options;
return (t.readyState === t.HAVE_ENOUGH_DATA || t.readyState === t.HAVE_FUTURE_DATA) && t.width && t.height && (t.complete = !0), t.addEventListener("play", this._onPlayStart), t.addEventListener("pause", this._onPlayStop), t.addEventListener("seeked", this._onSeeked), this._isSourceReady() ? this._mediaReady() : (e.preload || t.addEventListener("canplay", this._onCanPlay), t.addEventListener("canplaythrough", this._onCanPlayThrough), t.addEventListener("error", this._onError, !0)), this.alphaMode = await Pr(), this._load = new Promise((s, r) => {
this.isValid ? s(this) : (this._resolve = s, this._reject = r, e.preloadTimeoutMs !== void 0 && (this._preloadTimeout = setTimeout(() => {
this._onError(new ErrorEvent(`Preload exceeded timeout of ${e.preloadTimeoutMs}ms`));
})), t.load());
}), this._load;
}
/**
* Handle video error events.
* @param event - The error event
*/
_onError(t) {
this.resource.removeEventListener("error", this._onError, !0), this.emit("error", t), this._reject && (this._reject(t), this._reject = null, this._resolve = null);
}
/**
* Checks if the underlying source is playing.
* @returns True if playing.
*/
_isSourcePlaying() {
const t = this.resource;
return !t.paused && !t.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 t = this.resource;
this.isValid && (this.isReady = !0, this.resize(t.videoWidth, t.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 t = this.resource;
t && (t.removeEventListener("play", this._onPlayStart), t.removeEventListener("pause", this._onPlayStop), t.removeEventListener("seeked", this._onSeeked), t.removeEventListener("canplay", this._onCanPlay), t.removeEventListener("canplaythrough", this._onCanPlayThrough), t.removeEventListener("error", this._onError, !0), t.pause(), t.src = "", t.load()), super.destroy();
}
/** Should the base texture automatically update itself, set to true by default. */
get autoUpdate() {
return this._autoUpdate;
}
set autoUpdate(t) {
t !== this._autoUpdate && (this._autoUpdate = t, 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(t) {
t !== this._updateFPS && (this._updateFPS = t, 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 && (ot.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 || (ot.shared.add(this.updateFrame, this), this._isConnectedToTicker = !0, this._msToNextUpdate = 0)) : (this._videoFrameRequestCallbackHandle !== null && (this.resource.cancelVideoFrameCallback(this._videoFrameRequestCallbackHandle), this._videoFrameRequestCallbackHandle = null), this._isConnectedToTicker && (ot.shared.remove(this.updateFrame, this), this._isConnectedToTicker = !1, this._msToNextUpdate = 0));
}
static test(t) {
return globalThis.HTMLVideoElement && t instanceof HTMLVideoElement || globalThis.VideoFrame && t instanceof VideoFrame;
}
};
ei.extension = B.TextureSource;
ei.defaultOptions = {
...Ot.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
};
ei.MIME_TYPES = {
ogv: "video/ogg",
mov: "video/quicktime",
m4v: "video/mp4"
};
let $e = ei;
const gt = (i, t, e = !1) => (Array.isArray(i) || (i = [i]), t ? i.map((s) => typeof s == "string" || e ? t(s) : s) : i);
class la {
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(t) {
return this._cache.has(t);
}
/**
* Fetch entry by key
* @param key - The key of the entry to get
*/
get(t) {
const e = this._cache.get(t);
return e || it(`[Assets] Asset id ${t} was not found in the Cache`), e;
}
/**
* 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(t, e) {
const s = gt(t);
let r;
for (let h = 0; h < this.parsers.length; h++) {
const c = this.parsers[h];
if (c.test(e)) {
r = c.getCacheableAssets(s, e);
break;
}
}
const n = new Map(Object.entries(r || {}));
r || s.forEach((h) => {
n.set(h, e);
});
const a = [...n.keys()], o = {
cacheKeys: a,
keys: s
};
s.forEach((h) => {
this._cacheMap.set(h, o);
}), a.forEach((h) => {
const c = r ? r[h] : e;
this._cache.has(h) && this._cache.get(h) !== c && it("[Cache] already has key:", h), this._cache.set(h, n.get(h));
});
}
/**
* 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(t) {
if (!this._cacheMap.has(t)) {
it(`[Assets] Asset id ${t} was not found in the Cache`);
return;
}
const e = this._cacheMap.get(t);
e.cacheKeys.forEach((r) => {
this._cache.delete(r);
}), e.keys.forEach((r) => {
this._cacheMap.delete(r);
});
}
/** All loader parsers registered */
get parsers() {
return this._parsers;
}
}
const rt = new la(), Bi = [];
dt.handleByList(B.TextureSource, Bi);
function ca(i = {}) {
const t = i && i.resource, e = t ? i.resource : i, s = t ? i : { resource: i };
for (let r = 0; r < Bi.length; r++) {
const n = Bi[r];
if (n.test(e))
return new n(s);
}
throw new Error(`Could not find a source type for resource: ${s.resource}`);
}
function ua(i = {}, t = !1) {
const e = i && i.resource, s = e ? i.resource : i, r = e ? i : { resource: i };
if (!t && rt.has(s))
return rt.get(s);
const n = new L({ source: ca(r) });
return n.on("destroy", () => {
rt.has(s) && rt.remove(s);
}), t || rt.set(s, n), n;
}
function da(i, t = !1) {
return typeof i == "string" ? rt.get(i) : i instanceof Ot ? new L({ source: i }) : ua(i, t);
}
L.from = da;
dt.add(Ar, Sr, Cr, $e, Be, Mr, $i);
var Zt = /* @__PURE__ */ ((i) => (i[i.Low = 0] = "Low", i[i.Normal = 1] = "Normal", i[i.High = 2] = "High", i))(Zt || {});
function pt(i) {
if (typeof i != "string")
throw new TypeError(`Path must be a string. Received ${JSON.stringify(i)}`);
}
function pe(i) {
return i.split("?")[0].split("#")[0];
}
function fa(i) {
return i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function pa(i, t, e) {
return i.replace(new RegExp(fa(t), "g"), e);
}
function ma(i, t) {
let e = "", s = 0, r = -1, n = 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 (!(r === o - 1 || n === 1))
if (r !== o - 1 && n === 2) {
if (e.length < 2 || s !== 2 || e.charCodeAt(e.length - 1) !== 46 || e.charCodeAt(e.length - 2) !== 46) {
if (e.length > 2) {
const h = e.lastIndexOf("/");
if (h !== e.length - 1) {
h === -1 ? (e = "", s = 0) : (e = e.slice(0, h), s = e.length - 1 - e.lastIndexOf("/")), r = o, n = 0;
continue;
}
} else if (e.length === 2 || e.length === 1) {
e = "", s = 0, r = o, n = 0;
continue;
}
}
} else
e.length > 0 ? e += `/${i.slice(r + 1, o)}` : e = i.slice(r + 1, o), s = o - r - 1;
r = o, n = 0;
} else
a === 46 && n !== -1 ? ++n : n = -1;
}
return e;
}
const bt = {
/**
* Converts a path to posix format.
* @param path - The path to convert to posix
*/
toPosix(i) {
return pa(i, "\\", "/");
},
/**
* Checks if the path is a URL e.g. http://, https://
* @param path - The path to check
*/
isUrl(i) {
return /^https?:/.test(this.toPosix(i));
},
/**
* Checks if the path is a data URL
* @param path - The path to check
*/
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
*/
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
*/
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
*/
getProtocol(i) {
pt(i), i = this.toPosix(i);
const t = /^file:\/\/\//.exec(i);
if (t)
return t[0];
const e = /^[^/:]+:\/{0,2}/.exec(i);
return e ? e[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
*/
toAbsolute(i, t, e) {
if (pt(i), this.isDataUrl(i) || this.isBlobUrl(i))
return i;
const s = pe(this.toPosix(t ?? Y.get().getBaseUrl())), r = pe(this.toPosix(e ?? this.rootname(s)));
return i = this.toPosix(i), i.startsWith("/") ? bt.join(r, i.slice(1)) : this.isAbsolute(i) ? i : this.join(s, i);
},
/**
* Normalizes the given path, resolving '..' and '.' segments
* @param path - The path to normalize
*/
normalize(i) {
if (pt(i), i.length === 0)
return ".";
if (this.isDataUrl(i) || this.isBlobUrl(i))
return i;
i = this.toPosix(i);
let t = "";
const e = i.startsWith("/");
this.hasProtocol(i) && (t = this.rootname(i), i = i.slice(t.length));
const s = i.endsWith("/");
return i = ma(i), i.length > 0 && s && (i += "/"), e ? `/${i}` : t + 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
*/
isAbsolute(i) {
return pt(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
*/
join(...i) {
if (i.length === 0)
return ".";
let t;
for (let e = 0; e < i.length; ++e) {
const s = i[e];
if (pt(s), s.length > 0)
if (t === void 0)
t = s;
else {
const r = i[e - 1] ?? "";
this.joinExtensions.includes(this.extname(r).toLowerCase()) ? t += `/../${s}` : t += `/${s}`;
}
}
return t === void 0 ? "." : this.normalize(t);
},
/**
* Returns the directory name of a path
* @param path - The path to parse
*/
dirname(i) {
if (pt(i), i.length === 0)
return ".";
i = this.toPosix(i);
let t = i.charCodeAt(0);
const e = t === 47;
let s = -1, r = !0;
const n = this.getProtocol(i), a = i;
i = i.slice(n.length);
for (let o = i.length - 1; o >= 1; --o)
if (t = i.charCodeAt(o), t === 47) {
if (!r) {
s = o;
break;
}
} else
r = !1;
return s === -1 ? e ? "/" : this.isUrl(a) ? n + i : n : e && s === 1 ? "//" : n + i.slice(0, s);
},
/**
* Returns the root of the path e.g. /, C:/, file:///, http://domain.com/
* @param path - The path to parse
*/
rootname(i) {
pt(i), i = this.toPosix(i);
let t = "";
if (i.startsWith("/") ? t = "/" : t = this.getProtocol(i), this.isUrl(i)) {
const e = i.indexOf("/", t.length);
e !== -1 ? t = i.slice(0, e) : t = i, t.endsWith("/") || (t += "/");
}
return t;
},
/**
* Returns the last portion of a path
* @param path - The path to test
* @param ext - Optional extension to remove
*/
basename(i, t) {
pt(i), t && pt(t), i = pe(this.toPosix(i));
let e = 0, s = -1, r = !0, n;
if (t !== void 0 && t.length > 0 && t.length <= i.length) {
if (t.length === i.length && t === i)
return "";
let a = t.length - 1, o = -1;
for (n = i.length - 1; n >= 0; --n) {
const h = i.charCodeAt(n);
if (h === 47) {
if (!r) {
e = n + 1;
break;
}
} else
o === -1 && (r = !1, o = n + 1), a >= 0 && (h === t.charCodeAt(a) ? --a === -1 && (s = n) : (a = -1, s = o));
}
return e === s ? s = o : s === -1 && (s = i.length), i.slice(e, s);
}
for (n = i.length - 1; n >= 0; --n)
if (i.charCodeAt(n) === 47) {
if (!r) {
e = n + 1;
break;
}
} else
s === -1 && (r = !1, s = n + 1);
return s === -1 ? "" : i.slice(e, s);
},
/**
* 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
*/
extname(i) {
pt(i), i = pe(this.toPosix(i));
let t = -1, e = 0, s = -1, r = !0, n = 0;
for (let a = i.length - 1; a >= 0; --a) {
const o = i.charCodeAt(a);
if (o === 47) {
if (!r) {
e = a + 1;
break;
}
continue;
}
s === -1 && (r = !1, s = a + 1), o === 46 ? t === -1 ? t = a : n !== 1 && (n = 1) : t !== -1 && (n = -1);
}
return t === -1 || s === -1 || n === 0 || n === 1 && t === s - 1 && t === e + 1 ? "" : i.slice(t, s);
},
/**
* Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties.
* @param path - The path to parse
*/
parse(i) {
pt(i);
const t = { root: "", dir: "", base: "", ext: "", name: "" };
if (i.length === 0)
return t;
i = pe(this.toPosix(i));
let e = i.charCodeAt(0);
const s = this.isAbsolute(i);
let r;
t.root = this.rootname(i), s || this.hasProtocol(i) ? r = 1 : r = 0;
let n = -1, a = 0, o = -1, h = !0, c = i.length - 1, l = 0;
for (; c >= r; --c) {
if (e = i.charCodeAt(c), e === 47) {
if (!h) {
a = c + 1;
break;
}
continue;
}
o === -1 && (h = !1, o = c + 1), e === 46 ? n === -1 ? n = c : l !== 1 && (l = 1) : n !== -1 && (l = -1);
}
return n === -1 || o === -1 || l === 0 || l === 1 && n === o - 1 && n === a + 1 ? o !== -1 && (a === 0 && s ? t.base = t.name = i.slice(1, o) : t.base = t.name = i.slice(a, o)) : (a === 0 && s ? (t.name = i.slice(1, n), t.base = i.slice(1, o)) : (t.name = i.slice(a, n), t.base = i.slice(a, o)), t.ext = i.slice(n, o)), t.dir = this.dirname(i), t;
},
sep: "/",
delimiter: ":",
joinExtensions: [".html"]
};
function Ir(i, t, e, s, r) {
const n = t[e];
for (let a = 0; a < n.length; a++) {
const o = n[a];
e < t.length - 1 ? Ir(i.replace(s[e], o), t, e + 1, s, r) : r.push(i.replace(s[e], o));
}
}
function ga(i) {
const t = /\{(.*?)\}/g, e = i.match(t), s = [];
if (e) {
const r = [];
e.forEach((n) => {
const a = n.substring(1, n.length - 1).split(",");
r.push(a);
}), Ir(i, r, 0, e, s);
} else
s.push(i);
return s;
}
const Ke = (i) => !Array.isArray(i);
class oe {
constructor() {
this._defaultBundleIdentifierOptions = {
connector: "-",
createBundleAssetId: (t, e) => `${t}${this._bundleIdConnector}${e}`,
extractAssetIdFromBundle: (t, e) => e.replace(`${t}${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(t) {
if (this._bundleIdConnector = t.connector ?? this._bundleIdConnector, this._createBundleAssetId = t.createBundleAssetId ?? this._createBundleAssetId, this._extractAssetIdFromBundle = t.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(...t) {
t.forEach((e) => {
this._preferredOrder.push(e), e.priority || (e.priority = Object.keys(e.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(t) {
this._basePath = t;
}
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(t) {
this._rootPath = t;
}
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(t) {
if (typeof t == "string")
this._defaultSearchParams = t;
else {
const e = t;
this._defaultSearchParams = Object.keys(e).map((s) => `${encodeURIComponent(s)}=${encodeURIComponent(e[s])}`).join("&");
}
}
/**
* Returns the aliases for a given asset
* @param asset - the asset to get the aliases for
*/
getAlias(t) {
const { alias: e, src: s } = t;
return gt(
e || s,
(n) => typeof n == "string" ? n : Array.isArray(n) ? n.map((a) => (a == null ? void 0 : a.src) ?? a) : n != null && n.src ? n.src : n,
!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(t) {
this._manifest && it("[Resolver] Manifest already exists, this will be overwritten"), this._manifest = t, t.bundles.forEach((e) => {
this.addBundle(e.name, e.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(t, e) {
const s = [];
let r = e;
Array.isArray(e) || (r = Object.entries(e).map(([n, a]) => typeof a == "string" || Array.isArray(a) ? { alias: n, src: a } : { alias: n, ...a })), r.forEach((n) => {
const a = n.src, o = n.alias;
let h;
if (typeof o == "string") {
const c = this._createBundleAssetId(t, o);
s.push(c), h = [o, c];
} else {
const c = o.map((l) => this._createBundleAssetId(t, l));
s.push(...c), h = [...o, ...c];
}
this.add({
...n,
alias: h,
src: a
});
}), this._bundles[t] = s;
}
/**
* 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(t) {
const e = [];
Array.isArray(t) ? e.push(...t) : e.push(t);
let s;
s = (n) => {
this.hasKey(n) && it(`[Resolver] already has key: ${n} overwriting`);
}, gt(e).forEach((n) => {
const { src: a } = n;
let { data: o, format: h, loadParser: c } = n;
const l = gt(a).map((p) => typeof p == "string" ? ga(p) : Array.isArray(p) ? p : [p]), u = this.getAlias(n);
Array.isArray(u) ? u.forEach(s) : s(u);
const d = [];
l.forEach((p) => {
p.forEach((f) => {
let g = {};
if (typeof f != "object") {
g.src = f;
for (let m = 0; m < this._parsers.length; m++) {
const y = this._parsers[m];
if (y.test(f)) {
g = y.parse(f);
break;
}
}
} else
o = f.data ?? o, h = f.format ?? h, c = f.loadParser ?? c, g = {
...g,
...f
};
if (!u)
throw new Error(`[Resolver] alias is undefined for this asset: ${g.src}`);
g = this._buildResolvedAsset(g, {
aliases: u,
data: o,
format: h,
loadParser: c
}), d.push(g);
});
}), u.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(t) {
const e = Ke(t);
t = gt(t);
const s = {};
return t.forEach((r) => {
const n = this._bundles[r];
if (n) {
const a = this.resolve(n), o = {};
for (const h in a) {
const c = a[h];
o[this._extractAssetIdFromBundle(r, h)] = c;
}
s[r] = o;
}
}), e ? s[t[0]] : s;
}
/**
* 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(t) {
const e = this.resolve(t);
if (typeof t != "string") {
const s = {};
for (const r in e)
s[r] = e[r].src;
return s;
}
return e.src;
}
resolve(t) {
const e = Ke(t);
t = gt(t);
const s = {};
return t.forEach((r) => {
if (!this._resolverHash[r])
if (this._assetMap[r]) {
let n = this._assetMap[r];
const a = this._getPreferredOrder(n);
a == null || a.priority.forEach((o) => {
a.params[o].forEach((h) => {
const c = n.filter((l) => l[o] ? l[o] === h : !1);
c.length && (n = c);
});
}), this._resolverHash[r] = n[0];
} else
this._resolverHash[r] = this._buildResolvedAsset({
alias: [r],
src: r
}, {});
s[r] = this._resolverHash[r];
}), e ? s[t[0]] : s;
}
/**
* Checks if an asset with a given key exists in the resolver
* @param key - The key of the asset
*/
hasKey(t) {
return !!this._assetMap[t];
}
/**
* Checks if a bundle with the given key exists in the resolver
* @param key - The key of the bundle
*/
hasBundle(t) {
return !!this._bundles[t];
}
/**
* Internal function for figuring out what prefer criteria an asset should use.
* @param assets
*/
_getPreferredOrder(t) {
for (let e = 0; e < t.length; e++) {
const s = t[0], r = this._preferredOrder.find((n) => n.params.format.includes(s.format));
if (r)
return r;
}
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(t) {
if (!this._defaultSearchParams)
return t;
const e = /\?/.test(t) ? "&" : "?";
return `${t}${e}${this._defaultSearchParams}`;
}
_buildResolvedAsset(t, e) {
const { aliases: s, data: r, loadParser: n, format: a } = e;
return (this._basePath || this._rootPath) && (t.src = bt.toAbsolute(t.src, this._basePath, this._rootPath)), t.alias = s ?? t.alias ?? [t.src], t.src = this._appendDefaultSearchParams(t.src), t.data = { ...r || {}, ...t.data }, t.loadParser = n ?? t.loadParser, t.format = a ?? t.format ?? ya(t.src), t;
}
}
oe.RETINA_PREFIX = /@([0-9\.]+)x/;
function ya(i) {
return i.split(".").pop().split("?").shift().split("#").shift();
}
const ks = (i, t) => {
const e = t.split("?")[1];
return e && (i += `?${e}`), i;
}, Er = class xe {
/**
* @param texture - Reference to the source BaseTexture object.
* @param {object} data - Spritesheet image data.
*/
constructor(t, e) {
this.linkedSheets = [], this._texture = t instanceof L ? t : null, this.textureSource = t.source, this.textures = {}, this.animations = {}, this.data = e;
const s = parseFloat(e.meta.scale);
s ? (this.resolution = s, t.source.resolution = this.resolution) : this.resolution = t.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((t) => {
this._callback = t, this._batchIndex = 0, this._frameKeys.length <= xe.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(t) {
let e = t;
const s = xe.BATCH_SIZE;
for (; e - t < s && e < this._frameKeys.length; ) {
const r = this._frameKeys[e], n = this._frames[r], a = n.frame;
if (a) {
let o = null, h = null;
const c = n.trimmed !== !1 && n.sourceSize ? n.sourceSize : n.frame, l = new tt(
0,
0,
Math.floor(c.w) / this.resolution,
Math.floor(c.h) / this.resolution
);
n.rotated ? o = new tt(
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 tt(
Math.floor(a.x) / this.resolution,
Math.floor(a.y) / this.resolution,
Math.floor(a.w) / this.resolution,
Math.floor(a.h) / this.resolution
), n.trimmed !== !1 && n.spriteSourceSize && (h = new tt(
Math.floor(n.spriteSourceSize.x) / this.resolution,
Math.floor(n.spriteSourceSize.y) / this.resolution,
Math.floor(a.w) / this.resolution,
Math.floor(a.h) / this.resolution
)), this.textures[r] = new L({
source: this.textureSource,
frame: o,
orig: l,
trim: h,
rotate: n.rotated ? 2 : 0,
defaultAnchor: n.anchor,
defaultBorders: n.borders,
label: r.toString()
});
}
e++;
}
}
/** Parse animations config. */
_processAnimations() {
const t = this.data.animations || {};
for (const e in t) {
this.animations[e] = [];
for (let s = 0; s < t[e].length; s++) {
const r = t[e][s];
this.animations[e].push(this.textures[r]);
}
}
}
/** The parse has completed. */
_parseComplete() {
const t = this._callback;
this._callback = null, this._batchIndex = 0, t.call(this, this.textures);
}
/** Begin the next batch of textures. */
_nextBatch() {
this._processFrames(this._batchIndex * xe.BATCH_SIZE), this._batchIndex++, setTimeout(() => {
this._batchIndex * xe.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(t = !1) {
var e;
for (const s in this.textures)
this.textures[s].destroy();
this._frames = null, this._frameKeys = null, this.data = null, this.textures = null, t && ((e = this._texture) == null || e.destroy(), this.textureSource.destroy()), this._texture = null, this.textureSource = null, this.linkedSheets = [];
}
};
Er.BATCH_SIZE = 1e3;
let Fi = Er;
const _a = [
"jpg",
"png",
"jpeg",
"avif",
"webp",
"basis",
"etc2",
"bc7",
"bc6h",
"bc5",
"bc4",
"bc3",
"bc2",
"bc1",
"eac",
"astc"
];
function Rr(i, t, e) {
const s = {};
if (i.forEach((r) => {
s[r] = t;
}), Object.keys(t.textures).forEach((r) => {
s[r] = t.textures[r];
}), !e) {
const r = bt.dirname(i[0]);
t.linkedSheets.forEach((n, a) => {
const o = Rr([`${r}/${t.data.meta.related_multi_packs[a]}`], n, !0);
Object.assign(s, o);
});
}
return s;
}
const xa = {
extension: B.Asset,
/** Handle the caching of the related Spritesheet Textures */
cache: {
test: (i) => i instanceof Fi,
getCacheableAssets: (i, t) => Rr(i, t, !1)
},
/** Resolve the resolution of the asset. */
resolver: {
test: (i) => {
const e = i.split("?")[0].split("."), s = e.pop(), r = e.pop();
return s === "json" && _a.includes(r);
},
parse: (i) => {
var e;
const t = i.split(".");
return {
resolution: parseFloat(((e = oe.RETINA_PREFIX.exec(i)) == null ? void 0 : e[1]) ?? "1"),
format: t[t.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: {
name: "spritesheetLoader",
extension: {
type: B.LoadParser,
priority: Zt.Normal
},
async testParse(i, t) {
return bt.extname(t.src).toLowerCase() === ".json" && !!i.frames;
},
async parse(i, t, e) {
var c, l;
const {
texture: s,
// if user need to use preloaded texture
imageFilename: r
// if user need to use custom filename (not from jsonFile.meta.image)
} = (t == null ? void 0 : t.data) ?? {};
let n = bt.dirname(t.src);
n && n.lastIndexOf("/") !== n.length - 1 && (n += "/");
let a;
if (s instanceof L)
a = s;
else {
const u = ks(n + (r ?? i.meta.image), t.src);
a = (await e.load([u]))[u];
}
const o = new Fi(
a.source,
i
);
await o.parse();
const h = (c = i == null ? void 0 : i.meta) == null ? void 0 : c.related_multi_packs;
if (Array.isArray(h)) {
const u = [];
for (const p of h) {
if (typeof p != "string")
continue;
let f = n + p;
(l = t.data) != null && l.ignoreMultiPack || (f = ks(f, t.src), u.push(e.load({
src: f,
data: {
ignoreMultiPack: !0
}
})));
}
const d = await Promise.all(u);
o.linkedSheets = d, d.forEach((p) => {
p.linkedSheets = [o].concat(o.linkedSheets.filter((f) => f !== p));
});
}
return o;
},
async unload(i, t, e) {
await e.unload(i.textureSource._sourceOrigin), i.destroy(!1);
}
}
};
dt.add(xa);
let Jt;
function ba() {
return (!Jt || Jt != null && Jt.isContextLost()) && (Jt = Y.get().createCanvas().getContext("webgl", {})), Jt;
}
class wa {
/**
* Create a new instance eof the Bind Group.
* @param resources - The resources that are bound together for use by a shader.
*/
constructor(t) {
this.resources = /* @__PURE__ */ Object.create(null), this._dirty = !0;
let e = 0;
for (const s in t) {
const r = t[s];
this.setResource(r, e++);
}
this._updateKey();
}
/**
* Updates the key if its flagged as dirty. This is used internally to
* match this bind group to a WebGPU BindGroup.
* @internal
* @ignore
*/
_updateKey() {
if (!this._dirty)
return;
this._dirty = !1;
const t = [];
let e = 0;
for (const s in this.resources)
t[e++] = this.resources[s]._resourceId;
this._key = t.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(t, e) {
var r, n;
const s = this.resources[e];
t !== s && (s && ((r = t.off) == null || r.call(t, "change", this.onResourceChange, this)), (n = t.on) == null || n.call(t, "change", this.onResourceChange, this), this.resources[e] = t, 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(t) {
return this.resources[t];
}
/**
* 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
* @ignore
*/
_touch(t) {
const e = this.resources;
for (const s in e)
e[s]._touched = t;
}
/** Destroys this bind group and removes all listeners. */
destroy() {
var e;
const t = this.resources;
for (const s in t) {
const r = t[s];
(e = r.off) == null || e.call(r, "change", this.onResourceChange, this);
}
this.resources = null;
}
onResourceChange(t) {
if (this._dirty = !0, t.destroyed) {
const e = this.resources;
for (const s in e)
e[s] === t && (e[s] = null);
} else
this._updateKey();
}
}
const Li = [];
dt.handleByNamedList(B.Environment, Li);
async function va(i) {
if (i)
for (let t = 0; t < Li.length; t++) {
const e = Li[t];
if (e.value.test()) {
await e.value.load();
return;
}
}
}
let me;
function Aa() {
if (typeof me == "boolean")
return me;
try {
me = new Function("param1", "param2", "param3", "return param1[param2] === param3;")({ a: "b" }, "a", "b") === !0;
} catch {
me = !1;
}
return me;
}
var Ki = { exports: {} };
Ki.exports = ii;
Ki.exports.default = ii;
function ii(i, t, e) {
e = e || 2;
var s = t && t.length, r = s ? t[0] * e : i.length, n = Br(i, 0, r, e, !0), a = [];
if (!n || n.next === n.prev)
return a;
var o, h, c, l, u, d, p;
if (s && (n = Pa(i, t, n, e)), i.length > 80 * e) {
o = c = i[0], h = l = i[1];
for (var f = e; f < r; f += e)
u = i[f], d = i[f + 1], u < o && (o = u), d < h && (h = d), u > c && (c = u), d > l && (l = d);
p = Math.max(c - o, l - h), p = p !== 0 ? 32767 / p : 0;
}
return Pe(n, a, e, o, h, p, 0), a;
}
function Br(i, t, e, s, r) {
var n, a;
if (r === Oi(i, t, e, s) > 0)
for (n = t; n < e; n += s)
a = Is(n, i[n], i[n + 1], a);
else
for (n = e - s; n >= t; n -= s)
a = Is(n, i[n], i[n + 1], a);
return a && si(a, a.next) && (Ie(a), a = a.next), a;
}
function Kt(i, t) {
if (!i)
return i;
t || (t = i);
var e = i, s;
do
if (s = !1, !e.steiner && (si(e, e.next) || W(e.prev, e, e.next) === 0)) {
if (Ie(e), e = t = e.prev, e === e.next)
break;
s = !0;
} else
e = e.next;
while (s || e !== t);
return t;
}
function Pe(i, t, e, s, r, n, a) {
if (i) {
!a && n && Ba(i, s, r, n);
for (var o = i, h, c; i.prev !== i.next; ) {
if (h = i.prev, c = i.next, n ? Ca(i, s, r, n) : Sa(i)) {
t.push(h.i / e | 0), t.push(i.i / e | 0), t.push(c.i / e | 0), Ie(i), i = c.next, o = c.next;
continue;
}
if (i = c, i === o) {
a ? a === 1 ? (i = Ma(Kt(i), t, e), Pe(i, t, e, s, r, n, 2)) : a === 2 && Ta(i, t, e, s, r, n) : Pe(Kt(i), t, e, s, r, n, 1);
break;
}
}
}
}
function Sa(i) {
var t = i.prev, e = i, s = i.next;
if (W(t, e, s) >= 0)
return !1;
for (var r = t.x, n = e.x, a = s.x, o = t.y, h = e.y, c = s.y, l = r < n ? r < a ? r : a : n < a ? n : a, u = o < h ? o < c ? o : c : h < c ? h : c, d = r > n ? r > a ? r : a : n > a ? n : a, p = o > h ? o > c ? o : c : h > c ? h : c, f = s.next; f !== t; ) {
if (f.x >= l && f.x <= d && f.y >= u && f.y <= p && te(r, o, n, h, a, c, f.x, f.y) && W(f.prev, f, f.next) >= 0)
return !1;
f = f.next;
}
return !0;
}
function Ca(i, t, e, s) {
var r = i.prev, n = i, a = i.next;
if (W(r, n, a) >= 0)
return !1;
for (var o = r.x, h = n.x, c = a.x, l = r.y, u = n.y, d = a.y, p = o < h ? o < c ? o : c : h < c ? h : c, f = l < u ? l < d ? l : d : u < d ? u : d, g = o > h ? o > c ? o : c : h > c ? h : c, m = l > u ? l > d ? l : d : u > d ? u : d, y = Di(p, f, t, e, s), _ = Di(g, m, t, e, s), x = i.prevZ, b = i.nextZ; x && x.z >= y && b && b.z <= _; ) {
if (x.x >= p && x.x <= g && x.y >= f && x.y <= m && x !== r && x !== a && te(o, l, h, u, c, d, x.x, x.y) && W(x.prev, x, x.next) >= 0 || (x = x.prevZ, b.x >= p && b.x <= g && b.y >= f && b.y <= m && b !== r && b !== a && te(o, l, h, u, c, d, b.x, b.y) && W(b.prev, b, b.next) >= 0))
return !1;
b = b.nextZ;
}
for (; x && x.z >= y; ) {
if (x.x >= p && x.x <= g && x.y >= f && x.y <= m && x !== r && x !== a && te(o, l, h, u, c, d, x.x, x.y) && W(x.prev, x, x.next) >= 0)
return !1;
x = x.prevZ;
}
for (; b && b.z <= _; ) {
if (b.x >= p && b.x <= g && b.y >= f && b.y <= m && b !== r && b !== a && te(o, l, h, u, c, d, b.x, b.y) && W(b.prev, b, b.next) >= 0)
return !1;
b = b.nextZ;
}
return !0;
}
function Ma(i, t, e) {
var s = i;
do {
var r = s.prev, n = s.next.next;
!si(r, n) && Fr(r, s, s.next, n) && ke(r, n) && ke(n, r) && (t.push(r.i / e | 0), t.push(s.i / e | 0), t.push(n.i / e | 0), Ie(s), Ie(s.next), s = i = n), s = s.next;
} while (s !== i);
return Kt(s);
}
function Ta(i, t, e, s, r, n) {
var a = i;
do {
for (var o = a.next.next; o !== a.prev; ) {
if (a.i !== o.i && Da(a, o)) {
var h = Lr(a, o);
a = Kt(a, a.next), h = Kt(h, h.next), Pe(a, t, e, s, r, n, 0), Pe(h, t, e, s, r, n, 0);
return;
}
o = o.next;
}
a = a.next;
} while (a !== i);
}
function Pa(i, t, e, s) {
var r = [], n, a, o, h, c;
for (n = 0, a = t.length; n < a; n++)
o = t[n] * s, h = n < a - 1 ? t[n + 1] * s : i.length, c = Br(i, o, h, s, !1), c === c.next && (c.steiner = !0), r.push(La(c));
for (r.sort(ka), n = 0; n < r.length; n++)
e = Ia(r[n], e);
return e;
}
function ka(i, t) {
return i.x - t.x;
}
function Ia(i, t) {
var e = Ea(i, t);
if (!e)
return t;
var s = Lr(e, i);
return Kt(s, s.next), Kt(e, e.next);
}
function Ea(i, t) {
var e = t, s = i.x, r = i.y, n = -1 / 0, a;
do {
if (r <= e.y && r >= e.next.y && e.next.y !== e.y) {
var o = e.x + (r - e.y) * (e.next.x - e.x) / (e.next.y - e.y);
if (o <= s && o > n && (n = o, a = e.x < e.next.x ? e : e.next, o === s))
return a;
}
e = e.next;
} while (e !== t);
if (!a)
return null;
var h = a, c = a.x, l = a.y, u = 1 / 0, d;
e = a;
do
s >= e.x && e.x >= c && s !== e.x && te(r < l ? s : n, r, c, l, r < l ? n : s, r, e.x, e.y) && (d = Math.abs(r - e.y) / (s - e.x), ke(e, i) && (d < u || d === u && (e.x > a.x || e.x === a.x && Ra(a, e))) && (a = e, u = d)), e = e.next;
while (e !== h);
return a;
}
function Ra(i, t) {
return W(i.prev, i, t.prev) < 0 && W(t.next, i, i.next) < 0;
}
function Ba(i, t, e, s) {
var r = i;
do
r.z === 0 && (r.z = Di(r.x, r.y, t, e, s)), r.prevZ = r.prev, r.nextZ = r.next, r = r.next;
while (r !== i);
r.prevZ.nextZ = null, r.prevZ = null, Fa(r);
}
function Fa(i) {
var t, e, s, r, n, a, o, h, c = 1;
do {
for (e = i, i = null, n = null, a = 0; e; ) {
for (a++, s = e, o = 0, t = 0; t < c && (o++, s = s.nextZ, !!s); t++)
;
for (h = c; o > 0 || h > 0 && s; )
o !== 0 && (h === 0 || !s || e.z <= s.z) ? (r = e, e = e.nextZ, o--) : (r = s, s = s.nextZ, h--), n ? n.nextZ = r : i = r, r.prevZ = n, n = r;
e = s;
}
n.nextZ = null, c *= 2;
} while (a > 1);
return i;
}
function Di(i, t, e, s, r) {
return i = (i - e) * r | 0, t = (t - s) * r | 0, i = (i | i << 8) & 16711935, i = (i | i << 4) & 252645135, i = (i | i << 2) & 858993459, i = (i | i << 1) & 1431655765, t = (t | t << 8) & 16711935, t = (t | t << 4) & 252645135, t = (t | t << 2) & 858993459, t = (t | t << 1) & 1431655765, i | t << 1;
}
function La(i) {
var t = i, e = i;
do
(t.x < e.x || t.x === e.x && t.y < e.y) && (e = t), t = t.next;
while (t !== i);
return e;
}
function te(i, t, e, s, r, n, a, o) {
return (r - a) * (t - o) >= (i - a) * (n - o) && (i - a) * (s - o) >= (e - a) * (t - o) && (e - a) * (n - o) >= (r - a) * (s - o);
}
function Da(i, t) {
return i.next.i !== t.i && i.prev.i !== t.i && !Ua(i, t) && // dones't intersect other edges
(ke(i, t) && ke(t, i) && Oa(i, t) && // locally visible
(W(i.prev, i, t.prev) || W(i, t.prev, t)) || // does not create opposite-facing sectors
si(i, t) && W(i.prev, i, i.next) > 0 && W(t.prev, t, t.next) > 0);
}
function W(i, t, e) {
return (t.y - i.y) * (e.x - t.x) - (t.x - i.x) * (e.y - t.y);
}
function si(i, t) {
return i.x === t.x && i.y === t.y;
}
function Fr(i, t, e, s) {
var r = We(W(i, t, e)), n = We(W(i, t, s)), a = We(W(e, s, i)), o = We(W(e, s, t));
return !!(r !== n && a !== o || r === 0 && He(i, e, t) || n === 0 && He(i, s, t) || a === 0 && He(e, i, s) || o === 0 && He(e, t, s));
}
function He(i, t, e) {
return t.x <= Math.max(i.x, e.x) && t.x >= Math.min(i.x, e.x) && t.y <= Math.max(i.y, e.y) && t.y >= Math.min(i.y, e.y);
}
function We(i) {
return i > 0 ? 1 : i < 0 ? -1 : 0;
}
function Ua(i, t) {
var e = i;
do {
if (e.i !== i.i && e.next.i !== i.i && e.i !== t.i && e.next.i !== t.i && Fr(e, e.next, i, t))
return !0;
e = e.next;
} while (e !== i);
return !1;
}
function ke(i, t) {
return W(i.prev, i, i.next) < 0 ? W(i, t, i.next) >= 0 && W(i, i.prev, t) >= 0 : W(i, t, i.prev) < 0 || W(i, i.next, t) < 0;
}
function Oa(i, t) {
var e = i, s = !1, r = (i.x + t.x) / 2, n = (i.y + t.y) / 2;
do
e.y > n != e.next.y > n && e.next.y !== e.y && r < (e.next.x - e.x) * (n - e.y) / (e.next.y - e.y) + e.x && (s = !s), e = e.next;
while (e !== i);
return s;
}
function Lr(i, t) {
var e = new Ui(i.i, i.x, i.y), s = new Ui(t.i, t.x, t.y), r = i.next, n = t.prev;
return i.next = t, t.prev = i, e.next = r, r.prev = e, s.next = e, e.prev = s, n.next = s, s.prev = n, s;
}
function Is(i, t, e, s) {
var r = new Ui(i, t, e);
return s ? (r.next = s.next, r.prev = s, s.next.prev = r, s.next = r) : (r.prev = r, r.next = r), r;
}
function Ie(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 Ui(i, t, e) {
this.i = i, this.x = t, this.y = e, this.prev = null, this.next = null, this.z = 0, this.prevZ = null, this.nextZ = null, this.steiner = !1;
}
ii.deviation = function(i, t, e, s) {
var r = t && t.length, n = r ? t[0] * e : i.length, a = Math.abs(Oi(i, 0, n, e));
if (r)
for (var o = 0, h = t.length; o < h; o++) {
var c = t[o] * e, l = o < h - 1 ? t[o + 1] * e : i.length;
a -= Math.abs(Oi(i, c, l, e));
}
var u = 0;
for (o = 0; o < s.length; o += 3) {
var d = s[o] * e, p = s[o + 1] * e, f = s[o + 2] * e;
u += Math.abs(
(i[d] - i[f]) * (i[p + 1] - i[d + 1]) - (i[d] - i[p]) * (i[f + 1] - i[d + 1])
);
}
return a === 0 && u === 0 ? 0 : Math.abs((u - a) / a);
};
function Oi(i, t, e, s) {
for (var r = 0, n = t, a = e - s; n < e; n += s)
r += (i[a] - i[n]) * (i[n + 1] + i[a + 1]), a = n;
return r;
}
ii.flatten = function(i) {
for (var t = i[0][0].length, e = { vertices: [], holes: [], dimensions: t }, s = 0, r = 0; r < i.length; r++) {
for (var n = 0; n < i[r].length; n++)
for (var a = 0; a < t; a++)
e.vertices.push(i[r][n][a]);
r > 0 && (s += i[r - 1].length, e.holes.push(s));
}
return e;
};
var Ga = Ki.exports;
const za = /* @__PURE__ */ Xi(Ga);
var Dr = /* @__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))(Dr || {});
class Ha {
/**
* @param name - The function name that will be executed on the listeners added to this Runner.
*/
constructor(t) {
this.items = [], this._name = t;
}
/* eslint-disable jsdoc/require-param, jsdoc/check-param-names */
/**
* Dispatch/Broadcast Runner to all listeners added to the queue.
* @param {...any} params - (optional) parameters to pass to each listener
*/
/* eslint-enable jsdoc/require-param, jsdoc/check-param-names */
emit(t, e, s, r, n, a, o, h) {
const { name: c, items: l } = this;
for (let u = 0, d = l.length; u < d; u++)
l[u][c](t, e, s, r, n, a, o, h);
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.
*
* ```
* 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(t) {
return t[this._name] && (this.remove(t), this.items.push(t)), this;
}
/**
* Remove a single listener from the dispatch queue.
* @param {any} item - The listener that you would like to remove.
*/
remove(t) {
const e = this.items.indexOf(t);
return e !== -1 && this.items.splice(e, 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(t) {
return this.items.indexOf(t) !== -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 Wa = [
"init",
"destroy",
"contextChange",
"resolutionChange",
"reset",
"renderEnd",
"renderStart",
"render",
"update",
"postrender",
"prerender"
], Ur = class Or extends Bt {
/**
* 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(t) {
super(), this.runners = /* @__PURE__ */ Object.create(null), this.renderPipes = /* @__PURE__ */ Object.create(null), this._initOptions = {}, this._systemsHash = /* @__PURE__ */ Object.create(null), this.type = t.type, this.name = t.name;
const e = [...Wa, ...t.runners ?? []];
this._addRunners(...e), this._addSystems(t.systems), this._addPipes(t.renderPipes, t.renderPipeAdaptors), this._unsafeEvalCheck();
}
/**
* Initialize the renderer.
* @param options - The options to use to create the renderer.
*/
async init(t = {}) {
for (const e in this._systemsHash)
t = { ...this._systemsHash[e].constructor.defaultOptions, ...t };
t = { ...Or.defaultOptions, ...t }, this._roundPixels = t.roundPixels ? 1 : 0;
for (let e = 0; e < this.runners.init.items.length; e++)
await this.runners.init.items[e].init(t);
this._initOptions = t;
}
render(t, e) {
let s = t;
if (s instanceof O && (s = { container: s }, e && (q($, "passing a second argument is deprecated, please use render options instead"), s.target = e.renderTexture)), s.target || (s.target = this.view.renderTarget), s.target === this.view.renderTarget && (this._lastObjectRendered = s.container, s.clearColor = this.background.colorRgba), s.clearColor) {
const r = Array.isArray(s.clearColor) && s.clearColor.length === 4;
s.clearColor = r ? s.clearColor : J.shared.setValue(s.clearColor).toArray();
}
s.transform || (s.container.updateLocalTransform(), s.transform = s.container.localTransform), this.runners.prerender.emit(s), this.runners.renderStart.emit(s), this.runners.render.emit(s), this.runners.renderEnd.emit(s), this.runners.postrender.emit(s);
}
/**
* 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(t, e, s) {
this.view.resize(t, e, s), this.emit("resize", this.view.screen.width, this.view.screen.height);
}
clear(t = {}) {
const e = this;
t.target || (t.target = e.renderTarget.renderTarget), t.clearColor || (t.clearColor = this.background.colorRgba), t.clear ?? (t.clear = Dr.ALL);
const { clear: s, clearColor: r, target: n } = t;
J.shared.setValue(r ?? this.background.colorRgba), e.renderTarget.clear(n, s, J.shared.toArray());
}
/** The resolution / device pixel ratio of the renderer. */
get resolution() {
return this.view.resolution;
}
set resolution(t) {
this.view.resolution = t, this.runners.resolutionChange.emit(t);
}
/**
* Same as view.width, actual number of pixels in the canvas by horizontal.
* @member {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(...t) {
t.forEach((e) => {
this.runners[e] = new Ha(e);
});
}
_addSystems(t) {
let e;
for (e in t) {
const s = t[e];
this._addSystem(s.value, s.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(t, e) {
const s = new t(this);
if (this[e])
throw new Error(`Whoops! The name "${e}" is already in use`);
this[e] = s, this._systemsHash[e] = s;
for (const r in this.runners)
this.runners[r].add(s);
return this;
}
_addPipes(t, e) {
const s = e.reduce((r, n) => (r[n.name] = n.value, r), {});
t.forEach((r) => {
const n = r.value, a = r.name, o = s[a];
this.renderPipes[a] = new n(
this,
o ? new o() : null
);
});
}
destroy(t = !1) {
this.runners.destroy.items.reverse(), this.runners.destroy.emit(t), Object.values(this.runners).forEach((e) => {
e.destroy();
}), this._systemsHash = null, this.renderPipes = null;
}
/**
* Generate a texture from a container.
* @param options - options or container target to use when generating the texture
* @returns a texture
*/
generateTexture(t) {
return this.textureGenerator.generateTexture(t);
}
/**
* 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;
}
/**
* Overrideable function by `pixi.js/unsafe-eval` to silence
* throwing an error if platform doesn't support unsafe-evals.
* @private
* @ignore
*/
_unsafeEvalCheck() {
if (!Aa())
throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
}
};
Ur.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 Gr = Ur, Ne;
function Na(i) {
return Ne !== void 0 || (Ne = (() => {
var e;
const t = {
stencil: !0,
failIfMajorPerformanceCaveat: i ?? Gr.defaultOptions.failIfMajorPerformanceCaveat
};
try {
if (!Y.get().getWebGLRenderingContext())
return !1;
let r = Y.get().createCanvas().getContext("webgl", t);
const n = !!((e = r == null ? void 0 : r.getContextAttributes()) != null && e.stencil);
if (r) {
const a = r.getExtension("WEBGL_lose_context");
a && a.loseContext();
}
return r = null, n;
} catch {
return !1;
}
})()), Ne;
}
let Ye;
async function Ya(i = {}) {
return Ye !== void 0 || (Ye = await (async () => {
if (!Y.get().getNavigator().gpu)
return !1;
try {
return await (await navigator.gpu.requestAdapter(i)).requestDevice(), !0;
} catch {
return !1;
}
})()), Ye;
}
const Es = ["webgl", "webgpu", "canvas"];
async function Va(i) {
let t = [];
i.preference ? (t.push(i.preference), Es.forEach((n) => {
n !== i.preference && t.push(n);
})) : t = Es.slice();
let e;
await va(
i.manageImports ?? !0
);
let s = {};
for (let n = 0; n < t.length; n++) {
const a = t[n];
if (a === "webgpu" && await Ya()) {
const { WebGPURenderer: o } = await import("./WebGPURenderer-CtFHd2D-.js");
e = o, s = { ...i, ...i.webgpu };
break;
} else if (a === "webgl" && Na(
i.failIfMajorPerformanceCaveat ?? Gr.defaultOptions.failIfMajorPerformanceCaveat
)) {
const { WebGLRenderer: o } = await import("./WebGLRenderer-C-mXrQNx.js");
e = o, s = { ...i, ...i.webgl };
break;
} else if (a === "canvas")
throw s = { ...i }, new Error("CanvasRenderer is not yet implemented");
}
if (delete s.webgpu, delete s.webgl, !e)
throw new Error("No available renderer for the current environment");
const r = new e();
return await r.init(s), r;
}
class ja {
/**
* @param loader
* @param verbose - should the loader log to the console
*/
constructor(t, e = !1) {
this._loader = t, this._assetList = [], this._isLoading = !1, this._maxConcurrent = 1, this.verbose = e;
}
/**
* Adds an array of assets to load.
* @param assetUrls - assets to load
*/
add(t) {
t.forEach((e) => {
this._assetList.push(e);
}), this.verbose && console.log("[BackgroundLoader] assets: ", this._assetList), this._isActive && !this._isLoading && this._next();
}
/**
* Loads the next set of assets. Will try to load as many assets as it can at the same time.
*
* The max assets it will try to load at one time will be 4.
*/
async _next() {
if (this._assetList.length && this._isActive) {
this._isLoading = !0;
const t = [], e = Math.min(this._assetList.length, this._maxConcurrent);
for (let s = 0; s < e; s++)
t.push(this._assetList.pop());
await this._loader.load(t), this._isLoading = !1, this._next();
}
}
/**
* Activate/Deactivate the loading. If set to true then it will immediately continue to load the next asset.
* @returns whether the class is active
*/
get active() {
return this._isActive;
}
set active(t) {
this._isActive !== t && (this._isActive = t, t && !this._isLoading && this._next());
}
}
const Xa = {
extension: B.CacheParser,
test: (i) => Array.isArray(i) && i.every((t) => t instanceof L),
getCacheableAssets: (i, t) => {
const e = {};
return i.forEach((s) => {
t.forEach((r, n) => {
e[s + (n === 0 ? "" : n + 1)] = r;
});
}), e;
}
};
async function zr(i) {
if ("Image" in globalThis)
return new Promise((t) => {
const e = new Image();
e.onload = () => {
t(!0);
}, e.onerror = () => {
t(!1);
}, e.src = i;
});
if ("createImageBitmap" in globalThis && "fetch" in globalThis) {
try {
const t = await (await fetch(i)).blob();
await createImageBitmap(t);
} catch {
return !1;
}
return !0;
}
return !1;
}
const $a = {
extension: {
type: B.DetectionParser,
priority: 1
},
test: async () => zr(
// eslint-disable-next-line max-len
"data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
),
add: async (i) => [...i, "avif"],
remove: async (i) => i.filter((t) => t !== "avif")
}, Rs = ["png", "jpg", "jpeg"], qa = {
extension: {
type: B.DetectionParser,
priority: -1
},
test: () => Promise.resolve(!0),
add: async (i) => [...i, ...Rs],
remove: async (i) => i.filter((t) => !Rs.includes(t))
}, Ka = "WorkerGlobalScope" in globalThis && globalThis instanceof globalThis.WorkerGlobalScope;
function Zi(i) {
return Ka ? !1 : document.createElement("video").canPlayType(i) !== "";
}
const Za = {
extension: {
type: B.DetectionParser,
priority: 0
},
test: async () => Zi("video/mp4"),
add: async (i) => [...i, "mp4", "m4v"],
remove: async (i) => i.filter((t) => t !== "mp4" && t !== "m4v")
}, Ja = {
extension: {
type: B.DetectionParser,
priority: 0
},
test: async () => Zi("video/ogg"),
add: async (i) => [...i, "ogv"],
remove: async (i) => i.filter((t) => t !== "ogv")
}, Qa = {
extension: {
type: B.DetectionParser,
priority: 0
},
test: async () => Zi("video/webm"),
add: async (i) => [...i, "webm"],
remove: async (i) => i.filter((t) => t !== "webm")
}, to = {
extension: {
type: B.DetectionParser,
priority: 0
},
test: async () => zr(
"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA="
),
add: async (i) => [...i, "webp"],
remove: async (i) => i.filter((t) => t !== "webp")
};
class eo {
constructor() {
this._parsers = [], this._parsersValidated = !1, this.parsers = new Proxy(this._parsers, {
set: (t, e, s) => (this._parsersValidated = !1, t[e] = s, !0)
}), this.promiseCache = {};
}
/** function used for testing */
reset() {
this._parsersValidated = !1, this.promiseCache = {};
}
/**
* Used internally to generate a promise for the asset to be loaded.
* @param url - The URL to be loaded
* @param data - any custom additional information relevant to the asset being loaded
* @returns - a promise that will resolve to an Asset for example a Texture of a JSON object
*/
_getLoadPromiseAndParser(t, e) {
const s = {
promise: null,
parser: null
};
return s.promise = (async () => {
var a, o;
let r = null, n = null;
if (e.loadParser && (n = this._parserHash[e.loadParser], n || it(`[Assets] specified load parser "${e.loadParser}" not found while loading ${t}`)), !n) {
for (let h = 0; h < this.parsers.length; h++) {
const c = this.parsers[h];
if (c.load && ((a = c.test) != null && a.call(c, t, e, this))) {
n = c;
break;
}
}
if (!n)
return it(`[Assets] ${t} could not be loaded as we don't know how to parse it, ensure the correct parser has been added`), null;
}
r = await n.load(t, e, this), s.parser = n;
for (let h = 0; h < this.parsers.length; h++) {
const c = this.parsers[h];
c.parse && c.parse && await ((o = c.testParse) == null ? void 0 : o.call(c, r, e, this)) && (r = await c.parse(r, e, this) || r, s.parser = c);
}
return r;
})(), s;
}
async load(t, e) {
this._parsersValidated || this._validateParsers();
let s = 0;
const r = {}, n = Ke(t), a = gt(t, (c) => ({
alias: [c],
src: c
})), o = a.length, h = a.map(async (c) => {
const l = bt.toAbsolute(c.src);
if (!r[c.src])
try {
this.promiseCache[l] || (this.promiseCache[l] = this._getLoadPromiseAndParser(l, c)), r[c.src] = await this.promiseCache[l].promise, e && e(++s / o);
} catch (u) {
throw delete this.promiseCache[l], delete r[c.src], new Error(`[Loader.load] Failed to load ${l}.
${u}`);
}
});
return await Promise.all(h), n ? r[a[0].src] : r;
}
/**
* Unloads one or more assets. Any unloaded assets will be destroyed, freeing up memory for your app.
* The parser that created the asset, will be the one that unloads it.
* @example
* // Single asset:
* const asset = await Loader.load('cool.png');
*
* await Loader.unload('cool.png');
*
* console.log(asset.destroyed); // true
* @param assetsToUnloadIn - urls that you want to unload, or a single one!
*/
async unload(t) {
const s = gt(t, (r) => ({
alias: [r],
src: r
})).map(async (r) => {
var o, h;
const n = bt.toAbsolute(r.src), a = this.promiseCache[n];
if (a) {
const c = await a.promise;
delete this.promiseCache[n], await ((h = (o = a.parser) == null ? void 0 : o.unload) == null ? void 0 : h.call(o, c, r, this));
}
});
await Promise.all(s);
}
/** validates our parsers, right now it only checks for name conflicts but we can add more here as required! */
_validateParsers() {
this._parsersValidated = !0, this._parserHash = this._parsers.filter((t) => t.name).reduce((t, e) => (e.name ? t[e.name] && it(`[Assets] loadParser name conflict "${e.name}"`) : it("[Assets] loadParser should have a name"), { ...t, [e.name]: e }), {});
}
}
function he(i, t) {
if (Array.isArray(t)) {
for (const e of t)
if (i.startsWith(`data:${e}`))
return !0;
return !1;
}
return i.startsWith(`data:${t}`);
}
function le(i, t) {
const e = i.split("?")[0], s = bt.extname(e).toLowerCase();
return Array.isArray(t) ? t.includes(s) : s === t;
}
const io = ".json", so = "application/json", ro = {
extension: {
type: B.LoadParser,
priority: Zt.Low
},
name: "loadJson",
test(i) {
return he(i, so) || le(i, io);
},
async load(i) {
return await (await Y.get().fetch(i)).json();
}
}, no = ".txt", ao = "text/plain", oo = {
name: "loadTxt",
extension: {
type: B.LoadParser,
priority: Zt.Low
},
test(i) {
return he(i, ao) || le(i, no);
},
async load(i) {
return await (await Y.get().fetch(i)).text();
}
}, ho = [
"normal",
"bold",
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900"
], lo = [".ttf", ".otf", ".woff", ".woff2"], co = [
"font/ttf",
"font/otf",
"font/woff",
"font/woff2"
], uo = /^(--|-?[A-Z_])[0-9A-Z_-]*$/i;
function fo(i) {
const t = bt.extname(i), r = bt.basename(i, t).replace(/(-|_)/g, " ").toLowerCase().split(" ").map((o) => o.charAt(0).toUpperCase() + o.slice(1));
let n = r.length > 0;
for (const o of r)
if (!o.match(uo)) {
n = !1;
break;
}
let a = r.join(" ");
return n || (a = `"${a.replace(/[\\"]/g, "\\$&")}"`), a;
}
const po = /^[0-9A-Za-z%:/?#\[\]@!\$&'()\*\+,;=\-._~]*$/;
function mo(i) {
return po.test(i) ? i : encodeURI(i);
}
const go = {
extension: {
type: B.LoadParser,
priority: Zt.Low
},
name: "loadWebFont",
test(i) {
return he(i, co) || le(i, lo);
},
async load(i, t) {
var s, r, n;
const e = Y.get().getFontFaceSet();
if (e) {
const a = [], o = ((s = t.data) == null ? void 0 : s.family) ?? fo(i), h = ((n = (r = t.data) == null ? void 0 : r.weights) == null ? void 0 : n.filter((l) => ho.includes(l))) ?? ["normal"], c = t.data ?? {};
for (let l = 0; l < h.length; l++) {
const u = h[l], d = new FontFace(o, `url(${mo(i)})`, {
...c,
weight: u
});
await d.load(), e.add(d), a.push(d);
}
return rt.set(`${o}-and-url`, {
url: i,
fontFaces: a
}), a.length === 1 ? a[0] : a;
}
return it("[loadWebFont] FontFace API is not supported. Skipping loading font"), null;
},
unload(i) {
(Array.isArray(i) ? i : [i]).forEach((t) => {
rt.remove(t.family), Y.get().getFontFaceSet().delete(t);
});
}
};
var yo = xo, wi = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }, _o = /([astvzqmhlc])([^astvzqmhlc]*)/ig;
function xo(i) {
var t = [];
return i.replace(_o, function(e, s, r) {
var n = s.toLowerCase();
for (r = wo(r), n == "m" && r.length > 2 && (t.push([s].concat(r.splice(0, 2))), n = "l", s = s == "m" ? "l" : "L"); ; ) {
if (r.length == wi[n])
return r.unshift(s), t.push(r);
if (r.length < wi[n])
throw new Error("malformed path data");
t.push([s].concat(r.splice(0, wi[n])));
}
}), t;
}
var bo = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig;
function wo(i) {
var t = i.match(bo);
return t ? t.map(Number) : [];
}
const vo = /* @__PURE__ */ Xi(yo);
function Ao(i, t) {
const e = vo(i), s = [];
let r = null, n = 0, a = 0;
for (let o = 0; o < e.length; o++) {
const h = e[o], c = h[0], l = h;
switch (c) {
case "M":
n = l[1], a = l[2], t.moveTo(n, a);
break;
case "m":
n += l[1], a += l[2], t.moveTo(n, a);
break;
case "H":
n = l[1], t.lineTo(n, a);
break;
case "h":
n += l[1], t.lineTo(n, a);
break;
case "V":
a = l[1], t.lineTo(n, a);
break;
case "v":
a += l[1], t.lineTo(n, a);
break;
case "L":
n = l[1], a = l[2], t.lineTo(n, a);
break;
case "l":
n += l[1], a += l[2], t.lineTo(n, a);
break;
case "C":
n = l[5], a = l[6], t.bezierCurveTo(
l[1],
l[2],
l[3],
l[4],
n,
a
);
break;
case "c":
t.bezierCurveTo(
n + l[1],
a + l[2],
n + l[3],
a + l[4],
n + l[5],
a + l[6]
), n += l[5], a += l[6];
break;
case "S":
n = l[3], a = l[4], t.bezierCurveToShort(
l[1],
l[2],
n,
a
);
break;
case "s":
t.bezierCurveToShort(
n + l[1],
a + l[2],
n + l[3],
a + l[4]
), n += l[3], a += l[4];
break;
case "Q":
n = l[3], a = l[4], t.quadraticCurveTo(
l[1],
l[2],
n,
a
);
break;
case "q":
t.quadraticCurveTo(
n + l[1],
a + l[2],
n + l[3],
a + l[4]
), n += l[3], a += l[4];
break;
case "T":
n = l[1], a = l[2], t.quadraticCurveToShort(
n,
a
);
break;
case "t":
n += l[1], a += l[2], t.quadraticCurveToShort(
n,
a
);
break;
case "A":
n = l[6], a = l[7], t.arcToSvg(
l[1],
l[2],
l[3],
l[4],
l[5],
n,
a
);
break;
case "a":
n += l[6], a += l[7], t.arcToSvg(
l[1],
l[2],
l[3],
l[4],
l[5],
n,
a
);
break;
case "Z":
case "z":
t.closePath(), s.length > 0 && (r = s.pop(), r ? (n = r.startX, a = r.startY) : (n = 0, a = 0)), r = null;
break;
default:
it(`Unknown SVG path command: ${c}`);
}
c !== "Z" && c !== "z" && r === null && (r = { startX: n, startY: a }, s.push(r));
}
return t;
}
class Ji {
/**
* @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(t = 0, e = 0, s = 0) {
this.type = "circle", this.x = t, this.y = e, this.radius = s;
}
/**
* Creates a clone of this Circle instance
* @returns A copy of the Circle
*/
clone() {
return new Ji(this.x, this.y, this.radius);
}
/**
* Checks whether the x and y coordinates given are contained within this 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
*/
contains(t, e) {
if (this.radius <= 0)
return !1;
const s = this.radius * this.radius;
let r = this.x - t, n = this.y - e;
return r *= r, n *= n, r + n <= s;
}
/**
* Checks whether the x and y coordinates given are contained within this circle including the stroke.
* @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
* @returns Whether the x/y coordinates are within this Circle
*/
strokeContains(t, e, s) {
if (this.radius === 0)
return !1;
const r = this.x - t, n = this.y - e, a = this.radius, o = s / 2, h = Math.sqrt(r * r + n * n);
return h < a + o && h > a - o;
}
/**
* Returns the framing rectangle of the circle as a Rectangle object
* @param out
* @returns The framing rectangle
*/
getBounds(t) {
return t = t || new tt(), t.x = this.x - this.radius, t.y = this.y - this.radius, t.width = this.radius * 2, t.height = this.radius * 2, t;
}
/**
* Copies another circle to this one.
* @param circle - The circle to copy from.
* @returns Returns itself.
*/
copyFrom(t) {
return this.x = t.x, this.y = t.y, this.radius = t.radius, this;
}
/**
* Copies this circle to another one.
* @param circle - The circle to copy to.
* @returns Returns given parameter.
*/
copyTo(t) {
return t.copyFrom(this), t;
}
toString() {
return `[pixi.js/math:Circle x=${this.x} y=${this.y} radius=${this.radius}]`;
}
}
class Qi {
/**
* @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(t = 0, e = 0, s = 0, r = 0) {
this.type = "ellipse", this.x = t, this.y = e, this.halfWidth = s, this.halfHeight = r;
}
/**
* Creates a clone of this Ellipse instance
* @returns {Ellipse} A copy of the ellipse
*/
clone() {
return new Qi(this.x, this.y, this.halfWidth, this.halfHeight);
}
/**
* Checks whether the x and y coordinates given are contained within this ellipse
* @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
*/
contains(t, e) {
if (this.halfWidth <= 0 || this.halfHeight <= 0)
return !1;
let s = (t - this.x) / this.halfWidth, r = (e - this.y) / this.halfHeight;
return s *= s, r *= r, s + r <= 1;
}
/**
* Checks whether the x and y coordinates given are contained within this ellipse including stroke
* @param x - The X coordinate of the point to test
* @param y - The Y coordinate of the point to test
* @param width
* @returns Whether the x/y coords are within this ellipse
*/
strokeContains(t, e, s) {
const { halfWidth: r, halfHeight: n } = this;
if (r <= 0 || n <= 0)
return !1;
const a = s / 2, o = r - a, h = n - a, c = r + a, l = n + a, u = t - this.x, d = e - this.y, p = u * u / (o * o) + d * d / (h * h), f = u * u / (c * c) + d * d / (l * l);
return p > 1 && f <= 1;
}
/**
* Returns the framing rectangle of the ellipse as a Rectangle object
* @returns The framing rectangle
*/
getBounds() {
return new tt(this.x - this.halfWidth, this.y - this.halfHeight, this.halfWidth * 2, this.halfHeight * 2);
}
/**
* Copies another ellipse to this one.
* @param ellipse - The ellipse to copy from.
* @returns Returns itself.
*/
copyFrom(t) {
return this.x = t.x, this.y = t.y, this.halfWidth = t.halfWidth, this.halfHeight = t.halfHeight, this;
}
/**
* Copies this ellipse to another one.
* @param ellipse - The ellipse to copy to.
* @returns Returns given parameter.
*/
copyTo(t) {
return t.copyFrom(this), t;
}
toString() {
return `[pixi.js/math:Ellipse x=${this.x} y=${this.y} halfWidth=${this.halfWidth} halfHeight=${this.halfHeight}]`;
}
}
function So(i, t, e, s, r, n) {
const a = i - e, o = t - s, h = r - e, c = n - s, l = a * h + o * c, u = h * h + c * c;
let d = -1;
u !== 0 && (d = l / u);
let p, f;
d < 0 ? (p = e, f = s) : d > 1 ? (p = r, f = n) : (p = e + d * h, f = s + d * c);
const g = i - p, m = t - f;
return g * g + m * m;
}
class Se {
/**
* @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(...t) {
this.type = "polygon";
let e = Array.isArray(t[0]) ? t[0] : t;
if (typeof e[0] != "number") {
const s = [];
for (let r = 0, n = e.length; r < n; r++)
s.push(e[r].x, e[r].y);
e = s;
}
this.points = e, this.closePath = !0;
}
/**
* Creates a clone of this polygon.
* @returns - A copy of the polygon.
*/
clone() {
const t = this.points.slice(), e = new Se(t);
return e.closePath = this.closePath, e;
}
/**
* Checks whether the x and y coordinates passed to this function are contained within this polygon.
* @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.
*/
contains(t, e) {
let s = !1;
const r = this.points.length / 2;
for (let n = 0, a = r - 1; n < r; a = n++) {
const o = this.points[n * 2], h = this.points[n * 2 + 1], c = this.points[a * 2], l = this.points[a * 2 + 1];
h > e != l > e && t < (c - o) * ((e - h) / (l - h)) + o && (s = !s);
}
return s;
}
/**
* Checks whether the x and y coordinates given are contained within this polygon including the stroke.
* @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
* @returns Whether the x/y coordinates are within this polygon
*/
strokeContains(t, e, s) {
const r = s / 2, n = r * r, { points: a } = this, o = a.length - (this.closePath ? 0 : 2);
for (let h = 0; h < o; h += 2) {
const c = a[h], l = a[h + 1], u = a[(h + 2) % a.length], d = a[(h + 3) % a.length];
if (So(t, e, c, l, u, d) <= n)
return !0;
}
return !1;
}
/**
* Returns the framing rectangle of the polygon as a Rectangle object
* @param out - optional rectangle to store the result
* @returns The framing rectangle
*/
getBounds(t) {
t = t || new tt();
const e = this.points;
let s = 1 / 0, r = -1 / 0, n = 1 / 0, a = -1 / 0;
for (let o = 0, h = e.length; o < h; o += 2) {
const c = e[o], l = e[o + 1];
s = c < s ? c : s, r = c > r ? c : r, n = l < n ? l : n, a = l > a ? l : a;
}
return t.x = s, t.width = r - s, t.y = n, t.height = a - n, t;
}
/**
* Copies another polygon to this one.
* @param polygon - The polygon to copy from.
* @returns Returns itself.
*/
copyFrom(t) {
return this.points = t.points.slice(), this.closePath = t.closePath, this;
}
/**
* Copies this polygon to another one.
* @param polygon - The polygon to copy to.
* @returns Returns given parameter.
*/
copyTo(t) {
return t.copyFrom(this), t;
}
toString() {
return `[pixi.js/math:PolygoncloseStroke=${this.closePath}points=${this.points.reduce((t, e) => `${t}, ${e}`, "")}]`;
}
/**
* Get the last X coordinate of the polygon
* @readonly
*/
get lastX() {
return this.points[this.points.length - 2];
}
/**
* Get the last Y coordinate of the polygon
* @readonly
*/
get lastY() {
return this.points[this.points.length - 1];
}
/**
* Get the first X coordinate of the polygon
* @readonly
*/
get x() {
return this.points[this.points.length - 2];
}
/**
* Get the first Y coordinate of the polygon
* @readonly
*/
get y() {
return this.points[this.points.length - 1];
}
}
const Ve = (i, t, e, s, r, n) => {
const a = i - e, o = t - s, h = Math.sqrt(a * a + o * o);
return h >= r - n && h <= r + n;
};
class ts {
/**
* @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(t = 0, e = 0, s = 0, r = 0, n = 20) {
this.type = "roundedRectangle", this.x = t, this.y = e, this.width = s, this.height = r, this.radius = n;
}
/**
* Returns the framing rectangle of the rounded rectangle as a Rectangle object
* @param out - optional rectangle to store the result
* @returns The framing rectangle
*/
getBounds(t) {
return t = t || new tt(), t.x = this.x, t.y = this.y, t.width = this.width, t.height = this.height, t;
}
/**
* Creates a clone of this Rounded Rectangle.
* @returns - A copy of the rounded rectangle.
*/
clone() {
return new ts(this.x, this.y, this.width, this.height, this.radius);
}
/**
* Copies another rectangle to this one.
* @param rectangle - The rectangle to copy from.
* @returns Returns itself.
*/
copyFrom(t) {
return this.x = t.x, this.y = t.y, this.width = t.width, this.height = t.height, this;
}
/**
* Copies this rectangle to another one.
* @param rectangle - The rectangle to copy to.
* @returns Returns given parameter.
*/
copyTo(t) {
return t.copyFrom(this), t;
}
/**
* Checks whether the x and y coordinates given are contained within this Rounded Rectangle
* @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.
*/
contains(t, e) {
if (this.width <= 0 || this.height <= 0)
return !1;
if (t >= this.x && t <= this.x + this.width && e >= this.y && e <= this.y + this.height) {
const s = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2));
if (e >= this.y + s && e <= this.y + this.height - s || t >= this.x + s && t <= this.x + this.width - s)
return !0;
let r = t - (this.x + s), n = e - (this.y + s);
const a = s * s;
if (r * r + n * n <= a || (r = t - (this.x + this.width - s), r * r + n * n <= a) || (n = e - (this.y + this.height - s), r * r + n * n <= a) || (r = t - (this.x + s), r * r + n * n <= a))
return !0;
}
return !1;
}
/**
* Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
* @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
* @returns Whether the x/y coordinates are within this rectangle
*/
strokeContains(t, e, s) {
const { x: r, y: n, width: a, height: o, radius: h } = this, c = s / 2, l = r + h, u = n + h, d = a - h * 2, p = o - h * 2, f = r + a, g = n + o;
return (t >= r - c && t <= r + c || t >= f - c && t <= f + c) && e >= u && e <= u + p || (e >= n - c && e <= n + c || e >= g - c && e <= g + c) && t >= l && t <= l + d ? !0 : (
// Top-left
t < l && e < u && Ve(t, e, l, u, h, c) || t > f - h && e < u && Ve(t, e, f - h, u, h, c) || t > f - h && e > g - h && Ve(t, e, f - h, g - h, h, c) || t < l && e > g - h && Ve(t, e, l, g - h, h, c)
);
}
toString() {
return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`;
}
}
var at = /* @__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))(at || {});
class Ee extends Bt {
/**
* Creates a new Buffer with the given options
* @param options - the options for the buffer
*/
constructor(t) {
let { data: e, size: s } = t;
const { usage: r, label: n, shrinkToFit: a } = t;
super(), this.uid = et("buffer"), this._resourceType = "buffer", this._resourceId = et("resource"), this._touched = 0, this._updateID = 1, this.shrinkToFit = !0, this.destroyed = !1, e instanceof Array && (e = new Float32Array(e)), this._data = e, s = s ?? (e == null ? void 0 : e.byteLength);
const o = !!e;
this.descriptor = {
size: s,
usage: r,
mappedAtCreation: o,
label: n
}, this.shrinkToFit = a ?? !0;
}
/** the data in the buffer */
get data() {
return this._data;
}
set data(t) {
this.setDataWithSize(t, t.length, !0);
}
/** whether the buffer is static or not */
get static() {
return !!(this.descriptor.usage & at.STATIC);
}
set static(t) {
t ? this.descriptor.usage |= at.STATIC : this.descriptor.usage &= ~at.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(t, e, s) {
if (this._updateID++, this._updateSize = e * t.BYTES_PER_ELEMENT, this._data === t) {
s && this.emit("update", this);
return;
}
const r = this._data;
if (this._data = t, r.length !== t.length) {
!this.shrinkToFit && t.byteLength < r.byteLength ? s && this.emit("update", this) : (this.descriptor.size = t.byteLength, this._resourceId = et("resource"), this.emit("change", this));
return;
}
s && 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(t) {
this._updateSize = t ?? 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 Hr(i, t) {
if (!(i instanceof Ee)) {
let e = t ? at.INDEX : at.VERTEX;
i instanceof Array && (t ? (i = new Uint32Array(i), e = at.INDEX | at.COPY_DST) : (i = new Float32Array(i), e = at.VERTEX | at.COPY_DST)), i = new Ee({
data: i,
label: t ? "index-mesh-buffer" : "vertex-mesh-buffer",
usage: e
});
}
return i;
}
function Co(i, t, e) {
const s = i.getAttribute(t);
if (!s)
return e.minX = 0, e.minY = 0, e.maxX = 0, e.maxY = 0, e;
const r = s.buffer.data;
let n = 1 / 0, a = 1 / 0, o = -1 / 0, h = -1 / 0;
const c = r.BYTES_PER_ELEMENT, l = (s.offset || 0) / c, u = (s.stride || 2 * 4) / c;
for (let d = l; d < r.length; d += u) {
const p = r[d], f = r[d + 1];
p > o && (o = p), f > h && (h = f), p < n && (n = p), f < a && (a = f);
}
return e.minX = n, e.minY = a, e.maxX = o, e.maxY = h, e;
}
function Mo(i) {
return (i instanceof Ee || Array.isArray(i) || i.BYTES_PER_ELEMENT) && (i = {
buffer: i
}), i.buffer = Hr(i.buffer, !1), i;
}
class To extends Bt {
/**
* Create a new instance of a geometry
* @param options - The options for the geometry.
*/
constructor(t) {
const { attributes: e, indexBuffer: s, topology: r } = t;
super(), this.uid = et("geometry"), this._layoutKey = 0, this.instanceCount = 1, this._bounds = new St(), this._boundsDirty = !0, this.attributes = e, this.buffers = [], this.instanceCount = t.instanceCount || 1;
for (const n in e) {
const a = e[n] = Mo(e[n]);
this.buffers.indexOf(a.buffer) === -1 && (this.buffers.push(a.buffer), a.buffer.on("update", this.onBufferUpdate, this), a.buffer.on("change", this.onBufferUpdate, this));
}
s && (this.indexBuffer = Hr(s, !0), this.buffers.push(this.indexBuffer)), this.topology = r || "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(t) {
return this.attributes[t];
}
/**
* 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(t) {
return this.getAttribute(t).buffer;
}
/**
* Used to figure out how many vertices there are in this geometry
* @returns the number of vertices in the geometry
*/
getSize() {
for (const t in this.attributes) {
const e = this.attributes[t];
return e.buffer.data.length / (e.stride / 4 || e.size);
}
return 0;
}
/** Returns the bounds of the geometry. */
get bounds() {
return this._boundsDirty ? (this._boundsDirty = !1, Co(this, "aPosition", this._bounds)) : this._bounds;
}
/**
* destroys the geometry.
* @param destroyBuffers - destroy the buffers associated with this geometry
*/
destroy(t = !1) {
this.emit("destroy", this), this.removeAllListeners(), t && this.buffers.forEach((e) => e.destroy()), this.attributes = null, this.buffers = null, this.indexBuffer = null, this._bounds = null;
}
}
const Po = new Float32Array(1), ko = new Uint32Array(1);
class Io extends To {
constructor() {
const e = new Ee({
data: Po,
label: "attribute-batch-buffer",
usage: at.VERTEX | at.COPY_DST,
shrinkToFit: !1
}), s = new Ee({
data: ko,
label: "index-batch-buffer",
usage: at.INDEX | at.COPY_DST,
// | BufferUsage.STATIC,
shrinkToFit: !1
}), r = 6 * 4;
super({
attributes: {
aPosition: {
buffer: e,
format: "float32x2",
stride: r,
offset: 0,
location: 1
},
aUV: {
buffer: e,
format: "float32x2",
stride: r,
offset: 2 * 4,
location: 3
},
aColor: {
buffer: e,
format: "unorm8x4",
stride: r,
offset: 4 * 4,
location: 0
},
aTextureIdAndRound: {
buffer: e,
format: "uint16x2",
stride: r,
offset: 5 * 4,
location: 2
}
},
indexBuffer: s
});
}
}
let je = null;
function Wr() {
if (je)
return je;
const i = ba();
return je = i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS), je;
}
const Nr = {};
function Eo(i, t) {
let e = 0;
for (let s = 0; s < t; s++)
e = e * 31 + i[s].uid >>> 0;
return Nr[e] || Ro(i, e);
}
let vi = 0;
function Ro(i, t) {
const e = {};
let s = 0;
vi || (vi = Wr());
for (let n = 0; n < vi; n++) {
const a = n < i.length ? i[n] : L.EMPTY.source;
e[s++] = a.source, e[s++] = a.style;
}
const r = new wa(e);
return Nr[t] = r, r;
}
class Bs {
constructor(t) {
typeof t == "number" ? this.rawBinaryData = new ArrayBuffer(t) : t instanceof Uint8Array ? this.rawBinaryData = t.buffer : this.rawBinaryData = t, 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(t) {
return this[`${t}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(t) {
switch (t) {
case "int8":
case "uint8":
return 1;
case "int16":
case "uint16":
return 2;
case "int32":
case "uint32":
case "float32":
return 4;
default:
throw new Error(`${t} isn't a valid view type`);
}
}
}
function Fs(i, t) {
const e = i.byteLength / 8 | 0, s = new Float64Array(i, 0, e);
new Float64Array(t, 0, e).set(s);
const n = i.byteLength - e * 8;
if (n > 0) {
const a = new Uint8Array(i, e * 8, n);
new Uint8Array(t, e * 8, n).set(a);
}
}
const Bo = {
normal: "normal-npm",
add: "add-npm",
screen: "screen-npm"
};
var Fo = /* @__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.RENDERING_MASK_REMOVE = 3] = "RENDERING_MASK_REMOVE", i[i.NONE = 4] = "NONE", i))(Fo || {});
function Ls(i, t) {
return t.alphaMode === "no-premultiply-alpha" && Bo[i] || i;
}
class Ds {
constructor() {
this.ids = /* @__PURE__ */ Object.create(null), this.textures = [], this.count = 0;
}
/** Clear the textures and their locations. */
clear() {
for (let t = 0; t < this.count; t++) {
const e = this.textures[t];
this.textures[t] = null, this.ids[e.uid] = null;
}
this.count = 0;
}
}
class Us {
constructor() {
this.renderPipeId = "batch", this.action = "startBatch", this.start = 0, this.size = 0, this.blendMode = "normal", this.canBundle = !0;
}
destroy() {
this.textures = null, this.gpuBindGroup = null, this.bindGroup = null, this.batcher = null;
}
}
let ge = 0;
const Yr = class Vr {
constructor(t = {}) {
this.uid = et("batcher"), this.dirty = !0, this.batchIndex = 0, this.batches = [], this._vertexSize = 6, this._elements = [], this._batchPool = [], this._batchPoolIndex = 0, this._textureBatchPool = [], this._textureBatchPoolIndex = 0, t = { ...Vr.defaultOptions, ...t };
const { vertexSize: e, indexSize: s } = t;
this.attributeBuffer = new Bs(e * this._vertexSize * 4), this.indexBuffer = new Uint16Array(s), this._maxTextures = Wr();
}
begin() {
this.batchIndex = 0, this.elementSize = 0, this.elementStart = 0, this.indexSize = 0, this.attributeSize = 0, this._batchPoolIndex = 0, this._textureBatchPoolIndex = 0, this._batchIndexStart = 0, this._batchIndexSize = 0, this.dirty = !0;
}
add(t) {
this._elements[this.elementSize++] = t, t.indexStart = this.indexSize, t.location = this.attributeSize, t.batcher = this, this.indexSize += t.indexSize, this.attributeSize += t.vertexSize * this._vertexSize;
}
checkAndUpdateTexture(t, e) {
const s = t.batch.textures.ids[e._source.uid];
return !s && s !== 0 ? !1 : (t.textureId = s, t.texture = e, !0);
}
updateElement(t) {
this.dirty = !0, t.packAttributes(
this.attributeBuffer.float32View,
this.attributeBuffer.uint32View,
t.location,
t.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(t) {
const e = this._elements;
let s = this._textureBatchPool[this._textureBatchPoolIndex++] || new Ds();
if (s.clear(), !e[this.elementStart])
return;
const r = e[this.elementStart];
let n = Ls(r.blendMode, r.texture._source);
this.attributeSize * 4 > this.attributeBuffer.size && this._resizeAttributeBuffer(this.attributeSize * 4), this.indexSize > this.indexBuffer.length && this._resizeIndexBuffer(this.indexSize);
const a = this.attributeBuffer.float32View, o = this.attributeBuffer.uint32View, h = this.indexBuffer;
let c = this._batchIndexSize, l = this._batchIndexStart, u = "startBatch", d = this._batchPool[this._batchPoolIndex++] || new Us();
const p = this._maxTextures;
for (let f = this.elementStart; f < this.elementSize; ++f) {
const g = e[f];
e[f] = null;
const y = g.texture._source, _ = Ls(g.blendMode, y), x = n !== _;
if (y._batchTick === ge && !x) {
g.textureId = y._textureBindLocation, c += g.indexSize, g.packAttributes(a, o, g.location, g.textureId), g.packIndex(h, g.indexStart, g.location / this._vertexSize), g.batch = d;
continue;
}
y._batchTick = ge, (s.count >= p || x) && (this._finishBatch(
d,
l,
c - l,
s,
n,
t,
u
), u = "renderBatch", l = c, n = _, s = this._textureBatchPool[this._textureBatchPoolIndex++] || new Ds(), s.clear(), d = this._batchPool[this._batchPoolIndex++] || new Us(), ++ge), g.textureId = y._textureBindLocation = s.count, s.ids[y.uid] = s.count, s.textures[s.count++] = y, g.batch = d, c += g.indexSize, g.packAttributes(a, o, g.location, g.textureId), g.packIndex(h, g.indexStart, g.location / this._vertexSize);
}
s.count > 0 && (this._finishBatch(
d,
l,
c - l,
s,
n,
t,
u
), l = c, ++ge), this.elementStart = this.elementSize, this._batchIndexStart = l, this._batchIndexSize = c;
}
_finishBatch(t, e, s, r, n, a, o) {
t.gpuBindGroup = null, t.action = o, t.batcher = this, t.textures = r, t.blendMode = n, t.start = e, t.size = s, ++ge, a.add(t);
}
finish(t) {
this.break(t);
}
/**
* Resizes the attribute buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureAttributeBuffer(t) {
t * 4 <= this.attributeBuffer.size || this._resizeAttributeBuffer(t * 4);
}
/**
* Resizes the index buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureIndexBuffer(t) {
t <= this.indexBuffer.length || this._resizeIndexBuffer(t);
}
_resizeAttributeBuffer(t) {
const e = Math.max(t, this.attributeBuffer.size * 2), s = new Bs(e);
Fs(this.attributeBuffer.rawBinaryData, s.rawBinaryData), this.attributeBuffer = s;
}
_resizeIndexBuffer(t) {
const e = this.indexBuffer;
let s = Math.max(t, e.length * 1.5);
s += s % 2;
const r = s > 65535 ? new Uint32Array(s) : new Uint16Array(s);
if (r.BYTES_PER_ELEMENT !== e.BYTES_PER_ELEMENT)
for (let n = 0; n < e.length; n++)
r[n] = e[n];
else
Fs(e.buffer, r.buffer);
this.indexBuffer = r;
}
destroy() {
for (let t = 0; t < this.batches.length; t++)
this.batches[t].destroy();
this.batches = null;
for (let t = 0; t < this._elements.length; t++)
this._elements[t].batch = null;
this._elements = null, this.indexBuffer = null, this.attributeBuffer.destroy(), this.attributeBuffer = null;
}
};
Yr.defaultOptions = {
vertexSize: 4,
indexSize: 6
};
let Lo = Yr;
function Do(i, t, e, s, r, n, a, o = null) {
let h = 0;
e *= t, r *= n;
const c = o.a, l = o.b, u = o.c, d = o.d, p = o.tx, f = o.ty;
for (; h < a; ) {
const g = i[e], m = i[e + 1];
s[r] = c * g + u * m + p, s[r + 1] = l * g + d * m + f, r += n, e += t, h++;
}
}
function Uo(i, t, e, s) {
let r = 0;
for (t *= e; r < s; )
i[t] = 0, i[t + 1] = 0, t += e, r++;
}
function jr(i, t, e, s, r) {
const n = t.a, a = t.b, o = t.c, h = t.d, c = t.tx, l = t.ty;
e = e || 0, s = s || 2, r = r || i.length / s - e;
let u = e * s;
for (let d = 0; d < r; d++) {
const p = i[u], f = i[u + 1];
i[u] = n * p + o * f + c, i[u + 1] = a * p + h * f + l, u += s;
}
}
function Oo(i, t) {
if (i === 16777215 || !t)
return t;
if (t === 16777215 || !i)
return i;
const e = i >> 16 & 255, s = i >> 8 & 255, r = i & 255, n = t >> 16 & 255, a = t >> 8 & 255, o = t & 255, h = e * n / 255, c = s * a / 255, l = r * o / 255;
return (h << 16) + (c << 8) + l;
}
class Xr {
constructor() {
this.batcher = null, this.batch = null, this.applyTransform = !0, this.roundPixels = 0;
}
get blendMode() {
return this.applyTransform ? this.renderable.groupBlendMode : "normal";
}
packIndex(t, e, s) {
const r = this.geometryData.indices;
for (let n = 0; n < this.indexSize; n++)
t[e++] = r[n + this.indexOffset] + s - this.vertexOffset;
}
packAttributes(t, e, s, r) {
const n = this.geometryData, a = this.renderable, o = n.vertices, h = n.uvs, c = this.vertexOffset * 2, l = (this.vertexOffset + this.vertexSize) * 2, u = this.color, d = u >> 16 | u & 65280 | (u & 255) << 16;
if (this.applyTransform) {
const p = Oo(d, a.groupColor) + (this.alpha * a.groupAlpha * 255 << 24), f = a.groupTransform, g = r << 16 | this.roundPixels & 65535, m = f.a, y = f.b, _ = f.c, x = f.d, b = f.tx, S = f.ty;
for (let k = c; k < l; k += 2) {
const M = o[k], C = o[k + 1];
t[s] = m * M + _ * C + b, t[s + 1] = y * M + x * C + S, t[s + 2] = h[k], t[s + 3] = h[k + 1], e[s + 4] = p, e[s + 5] = g, s += 6;
}
} else {
const p = d + (this.alpha * 255 << 24);
for (let f = c; f < l; f += 2)
t[s] = o[f], t[s + 1] = o[f + 1], t[s + 2] = h[f], t[s + 3] = h[f + 1], e[s + 4] = p, e[s + 5] = r << 16, s += 6;
}
}
// TODO rename to vertexSize
get vertSize() {
return this.vertexSize;
}
copyTo(t) {
t.indexOffset = this.indexOffset, t.indexSize = this.indexSize, t.vertexOffset = this.vertexOffset, t.vertexSize = this.vertexSize, t.color = this.color, t.alpha = this.alpha, t.texture = this.texture, t.geometryData = this.geometryData;
}
reset() {
this.applyTransform = !0;
}
}
const Ai = {
build(i, t) {
let e, s, r, n, a, o;
if (i.type === "circle") {
const b = i;
e = b.x, s = b.y, a = o = b.radius, r = n = 0;
} else if (i.type === "ellipse") {
const b = i;
e = b.x, s = b.y, a = b.halfWidth, o = b.halfHeight, r = n = 0;
} else {
const b = i, S = b.width / 2, k = b.height / 2;
e = b.x + S, s = b.y + k, a = o = Math.max(0, Math.min(b.radius, Math.min(S, k))), r = S - a, n = k - o;
}
if (!(a >= 0 && o >= 0 && r >= 0 && n >= 0))
return t;
const h = Math.ceil(2.3 * Math.sqrt(a + o)), c = h * 8 + (r ? 4 : 0) + (n ? 4 : 0);
if (c === 0)
return t;
if (h === 0)
return t[0] = t[6] = e + r, t[1] = t[3] = s + n, t[2] = t[4] = e - r, t[5] = t[7] = s - n, t;
let l = 0, u = h * 4 + (r ? 2 : 0) + 2, d = u, p = c, f = r + a, g = n, m = e + f, y = e - f, _ = s + g;
if (t[l++] = m, t[l++] = _, t[--u] = _, t[--u] = y, n) {
const b = s - g;
t[d++] = y, t[d++] = b, t[--p] = b, t[--p] = m;
}
for (let b = 1; b < h; b++) {
const S = Math.PI / 2 * (b / h), k = r + Math.cos(S) * a, M = n + Math.sin(S) * o, C = e + k, v = e - k, A = s + M, j = s - M;
t[l++] = C, t[l++] = A, t[--u] = A, t[--u] = v, t[d++] = v, t[d++] = j, t[--p] = j, t[--p] = C;
}
f = r, g = n + o, m = e + f, y = e - f, _ = s + g;
const x = s - g;
return t[l++] = m, t[l++] = _, t[--p] = x, t[--p] = m, r && (t[l++] = y, t[l++] = _, t[--p] = x, t[--p] = y), t;
},
triangulate(i, t, e, s, r, n) {
if (i.length === 0)
return;
let a = 0, o = 0;
for (let l = 0; l < i.length; l += 2)
a += i[l], o += i[l + 1];
a /= i.length / 2, o /= i.length / 2;
let h = s;
t[h * e] = a, t[h * e + 1] = o;
const c = h++;
for (let l = 0; l < i.length; l += 2)
t[h * e] = i[l], t[h * e + 1] = i[l + 1], l > 0 && (r[n++] = h, r[n++] = c, r[n++] = h - 1), h++;
r[n++] = c + 1, r[n++] = c, r[n++] = h - 1;
}
}, Go = 1e-4, Os = 1e-4;
function zo(i) {
const t = i.length;
if (t < 6)
return 1;
let e = 0;
for (let s = 0, r = i[t - 2], n = i[t - 1]; s < t; s += 2) {
const a = i[s], o = i[s + 1];
e += (a - r) * (o + n), r = a, n = o;
}
return e < 0 ? -1 : 1;
}
function Gs(i, t, e, s, r, n, a, o) {
const h = i - e * r, c = t - s * r, l = i + e * n, u = t + s * n;
let d, p;
a ? (d = s, p = -e) : (d = -s, p = e);
const f = h + d, g = c + p, m = l + d, y = u + p;
return o.push(f, g), o.push(m, y), 2;
}
function Nt(i, t, e, s, r, n, a, o) {
const h = e - i, c = s - t;
let l = Math.atan2(h, c), u = Math.atan2(r - i, n - t);
o && l < u ? l += Math.PI * 2 : !o && l > u && (u += Math.PI * 2);
let d = l;
const p = u - l, f = Math.abs(p), g = Math.sqrt(h * h + c * c), m = (15 * f * Math.sqrt(g) / Math.PI >> 0) + 1, y = p / m;
if (d += y, o) {
a.push(i, t), a.push(e, s);
for (let _ = 1, x = d; _ < m; _++, x += y)
a.push(i, t), a.push(
i + Math.sin(x) * g,
t + Math.cos(x) * g
);
a.push(i, t), a.push(r, n);
} else {
a.push(e, s), a.push(i, t);
for (let _ = 1, x = d; _ < m; _++, x += y)
a.push(
i + Math.sin(x) * g,
t + Math.cos(x) * g
), a.push(i, t);
a.push(r, n), a.push(i, t);
}
return m * 2;
}
function Ho(i, t, e, s, r, n, a, o, h) {
const c = Go;
if (i.length === 0)
return;
const l = t;
let u = l.alignment;
if (t.alignment !== 0.5) {
let U = zo(i);
u = (u - 0.5) * U + 0.5;
}
const d = new st(i[0], i[1]), p = new st(i[i.length - 2], i[i.length - 1]), f = s, g = Math.abs(d.x - p.x) < c && Math.abs(d.y - p.y) < c;
if (f) {
i = i.slice(), g && (i.pop(), i.pop(), p.set(i[i.length - 2], i[i.length - 1]));
const U = (d.x + p.x) * 0.5, Ft = (p.y + d.y) * 0.5;
i.unshift(U, Ft), i.push(U, Ft);
}
const m = r, y = i.length / 2;
let _ = i.length;
const x = m.length / 2, b = l.width / 2, S = b * b, k = l.miterLimit * l.miterLimit;
let M = i[0], C = i[1], v = i[2], A = i[3], j = 0, Mt = 0, R = -(C - A), E = M - v, z = 0, X = 0, ft = Math.sqrt(R * R + E * E);
R /= ft, E /= ft, R *= b, E *= b;
const hs = u, I = (1 - hs) * 2, F = hs * 2;
f || (l.cap === "round" ? _ += Nt(
M - R * (I - F) * 0.5,
C - E * (I - F) * 0.5,
M - R * I,
C - E * I,
M + R * F,
C + E * F,
m,
!0
) + 2 : l.cap === "square" && (_ += Gs(M, C, R, E, I, F, !0, m))), m.push(
M - R * I,
C - E * I
), m.push(
M + R * F,
C + E * F
);
for (let U = 1; U < y - 1; ++U) {
M = i[(U - 1) * 2], C = i[(U - 1) * 2 + 1], v = i[U * 2], A = i[U * 2 + 1], j = i[(U + 1) * 2], Mt = i[(U + 1) * 2 + 1], R = -(C - A), E = M - v, ft = Math.sqrt(R * R + E * E), R /= ft, E /= ft, R *= b, E *= b, z = -(A - Mt), X = v - j, ft = Math.sqrt(z * z + X * X), z /= ft, X /= ft, z *= b, X *= b;
const Ft = v - M, ce = C - A, ue = v - j, de = Mt - A, ls = Ft * ue + ce * de, Fe = ce * ue - de * Ft, fe = Fe < 0;
if (Math.abs(Fe) < 1e-3 * Math.abs(ls)) {
m.push(
v - R * I,
A - E * I
), m.push(
v + R * F,
A + E * F
), ls >= 0 && (l.join === "round" ? _ += Nt(
v,
A,
v - R * I,
A - E * I,
v - z * I,
A - X * I,
m,
!1
) + 4 : _ += 2, m.push(
v - z * F,
A - X * F
), m.push(
v + z * I,
A + X * I
));
continue;
}
const cs = (-R + M) * (-E + A) - (-R + v) * (-E + C), us = (-z + j) * (-X + A) - (-z + v) * (-X + Mt), Le = (Ft * us - ue * cs) / Fe, De = (de * cs - ce * us) / Fe, hi = (Le - v) * (Le - v) + (De - A) * (De - A), Gt = v + (Le - v) * I, zt = A + (De - A) * I, Ht = v - (Le - v) * F, Wt = A - (De - A) * F, _n = Math.min(Ft * Ft + ce * ce, ue * ue + de * de), ds = fe ? I : F, xn = _n + ds * ds * S;
hi <= xn ? l.join === "bevel" || hi / S > k ? (fe ? (m.push(Gt, zt), m.push(v + R * F, A + E * F), m.push(Gt, zt), m.push(v + z * F, A + X * F)) : (m.push(v - R * I, A - E * I), m.push(Ht, Wt), m.push(v - z * I, A - X * I), m.push(Ht, Wt)), _ += 2) : l.join === "round" ? fe ? (m.push(Gt, zt), m.push(v + R * F, A + E * F), _ += Nt(
v,
A,
v + R * F,
A + E * F,
v + z * F,
A + X * F,
m,
!0
) + 4, m.push(Gt, zt), m.push(v + z * F, A + X * F)) : (m.push(v - R * I, A - E * I), m.push(Ht, Wt), _ += Nt(
v,
A,
v - R * I,
A - E * I,
v - z * I,
A - X * I,
m,
!1
) + 4, m.push(v - z * I, A - X * I), m.push(Ht, Wt)) : (m.push(Gt, zt), m.push(Ht, Wt)) : (m.push(v - R * I, A - E * I), m.push(v + R * F, A + E * F), l.join === "round" ? fe ? _ += Nt(
v,
A,
v + R * F,
A + E * F,
v + z * F,
A + X * F,
m,
!0
) + 2 : _ += Nt(
v,
A,
v - R * I,
A - E * I,
v - z * I,
A - X * I,
m,
!1
) + 2 : l.join === "miter" && hi / S <= k && (fe ? (m.push(Ht, Wt), m.push(Ht, Wt)) : (m.push(Gt, zt), m.push(Gt, zt)), _ += 2), m.push(v - z * I, A - X * I), m.push(v + z * F, A + X * F), _ += 2);
}
M = i[(y - 2) * 2], C = i[(y - 2) * 2 + 1], v = i[(y - 1) * 2], A = i[(y - 1) * 2 + 1], R = -(C - A), E = M - v, ft = Math.sqrt(R * R + E * E), R /= ft, E /= ft, R *= b, E *= b, m.push(v - R * I, A - E * I), m.push(v + R * F, A + E * F), f || (l.cap === "round" ? _ += Nt(
v - R * (I - F) * 0.5,
A - E * (I - F) * 0.5,
v - R * I,
A - E * I,
v + R * F,
A + E * F,
m,
!1
) + 2 : l.cap === "square" && (_ += Gs(v, A, R, E, I, F, !1, m)));
const yn = Os * Os;
for (let U = x; U < _ + x - 2; ++U)
M = m[U * 2], C = m[U * 2 + 1], v = m[(U + 1) * 2], A = m[(U + 1) * 2 + 1], j = m[(U + 2) * 2], Mt = m[(U + 2) * 2 + 1], !(Math.abs(M * (A - Mt) + v * (Mt - C) + j * (C - A)) < yn) && o.push(U, U + 1, U + 2);
}
function $r(i, t, e, s, r, n, a) {
const o = za(i, t, 2);
if (!o)
return;
for (let c = 0; c < o.length; c += 3)
n[a++] = o[c] + r, n[a++] = o[c + 1] + r, n[a++] = o[c + 2] + r;
let h = r * s;
for (let c = 0; c < i.length; c += 2)
e[h] = i[c], e[h + 1] = i[c + 1], h += s;
}
const Wo = [], No = {
build(i, t) {
for (let e = 0; e < i.points.length; e++)
t[e] = i.points[e];
return t;
},
triangulate(i, t, e, s, r, n) {
$r(i, Wo, t, e, s, r, n);
}
}, Yo = {
build(i, t) {
const e = i, s = e.x, r = e.y, n = e.width, a = e.height;
return n >= 0 && a >= 0 && (t[0] = s, t[1] = r, t[2] = s + n, t[3] = r, t[4] = s + n, t[5] = r + a, t[6] = s, t[7] = r + a), t;
},
triangulate(i, t, e, s, r, n) {
let a = 0;
s *= e, t[s + a] = i[0], t[s + a + 1] = i[1], a += e, t[s + a] = i[2], t[s + a + 1] = i[3], a += e, t[s + a] = i[6], t[s + a + 1] = i[7], a += e, t[s + a] = i[4], t[s + a + 1] = i[5], a += e;
const o = s / e;
r[n++] = o, r[n++] = o + 1, r[n++] = o + 2, r[n++] = o + 1, r[n++] = o + 3, r[n++] = o + 2;
}
}, Vo = {
build(i, t) {
return t[0] = i.x, t[1] = i.y, t[2] = i.x2, t[3] = i.y2, t[4] = i.x3, t[5] = i.y3, t;
},
triangulate(i, t, e, s, r, n) {
let a = 0;
s *= e, t[s + a] = i[0], t[s + a + 1] = i[1], a += e, t[s + a] = i[2], t[s + a + 1] = i[3], a += e, t[s + a] = i[4], t[s + a + 1] = i[5];
const o = s / e;
r[n++] = o, r[n++] = o + 1, r[n++] = o + 2;
}
}, es = {
rectangle: Yo,
polygon: No,
triangle: Vo,
circle: Ai,
ellipse: Ai,
roundedRectangle: Ai
}, jo = new tt();
function Xo(i, t) {
const { geometryData: e, batches: s } = t;
s.length = 0, e.indices.length = 0, e.vertices.length = 0, e.uvs.length = 0;
for (let r = 0; r < i.instructions.length; r++) {
const n = i.instructions[r];
if (n.action === "texture")
$o(n.data, s, e);
else if (n.action === "fill" || n.action === "stroke") {
const a = n.action === "stroke", o = n.data.path.shapePath, h = n.data.style, c = n.data.hole;
a && c && zs(c.shapePath, h, null, !0, s, e), zs(o, h, c, a, s, e);
}
}
}
function $o(i, t, e) {
const { vertices: s, uvs: r, indices: n } = e, a = n.length, o = s.length / 2, h = [], c = es.rectangle, l = jo, u = i.image;
l.x = i.dx, l.y = i.dy, l.width = i.dw, l.height = i.dh;
const d = i.transform;
c.build(l, h), d && jr(h, d), c.triangulate(h, s, 2, o, n, a);
const p = u.uvs;
r.push(
p.x0,
p.y0,
p.x1,
p.y1,
p.x3,
p.y3,
p.x2,
p.y2
);
const f = kt.get(Xr);
f.indexOffset = a, f.indexSize = n.length - a, f.vertexOffset = o, f.vertexSize = s.length / 2 - o, f.color = i.style, f.alpha = i.alpha, f.texture = u, f.geometryData = e, t.push(f);
}
function zs(i, t, e, s, r, n) {
const { vertices: a, uvs: o, indices: h } = n, c = i.shapePrimitives.length - 1;
i.shapePrimitives.forEach(({ shape: l, transform: u }, d) => {
const p = h.length, f = a.length / 2, g = [], m = es[l.type];
if (m.build(l, g), u && jr(g, u), s) {
const b = l.closePath ?? !0;
Ho(g, t, !1, b, a, 2, f, h);
} else if (e && c === d) {
c !== 0 && console.warn("[Pixi Graphics] only the last shape have be cut out");
const b = [], S = g.slice();
qo(e.shapePath).forEach((M) => {
b.push(S.length / 2), S.push(...M);
}), $r(S, b, a, 2, f, h, p);
} else
m.triangulate(g, a, 2, f, h, p);
const y = o.length / 2, _ = t.texture;
if (_ !== L.WHITE) {
const b = t.matrix;
u && b.append(u.clone().invert()), Do(a, 2, f, o, y, 2, a.length / 2 - f, b);
} else
Uo(o, y, 2, a.length / 2 - f);
const x = kt.get(Xr);
x.indexOffset = p, x.indexSize = h.length - p, x.vertexOffset = f, x.vertexSize = a.length / 2 - f, x.color = t.color, x.alpha = t.alpha, x.texture = _, x.geometryData = n, r.push(x);
});
}
function qo(i) {
if (!i)
return [];
const t = i.shapePrimitives, e = [];
for (let s = 0; s < t.length; s++) {
const r = t[s].shape, n = [];
es[r.type].build(r, n), e.push(n);
}
return e;
}
class Ko {
constructor() {
this.batches = [], this.geometryData = {
vertices: [],
uvs: [],
indices: []
};
}
}
class Zo {
constructor() {
this.geometry = new Io(), this.instructions = new xr();
}
init() {
this.instructions.reset();
}
}
const is = class Gi {
constructor() {
this._activeBatchers = [], this._gpuContextHash = {}, this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null);
}
/**
* Runner init called, update the default options
* @ignore
*/
init(t) {
Gi.defaultOptions.bezierSmoothness = (t == null ? void 0 : t.bezierSmoothness) ?? Gi.defaultOptions.bezierSmoothness;
}
prerender() {
this._returnActiveBatchers();
}
getContextRenderData(t) {
return this._graphicsDataContextHash[t.uid] || this._initContextRenderData(t);
}
// Context management functions
updateGpuContext(t) {
let e = this._gpuContextHash[t.uid] || this._initContext(t);
if (t.dirty) {
e ? this._cleanGraphicsContextData(t) : e = this._initContext(t), Xo(t, e);
const s = t.batchMode;
t.customShader || s === "no-batch" ? e.isBatchable = !1 : s === "auto" && (e.isBatchable = e.geometryData.vertices.length < 400), t.dirty = !1;
}
return e;
}
getGpuContext(t) {
return this._gpuContextHash[t.uid] || this._initContext(t);
}
_returnActiveBatchers() {
for (let t = 0; t < this._activeBatchers.length; t++)
kt.return(this._activeBatchers[t]);
this._activeBatchers.length = 0;
}
_initContextRenderData(t) {
const e = kt.get(Zo), { batches: s, geometryData: r } = this._gpuContextHash[t.uid], n = r.vertices.length, a = r.indices.length;
for (let l = 0; l < s.length; l++)
s[l].applyTransform = !1;
const o = kt.get(Lo);
this._activeBatchers.push(o), o.ensureAttributeBuffer(n), o.ensureIndexBuffer(a), o.begin();
for (let l = 0; l < s.length; l++) {
const u = s[l];
o.add(u);
}
o.finish(e.instructions);
const h = e.geometry;
h.indexBuffer.setDataWithSize(o.indexBuffer, o.indexSize, !0), h.buffers[0].setDataWithSize(o.attributeBuffer.float32View, o.attributeSize, !0);
const c = o.batches;
for (let l = 0; l < c.length; l++) {
const u = c[l];
u.bindGroup = Eo(u.textures.textures, u.textures.count);
}
return this._graphicsDataContextHash[t.uid] = e, e;
}
_initContext(t) {
const e = new Ko();
return e.context = t, this._gpuContextHash[t.uid] = e, t.on("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[t.uid];
}
onGraphicsContextDestroy(t) {
this._cleanGraphicsContextData(t), t.off("destroy", this.onGraphicsContextDestroy, this), this._gpuContextHash[t.uid] = null;
}
_cleanGraphicsContextData(t) {
const e = this._gpuContextHash[t.uid];
e.isBatchable || this._graphicsDataContextHash[t.uid] && (kt.return(this.getContextRenderData(t)), this._graphicsDataContextHash[t.uid] = null), e.batches && e.batches.forEach((s) => {
kt.return(s);
});
}
destroy() {
for (const t in this._gpuContextHash)
this._gpuContextHash[t] && this.onGraphicsContextDestroy(this._gpuContextHash[t].context);
}
};
is.extension = {
type: [
B.WebGLSystem,
B.WebGPUSystem,
B.CanvasSystem
],
name: "graphicsContext"
};
is.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 qr = is;
const Jo = 8, Xe = 11920929e-14, Qo = 1;
function Kr(i, t, e, s, r, n, a, o, h, c) {
const u = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, c ?? qr.defaultOptions.bezierSmoothness)
);
let d = (Qo - u) / 1;
return d *= d, th(t, e, s, r, n, a, o, h, i, d), i;
}
function th(i, t, e, s, r, n, a, o, h, c) {
zi(i, t, e, s, r, n, a, o, h, c, 0), h.push(a, o);
}
function zi(i, t, e, s, r, n, a, o, h, c, l) {
if (l > Jo)
return;
const u = (i + e) / 2, d = (t + s) / 2, p = (e + r) / 2, f = (s + n) / 2, g = (r + a) / 2, m = (n + o) / 2, y = (u + p) / 2, _ = (d + f) / 2, x = (p + g) / 2, b = (f + m) / 2, S = (y + x) / 2, k = (_ + b) / 2;
if (l > 0) {
let M = a - i, C = o - t;
const v = Math.abs((e - a) * C - (s - o) * M), A = Math.abs((r - a) * C - (n - o) * M);
if (v > Xe && A > Xe) {
if ((v + A) * (v + A) <= c * (M * M + C * C)) {
h.push(S, k);
return;
}
} else if (v > Xe) {
if (v * v <= c * (M * M + C * C)) {
h.push(S, k);
return;
}
} else if (A > Xe) {
if (A * A <= c * (M * M + C * C)) {
h.push(S, k);
return;
}
} else if (M = S - (i + a) / 2, C = k - (t + o) / 2, M * M + C * C <= c) {
h.push(S, k);
return;
}
}
zi(i, t, u, d, y, _, S, k, h, c, l + 1), zi(S, k, x, b, g, m, a, o, h, c, l + 1);
}
const eh = 8, ih = 11920929e-14, sh = 1;
function rh(i, t, e, s, r, n, a, o) {
const c = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, o ?? qr.defaultOptions.bezierSmoothness)
);
let l = (sh - c) / 1;
return l *= l, nh(t, e, s, r, n, a, i, l), i;
}
function nh(i, t, e, s, r, n, a, o) {
Hi(a, i, t, e, s, r, n, o, 0), a.push(r, n);
}
function Hi(i, t, e, s, r, n, a, o, h) {
if (h > eh)
return;
const c = (t + s) / 2, l = (e + r) / 2, u = (s + n) / 2, d = (r + a) / 2, p = (c + u) / 2, f = (l + d) / 2;
let g = n - t, m = a - e;
const y = Math.abs((s - n) * m - (r - a) * g);
if (y > ih) {
if (y * y <= o * (g * g + m * m)) {
i.push(p, f);
return;
}
} else if (g = p - (t + n) / 2, m = f - (e + a) / 2, g * g + m * m <= o) {
i.push(p, f);
return;
}
Hi(i, t, e, c, l, p, f, o, h + 1), Hi(i, p, f, u, d, n, a, o, h + 1);
}
function Zr(i, t, e, s, r, n, a, o) {
let h = Math.abs(r - n);
(!a && r > n || a && n > r) && (h = 2 * Math.PI - h), o = o || Math.max(6, Math.floor(6 * Math.pow(s, 1 / 3) * (h / Math.PI))), o = Math.max(o, 3);
let c = h / o, l = r;
c *= a ? -1 : 1;
for (let u = 0; u < o + 1; u++) {
const d = Math.cos(l), p = Math.sin(l), f = t + d * s, g = e + p * s;
i.push(f, g), l += c;
}
}
function ah(i, t, e, s, r, n) {
const a = i[i.length - 2], h = i[i.length - 1] - e, c = a - t, l = r - e, u = s - t, d = Math.abs(h * u - c * l);
if (d < 1e-8 || n === 0) {
(i[i.length - 2] !== t || i[i.length - 1] !== e) && i.push(t, e);
return;
}
const p = h * h + c * c, f = l * l + u * u, g = h * l + c * u, m = n * Math.sqrt(p) / d, y = n * Math.sqrt(f) / d, _ = m * g / p, x = y * g / f, b = m * u + y * c, S = m * l + y * h, k = c * (y + _), M = h * (y + _), C = u * (m + x), v = l * (m + x), A = Math.atan2(M - S, k - b), j = Math.atan2(v - S, C - b);
Zr(
i,
b + t,
S + e,
n,
A,
j,
c * l > u * h
);
}
const Ce = Math.PI * 2, Si = {
centerX: 0,
centerY: 0,
ang1: 0,
ang2: 0
}, Ci = ({ x: i, y: t }, e, s, r, n, a, o, h) => {
i *= e, t *= s;
const c = r * i - n * t, l = n * i + r * t;
return h.x = c + a, h.y = l + o, h;
};
function oh(i, t) {
const e = t === -1.5707963267948966 ? -0.551915024494 : 1.3333333333333333 * Math.tan(t / 4), s = t === 1.5707963267948966 ? 0.551915024494 : e, r = Math.cos(i), n = Math.sin(i), a = Math.cos(i + t), o = Math.sin(i + t);
return [
{
x: r - n * s,
y: n + r * s
},
{
x: a + o * s,
y: o - a * s
},
{
x: a,
y: o
}
];
}
const Hs = (i, t, e, s) => {
const r = i * s - t * e < 0 ? -1 : 1;
let n = i * e + t * s;
return n > 1 && (n = 1), n < -1 && (n = -1), r * Math.acos(n);
}, hh = (i, t, e, s, r, n, a, o, h, c, l, u, d) => {
const p = Math.pow(r, 2), f = Math.pow(n, 2), g = Math.pow(l, 2), m = Math.pow(u, 2);
let y = p * f - p * m - f * g;
y < 0 && (y = 0), y /= p * m + f * g, y = Math.sqrt(y) * (a === o ? -1 : 1);
const _ = y * r / n * u, x = y * -n / r * l, b = c * _ - h * x + (i + e) / 2, S = h * _ + c * x + (t + s) / 2, k = (l - _) / r, M = (u - x) / n, C = (-l - _) / r, v = (-u - x) / n, A = Hs(1, 0, k, M);
let j = Hs(k, M, C, v);
o === 0 && j > 0 && (j -= Ce), o === 1 && j < 0 && (j += Ce), d.centerX = b, d.centerY = S, d.ang1 = A, d.ang2 = j;
};
function lh(i, t, e, s, r, n, a, o = 0, h = 0, c = 0) {
if (n === 0 || a === 0)
return;
const l = Math.sin(o * Ce / 360), u = Math.cos(o * Ce / 360), d = u * (t - s) / 2 + l * (e - r) / 2, p = -l * (t - s) / 2 + u * (e - r) / 2;
if (d === 0 && p === 0)
return;
n = Math.abs(n), a = Math.abs(a);
const f = Math.pow(d, 2) / Math.pow(n, 2) + Math.pow(p, 2) / Math.pow(a, 2);
f > 1 && (n *= Math.sqrt(f), a *= Math.sqrt(f)), hh(
t,
e,
s,
r,
n,
a,
h,
c,
l,
u,
d,
p,
Si
);
let { ang1: g, ang2: m } = Si;
const { centerX: y, centerY: _ } = Si;
let x = Math.abs(m) / (Ce / 4);
Math.abs(1 - x) < 1e-7 && (x = 1);
const b = Math.max(Math.ceil(x), 1);
m /= b;
let S = i[i.length - 2], k = i[i.length - 1];
const M = { x: 0, y: 0 };
for (let C = 0; C < b; C++) {
const v = oh(g, m), { x: A, y: j } = Ci(v[0], n, a, u, l, y, _, M), { x: Mt, y: R } = Ci(v[1], n, a, u, l, y, _, M), { x: E, y: z } = Ci(v[2], n, a, u, l, y, _, M);
Kr(
i,
S,
k,
A,
j,
Mt,
R,
E,
z
), S = E, k = z, g += m;
}
}
function ch(i, t, e) {
const s = (a, o) => {
const h = o.x - a.x, c = o.y - a.y, l = Math.sqrt(h * h + c * c), u = h / l, d = c / l;
return { len: l, nx: u, ny: d };
}, r = (a, o) => {
a === 0 ? i.moveTo(o.x, o.y) : i.lineTo(o.x, o.y);
};
let n = t[t.length - 1];
for (let a = 0; a < t.length; a++) {
const o = t[a % t.length], h = o.radius ?? e;
if (h <= 0) {
r(a, o), n = o;
continue;
}
const c = t[(a + 1) % t.length], l = s(o, n), u = s(o, c);
if (l.len < 1e-4 || u.len < 1e-4) {
r(a, o), n = o;
continue;
}
let d = Math.asin(l.nx * u.ny - l.ny * u.nx), p = 1, f = !1;
l.nx * u.nx - l.ny * -u.ny < 0 ? d < 0 ? d = Math.PI + d : (d = Math.PI - d, p = -1, f = !0) : d > 0 && (p = -1, f = !0);
const g = d / 2;
let m, y = Math.abs(
Math.cos(g) * h / Math.sin(g)
);
y > Math.min(l.len / 2, u.len / 2) ? (y = Math.min(l.len / 2, u.len / 2), m = Math.abs(y * Math.sin(g) / Math.cos(g))) : m = h;
const _ = o.x + u.nx * y + -u.ny * m * p, x = o.y + u.ny * y + u.nx * m * p, b = Math.atan2(l.ny, l.nx) + Math.PI / 2 * p, S = Math.atan2(u.ny, u.nx) - Math.PI / 2 * p;
a === 0 && i.moveTo(
_ + Math.cos(b) * m,
x + Math.sin(b) * m
), i.arc(_, x, m, b, S, f), n = o;
}
}
function uh(i, t, e, s) {
const r = (o, h) => Math.sqrt((o.x - h.x) ** 2 + (o.y - h.y) ** 2), n = (o, h, c) => ({
x: o.x + (h.x - o.x) * c,
y: o.y + (h.y - o.y) * c
}), a = t.length;
for (let o = 0; o < a; o++) {
const h = t[(o + 1) % a], c = h.radius ?? e;
if (c <= 0) {
o === 0 ? i.moveTo(h.x, h.y) : i.lineTo(h.x, h.y);
continue;
}
const l = t[o], u = t[(o + 2) % a], d = r(l, h);
let p;
if (d < 1e-4)
p = h;
else {
const m = Math.min(d / 2, c);
p = n(
h,
l,
m / d
);
}
const f = r(u, h);
let g;
if (f < 1e-4)
g = h;
else {
const m = Math.min(f / 2, c);
g = n(
h,
u,
m / f
);
}
o === 0 ? i.moveTo(p.x, p.y) : i.lineTo(p.x, p.y), i.quadraticCurveTo(h.x, h.y, g.x, g.y, s);
}
}
const dh = new tt();
class fh {
constructor(t) {
this.shapePrimitives = [], this._currentPoly = null, this._bounds = new St(), this._graphicsPath2D = t;
}
/**
* 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(t, e) {
return this.startPoly(t, e), 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(t, e) {
this._ensurePoly();
const s = this._currentPoly.points, r = s[s.length - 2], n = s[s.length - 1];
return (r !== t || n !== e) && s.push(t, e), 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(t, e, s, r, n, a) {
this._ensurePoly(!1);
const o = this._currentPoly.points;
return Zr(o, t, e, s, r, n, 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(t, e, s, r, n) {
this._ensurePoly();
const a = this._currentPoly.points;
return ah(a, t, e, s, r, n), 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(t, e, s, r, n, a, o) {
const h = this._currentPoly.points;
return lh(
h,
this._currentPoly.lastX,
this._currentPoly.lastY,
a,
o,
t,
e,
s,
r,
n
), 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(t, e, s, r, n, a, o) {
this._ensurePoly();
const h = this._currentPoly;
return Kr(
this._currentPoly.points,
h.lastX,
h.lastY,
t,
e,
s,
r,
n,
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(t, e, s, r, n) {
this._ensurePoly();
const a = this._currentPoly;
return rh(
this._currentPoly.points,
a.lastX,
a.lastY,
t,
e,
s,
r,
n
), 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(t, e) {
this.endPoly(), e && !e.isIdentity() && (t = t.clone(!0), t.transform(e));
for (let s = 0; s < t.instructions.length; s++) {
const r = t.instructions[s];
this[r.action](...r.data);
}
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(t = !1) {
this.endPoly(t);
}
/**
* 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(t, e, s, r, n) {
return this.drawShape(new tt(t, e, s, r), n), 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(t, e, s, r) {
return this.drawShape(new Ji(t, e, s), r), 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(t, e, s) {
const r = new Se(t);
return r.closePath = e, this.drawShape(r, s), 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(t, e, s, r, n = 0, a) {
r = Math.max(r | 0, 3);
const o = -1 * Math.PI / 2 + n, h = Math.PI * 2 / r, c = [];
for (let l = 0; l < r; l++) {
const u = l * h + o;
c.push(
t + s * Math.cos(u),
e + s * Math.sin(u)
);
}
return this.poly(c, !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(t, e, s, r, n, a = 0, o) {
if (r = Math.max(r | 0, 3), n <= 0)
return this.regularPoly(t, e, s, r, a);
const h = s * Math.sin(Math.PI / r) - 1e-3;
n = Math.min(n, h);
const c = -1 * Math.PI / 2 + a, l = Math.PI * 2 / r, u = (r - 2) * Math.PI / r / 2;
for (let d = 0; d < r; d++) {
const p = d * l + c, f = t + s * Math.cos(p), g = e + s * Math.sin(p), m = p + Math.PI + u, y = p - Math.PI - u, _ = f + n * Math.cos(m), x = g + n * Math.sin(m), b = f + n * Math.cos(y), S = g + n * Math.sin(y);
d === 0 ? this.moveTo(_, x) : this.lineTo(_, x), this.quadraticCurveTo(f, g, b, S, 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(t, e, s = !1, r) {
return t.length < 3 ? this : (s ? uh(this, t, e, r) : ch(this, t, e), 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(t, e, s, r, n) {
if (n === 0)
return this.rect(t, e, s, r);
const a = Math.min(s, r) / 2, o = Math.min(a, Math.max(-a, n)), h = t + s, c = e + r, l = o < 0 ? -o : 0, u = Math.abs(o);
return this.moveTo(t, e + u).arcTo(t + l, e + l, t + u, e, u).lineTo(h - u, e).arcTo(h - l, e + l, h, e + u, u).lineTo(h, c - u).arcTo(h - l, c - l, t + s - u, c, u).lineTo(t + u, c).arcTo(t + l, c - l, t, c - u, u).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(t, e, s, r, n, a) {
if (n <= 0)
return this.rect(t, e, s, r);
const o = Math.min(n, Math.min(s, r) / 2), h = t + s, c = e + r, l = [
t + o,
e,
h - o,
e,
h,
e + o,
h,
c - o,
h - o,
c,
t + o,
c,
t,
c - o,
t,
e + o
];
for (let u = l.length - 1; u >= 2; u -= 2)
l[u] === l[u - 2] && l[u - 1] === l[u - 3] && l.splice(u - 1, 2);
return this.poly(l, !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(t, e, s, r, n) {
return this.drawShape(new Qi(t, e, s, r), n), 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(t, e, s, r, n, a) {
return this.drawShape(new ts(t, e, s, r, n), 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(t, e) {
return this.endPoly(), this.shapePrimitives.push({ shape: t, transform: e }), 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(t, e) {
let s = this._currentPoly;
return s && this.endPoly(), s = new Se(), s.points.push(t, e), this._currentPoly = s, 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(t = !1) {
const e = this._currentPoly;
return e && e.points.length > 2 && (e.closePath = t, this.shapePrimitives.push({ shape: e })), this._currentPoly = null, this;
}
_ensurePoly(t = !0) {
if (!this._currentPoly && (this._currentPoly = new Se(), t)) {
const e = this.shapePrimitives[this.shapePrimitives.length - 1];
if (e) {
let s = e.shape.x, r = e.shape.y;
if (!e.transform.isIdentity()) {
const n = e.transform, a = s;
s = n.a * s + n.c * r + n.tx, r = n.b * a + n.d * r + n.ty;
}
this._currentPoly.points.push(s, r);
} else
this._currentPoly.points.push(0, 0);
}
}
/** Builds the path. */
buildPath() {
const t = this._graphicsPath2D;
this.shapePrimitives.length = 0, this._currentPoly = null;
for (let e = 0; e < t.instructions.length; e++) {
const s = t.instructions[e];
this[s.action](...s.data);
}
this.finish();
}
/** Gets the bounds of the path. */
get bounds() {
const t = this._bounds;
t.clear();
const e = this.shapePrimitives;
for (let s = 0; s < e.length; s++) {
const r = e[s], n = r.shape.getBounds(dh);
r.transform ? t.addRect(n, r.transform) : t.addRect(n);
}
return t;
}
}
class ae {
/**
* 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.
*/
constructor(t) {
this.instructions = [], this.uid = et("graphicsPath"), this._dirty = !0, typeof t == "string" ? Ao(t, this) : this.instructions = (t == null ? void 0 : t.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 fh(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(t, e) {
return t = t.clone(), this.instructions.push({ action: "addPath", data: [t, e] }), this._dirty = !0, this;
}
arc(...t) {
return this.instructions.push({ action: "arc", data: t }), this._dirty = !0, this;
}
arcTo(...t) {
return this.instructions.push({ action: "arcTo", data: t }), this._dirty = !0, this;
}
arcToSvg(...t) {
return this.instructions.push({ action: "arcToSvg", data: t }), this._dirty = !0, this;
}
bezierCurveTo(...t) {
return this.instructions.push({ action: "bezierCurveTo", data: t }), 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(t, e, s, r, n) {
const a = this.instructions[this.instructions.length - 1], o = this.getLastPoint(st.shared);
let h = 0, c = 0;
if (!a || a.action !== "bezierCurveTo")
h = o.x, c = o.y;
else {
h = a.data[2], c = a.data[3];
const l = o.x, u = o.y;
h = l + (l - h), c = u + (u - c);
}
return this.instructions.push({ action: "bezierCurveTo", data: [h, c, t, e, s, r, n] }), 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(...t) {
return this.instructions.push({ action: "ellipse", data: t }), this._dirty = !0, this;
}
lineTo(...t) {
return this.instructions.push({ action: "lineTo", data: t }), this._dirty = !0, this;
}
moveTo(...t) {
return this.instructions.push({ action: "moveTo", data: t }), this;
}
quadraticCurveTo(...t) {
return this.instructions.push({ action: "quadraticCurveTo", data: t }), 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(t, e, s) {
const r = this.instructions[this.instructions.length - 1], n = this.getLastPoint(st.shared);
let a = 0, o = 0;
if (!r || r.action !== "quadraticCurveTo")
a = n.x, o = n.y;
else {
a = r.data[0], o = r.data[1];
const h = n.x, c = n.y;
a = h + (h - a), o = c + (c - o);
}
return this.instructions.push({ action: "quadraticCurveTo", data: [a, o, t, e, s] }), 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(t, e, s, r, n) {
return this.instructions.push({ action: "rect", data: [t, e, s, r, n] }), 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(t, e, s, r) {
return this.instructions.push({ action: "circle", data: [t, e, s, r] }), this._dirty = !0, this;
}
roundRect(...t) {
return this.instructions.push({ action: "roundRect", data: t }), this._dirty = !0, this;
}
poly(...t) {
return this.instructions.push({ action: "poly", data: t }), this._dirty = !0, this;
}
regularPoly(...t) {
return this.instructions.push({ action: "regularPoly", data: t }), this._dirty = !0, this;
}
roundPoly(...t) {
return this.instructions.push({ action: "roundPoly", data: t }), this._dirty = !0, this;
}
roundShape(...t) {
return this.instructions.push({ action: "roundShape", data: t }), this._dirty = !0, this;
}
filletRect(...t) {
return this.instructions.push({ action: "filletRect", data: t }), this._dirty = !0, this;
}
chamferRect(...t) {
return this.instructions.push({ action: "chamferRect", data: t }), 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(t, e, s, r, n, a, o) {
n = n || r / 2;
const h = -1 * Math.PI / 2 + a, c = s * 2, l = Math.PI * 2 / c, u = [];
for (let d = 0; d < c; d++) {
const p = d % 2 ? n : r, f = d * l + h;
u.push(
t + p * Math.cos(f),
e + p * Math.sin(f)
);
}
return this.poly(u, !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(t = !1) {
const e = new ae();
if (!t)
e.instructions = this.instructions.slice();
else
for (let s = 0; s < this.instructions.length; s++) {
const r = this.instructions[s];
e.instructions.push({ action: r.action, data: r.data.slice() });
}
return e;
}
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(t) {
if (t.isIdentity())
return this;
const e = t.a, s = t.b, r = t.c, n = t.d, a = t.tx, o = t.ty;
let h = 0, c = 0, l = 0, u = 0, d = 0, p = 0, f = 0, g = 0;
for (let m = 0; m < this.instructions.length; m++) {
const y = this.instructions[m], _ = y.data;
switch (y.action) {
case "moveTo":
case "lineTo":
h = _[0], c = _[1], _[0] = e * h + r * c + a, _[1] = s * h + n * c + o;
break;
case "bezierCurveTo":
l = _[0], u = _[1], d = _[2], p = _[3], h = _[4], c = _[5], _[0] = e * l + r * u + a, _[1] = s * l + n * u + o, _[2] = e * d + r * p + a, _[3] = s * d + n * p + o, _[4] = e * h + r * c + a, _[5] = s * h + n * c + o;
break;
case "quadraticCurveTo":
l = _[0], u = _[1], h = _[2], c = _[3], _[0] = e * l + r * u + a, _[1] = s * l + n * u + o, _[2] = e * h + r * c + a, _[3] = s * h + n * c + o;
break;
case "arcToSvg":
h = _[5], c = _[6], f = _[0], g = _[1], _[0] = e * f + r * g, _[1] = s * f + n * g, _[5] = e * h + r * c + a, _[6] = s * h + n * c + o;
break;
case "circle":
_[4] = ye(_[3], t);
break;
case "rect":
_[4] = ye(_[4], t);
break;
case "ellipse":
_[8] = ye(_[8], t);
break;
case "roundRect":
_[5] = ye(_[5], t);
break;
case "addPath":
_[0].transform(t);
break;
case "poly":
_[2] = ye(_[2], t);
break;
default:
it("unknown transform action", y.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(t) {
let e = this.instructions.length - 1, s = this.instructions[e];
if (!s)
return t.x = 0, t.y = 0, t;
for (; s.action === "closePath"; ) {
if (e--, e < 0)
return t.x = 0, t.y = 0, t;
s = this.instructions[e];
}
switch (s.action) {
case "moveTo":
case "lineTo":
t.x = s.data[0], t.y = s.data[1];
break;
case "quadraticCurveTo":
t.x = s.data[2], t.y = s.data[3];
break;
case "bezierCurveTo":
t.x = s.data[4], t.y = s.data[5];
break;
case "arc":
case "arcToSvg":
t.x = s.data[5], t.y = s.data[6];
break;
case "addPath":
s.data[0].getLastPoint(t);
break;
}
return t;
}
}
function ye(i, t) {
return i ? i.prepend(t) : t.clone();
}
function ph(i, t) {
if (typeof i == "string") {
const s = document.createElement("div");
s.innerHTML = i.trim(), i = s.querySelector("svg");
}
const e = {
context: t,
path: new ae()
};
return Jr(i, e, null, null), t;
}
function Jr(i, t, e, s) {
const r = i.children, { fillStyle: n, strokeStyle: a } = mh(i);
n && e ? e = { ...e, ...n } : n && (e = n), a && s ? s = { ...s, ...a } : a && (s = a), t.context.fillStyle = e, t.context.strokeStyle = s;
let o, h, c, l, u, d, p, f, g, m, y, _, x, b, S, k, M;
switch (i.nodeName.toLowerCase()) {
case "path":
b = i.getAttribute("d"), S = new ae(b), t.context.path(S), e && t.context.fill(), s && t.context.stroke();
break;
case "circle":
p = K(i, "cx", 0), f = K(i, "cy", 0), g = K(i, "r", 0), t.context.ellipse(p, f, g, g), e && t.context.fill(), s && t.context.stroke();
break;
case "rect":
o = K(i, "x", 0), h = K(i, "y", 0), k = K(i, "width", 0), M = K(i, "height", 0), m = K(i, "rx", 0), y = K(i, "ry", 0), m || y ? t.context.roundRect(o, h, k, M, m || y) : t.context.rect(o, h, k, M), e && t.context.fill(), s && t.context.stroke();
break;
case "ellipse":
p = K(i, "cx", 0), f = K(i, "cy", 0), m = K(i, "rx", 0), y = K(i, "ry", 0), t.context.beginPath(), t.context.ellipse(p, f, m, y), e && t.context.fill(), s && t.context.stroke();
break;
case "line":
c = K(i, "x1", 0), l = K(i, "y1", 0), u = K(i, "x2", 0), d = K(i, "y2", 0), t.context.beginPath(), t.context.moveTo(c, l), t.context.lineTo(u, d), s && t.context.stroke();
break;
case "polygon":
x = i.getAttribute("points"), _ = x.match(/\d+/g).map((C) => parseInt(C, 10)), t.context.poly(_, !0), e && t.context.fill(), s && t.context.stroke();
break;
case "polyline":
x = i.getAttribute("points"), _ = x.match(/\d+/g).map((C) => parseInt(C, 10)), t.context.poly(_, !1), s && t.context.stroke();
break;
case "g":
case "svg":
break;
default: {
console.info(`[SVG parser] <${i.nodeName}> elements unsupported`);
break;
}
}
for (let C = 0; C < r.length; C++)
Jr(r[C], t, e, s);
}
function K(i, t, e) {
const s = i.getAttribute(t);
return s ? Number(s) : e;
}
function mh(i) {
const t = i.getAttribute("style"), e = {}, s = {};
let r = !1, n = !1;
if (t) {
const a = t.split(";");
for (let o = 0; o < a.length; o++) {
const h = a[o], [c, l] = h.split(":");
switch (c) {
case "stroke":
l !== "none" && (e.color = J.shared.setValue(l).toNumber(), n = !0);
break;
case "stroke-width":
e.width = Number(l);
break;
case "fill":
l !== "none" && (r = !0, s.color = J.shared.setValue(l).toNumber());
break;
case "fill-opacity":
s.alpha = Number(l);
break;
case "stroke-opacity":
e.alpha = Number(l);
break;
case "opacity":
s.alpha = Number(l), e.alpha = Number(l);
break;
}
}
} else {
const a = i.getAttribute("stroke");
a && a !== "none" && (n = !0, e.color = J.shared.setValue(a).toNumber(), e.width = K(i, "stroke-width", 1));
const o = i.getAttribute("fill");
o && o !== "none" && (r = !0, s.color = J.shared.setValue(o).toNumber());
}
return {
strokeStyle: n ? e : null,
fillStyle: r ? s : null
};
}
const Qr = class Wi {
constructor(t, e, s, r) {
this.uid = et("fillGradient"), this.type = "linear", this.gradientStops = [], this.x0 = t, this.y0 = e, this.x1 = s, this.y1 = r;
}
addColorStop(t, e) {
return this.gradientStops.push({ offset: t, color: J.shared.setValue(e).toHex() }), this;
}
// TODO move to the system!
buildLinearGradient() {
const t = Wi.defaultTextureSize, { gradientStops: e } = this, s = Y.get().createCanvas();
s.width = t, s.height = t;
const r = s.getContext("2d"), n = r.createLinearGradient(0, 0, Wi.defaultTextureSize, 1);
for (let g = 0; g < e.length; g++) {
const m = e[g];
n.addColorStop(m.offset, m.color);
}
r.fillStyle = n, r.fillRect(0, 0, t, t), this.texture = new L({
source: new Be({
resource: s,
addressModeU: "clamp-to-edge",
addressModeV: "repeat"
})
});
const { x0: a, y0: o, x1: h, y1: c } = this, l = new D(), u = h - a, d = c - o, p = Math.sqrt(u * u + d * d), f = Math.atan2(d, u);
l.translate(-a, -o), l.scale(1 / t, 1 / t), l.rotate(-f), l.scale(256 / p, 1), this.transform = l;
}
};
Qr.defaultTextureSize = 256;
let tn = Qr;
const Ws = {
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 gh {
constructor(t, e) {
this.uid = et("fillPattern"), this.transform = new D(), this.texture = t, this.transform.scale(
1 / t.frame.width,
1 / t.frame.height
), e && (t.source.style.addressModeU = Ws[e].addressModeU, t.source.style.addressModeV = Ws[e].addressModeV);
}
setTransform(t) {
const e = this.texture;
this.transform.copyFrom(t), this.transform.invert(), this.transform.scale(
1 / e.frame.width,
1 / e.frame.height
);
}
}
function Lt(i, t) {
var a;
if (i == null)
return null;
let e, s;
if (i != null && i.fill ? (s = i.fill, e = { ...t, ...i }) : (s = i, e = t), J.isColorLike(s)) {
const o = J.shared.setValue(s ?? 0);
return {
...e,
color: o.toNumber(),
alpha: o.alpha === 1 ? e.alpha : o.alpha,
texture: L.WHITE
};
} else if (s instanceof gh) {
const o = s;
return {
...e,
color: 16777215,
texture: o.texture,
matrix: o.transform,
fill: e.fill ?? null
};
} else if (s instanceof tn) {
const o = s;
return o.buildLinearGradient(), {
...e,
color: 16777215,
texture: o.texture,
matrix: o.transform
};
}
const r = { ...t, ...i };
if (r.texture) {
if (r.texture !== L.WHITE) {
const h = ((a = r.matrix) == null ? void 0 : a.invert()) || new D();
h.scale(
1 / r.texture.frame.width,
1 / r.texture.frame.height
), r.matrix = h;
}
const o = r.texture.source.style;
o.addressMode === "clamp-to-edge" && (o.addressMode = "repeat");
}
const n = J.shared.setValue(r.color);
return r.alpha *= n.alpha, r.color = n.toNumber(), r.matrix = r.matrix ? r.matrix.clone() : null, r;
}
const yh = new st(), Ns = new D(), ss = class At extends Bt {
constructor() {
super(...arguments), this.uid = et("graphicsContext"), this.dirty = !0, this.batchMode = "auto", this.instructions = [], this._activePath = new ae(), this._transform = new D(), this._fillStyle = { ...At.defaultFillStyle }, this._strokeStyle = { ...At.defaultStrokeStyle }, this._stateStack = [], this._tick = 0, this._bounds = new St(), 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 t = new At();
return t.batchMode = this.batchMode, t.instructions = this.instructions.slice(), t._activePath = this._activePath.clone(), t._transform = this._transform.clone(), t._fillStyle = { ...this._fillStyle }, t._strokeStyle = { ...this._strokeStyle }, t._stateStack = this._stateStack.slice(), t._bounds = this._bounds.clone(), t._boundsDirty = !0, t;
}
/**
* 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(t) {
this._fillStyle = Lt(t, At.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(t) {
this._strokeStyle = Lt(t, At.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(t) {
return this._fillStyle = Lt(t, At.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(t) {
return this._strokeStyle = Lt(t, At.defaultStrokeStyle), this;
}
texture(t, e, s, r, n, a) {
return this.instructions.push({
action: "texture",
data: {
image: t,
dx: s || 0,
dy: r || 0,
dw: n || t.frame.width,
dh: a || t.frame.height,
transform: this._transform.clone(),
alpha: this._fillStyle.alpha,
style: e ? J.shared.setValue(e).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 ae(), this;
}
fill(t, e) {
let s;
const r = this.instructions[this.instructions.length - 1];
return this._tick === 0 && r && r.action === "stroke" ? s = r.data.path : s = this._activePath.clone(), s ? (t != null && (e !== void 0 && typeof t == "number" && (q($, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead"), t = { color: t, alpha: e }), this._fillStyle = Lt(t, At.defaultFillStyle)), this.instructions.push({
action: "fill",
// TODO copy fill style!
data: { style: this.fillStyle, path: s }
}), this.onUpdate(), this._initNextPathLocation(), this._tick = 0, this) : this;
}
_initNextPathLocation() {
const { x: t, y: e } = this._activePath.getLastPoint(st.shared);
this._activePath.clear(), this._activePath.moveTo(t, e);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillStyleInputs 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(t) {
let e;
const s = this.instructions[this.instructions.length - 1];
return this._tick === 0 && s && s.action === "fill" ? e = s.data.path : e = this._activePath.clone(), e ? (t != null && (this._strokeStyle = Lt(t, At.defaultStrokeStyle)), this.instructions.push({
action: "stroke",
// TODO copy fill style!
data: { style: this.strokeStyle, path: e }
}), 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 t = 0; t < 2; t++) {
const e = this.instructions[this.instructions.length - 1 - t], s = this._activePath.clone();
if (e && (e.action === "stroke" || e.action === "fill"))
if (e.data.hole)
e.data.hole.addPath(s);
else {
e.data.hole = s;
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(t, e, s, r, n, a) {
this._tick++;
const o = this._transform;
return this._activePath.arc(
o.a * t + o.c * e + o.tx,
o.b * t + o.d * e + o.ty,
s,
r,
n,
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(t, e, s, r, n) {
this._tick++;
const a = this._transform;
return this._activePath.arcTo(
a.a * t + a.c * e + a.tx,
a.b * t + a.d * e + a.ty,
a.a * s + a.c * r + a.tx,
a.b * s + a.d * r + a.ty,
n
), 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(t, e, s, r, n, a, o) {
this._tick++;
const h = this._transform;
return this._activePath.arcToSvg(
t,
e,
s,
// should we rotate this with transform??
r,
n,
h.a * a + h.c * o + h.tx,
h.b * a + h.d * o + h.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(t, e, s, r, n, a, o) {
this._tick++;
const h = this._transform;
return this._activePath.bezierCurveTo(
h.a * t + h.c * e + h.tx,
h.b * t + h.d * e + h.ty,
h.a * s + h.c * r + h.tx,
h.b * s + h.d * r + h.ty,
h.a * n + h.c * a + h.tx,
h.b * n + h.d * a + h.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 t;
return this._tick++, (t = this._activePath) == null || t.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(t, e, s, r) {
return this._tick++, this._activePath.ellipse(t, e, s, r, 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(t, e, s) {
return this._tick++, this._activePath.circle(t, e, s, 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(t) {
return this._tick++, this._activePath.addPath(t, 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(t, e) {
this._tick++;
const s = this._transform;
return this._activePath.lineTo(
s.a * t + s.c * e + s.tx,
s.b * t + s.d * e + s.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(t, e) {
this._tick++;
const s = this._transform, r = this._activePath.instructions, n = s.a * t + s.c * e + s.tx, a = s.b * t + s.d * e + s.ty;
return r.length === 1 && r[0].action === "moveTo" ? (r[0].data[0] = n, r[0].data[1] = a, this) : (this._activePath.moveTo(
n,
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(t, e, s, r, n) {
this._tick++;
const a = this._transform;
return this._activePath.quadraticCurveTo(
a.a * t + a.c * e + a.tx,
a.b * t + a.d * e + a.ty,
a.a * s + a.c * r + a.tx,
a.b * s + a.d * r + a.ty,
n
), 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(t, e, s, r) {
return this._tick++, this._activePath.rect(t, e, s, r, 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(t, e, s, r, n) {
return this._tick++, this._activePath.roundRect(t, e, s, r, n, 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(t, e) {
return this._tick++, this._activePath.poly(t, e, 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(t, e, s, r, n = 0, a) {
return this._tick++, this._activePath.regularPoly(t, e, s, r, n, 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(t, e, s, r, n, a) {
return this._tick++, this._activePath.roundPoly(t, e, s, r, n, 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(t, e, s, r) {
return this._tick++, this._activePath.roundShape(t, e, s, r), 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(t, e, s, r, n) {
return this._tick++, this._activePath.filletRect(t, e, s, r, n), 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(t, e, s, r, n, a) {
return this._tick++, this._activePath.chamferRect(t, e, s, r, n, 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(t, e, s, r, n = 0, a = 0) {
return this._tick++, this._activePath.star(t, e, s, r, n, 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(t) {
return this._tick++, ph(t, 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 t = this._stateStack.pop();
return t && (this._transform = t.transform, this._fillStyle = t.fillStyle, this._strokeStyle = t.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(t) {
return this._transform.rotate(t), 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(t, e = t) {
return this._transform.scale(t, e), this;
}
setTransform(t, e, s, r, n, a) {
return t instanceof D ? (this._transform.set(t.a, t.b, t.c, t.d, t.tx, t.ty), this) : (this._transform.set(t, e, s, r, n, a), this);
}
transform(t, e, s, r, n, a) {
return t instanceof D ? (this._transform.append(t), this) : (Ns.set(t, e, s, r, n, a), this._transform.append(Ns), 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(t, e = t) {
return this._transform.translate(t, e), 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.dirty || (this.emit("update", this, 16), this.dirty = !0, this._boundsDirty = !0);
}
/** The bounds of the graphic shape. */
get bounds() {
if (!this._boundsDirty)
return this._bounds;
const t = this._bounds;
t.clear();
for (let e = 0; e < this.instructions.length; e++) {
const s = this.instructions[e], r = s.action;
if (r === "fill") {
const n = s.data;
t.addBounds(n.path.bounds);
} else if (r === "texture") {
const n = s.data;
t.addFrame(n.dx, n.dy, n.dx + n.dw, n.dy + n.dh, n.transform);
}
if (r === "stroke") {
const n = s.data, a = n.style.width / 2, o = n.path.bounds;
t.addFrame(
o.minX - a,
o.minY - a,
o.maxX + a,
o.maxY + a
);
}
}
return t;
}
/**
* 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(t) {
var r;
if (!this.bounds.containsPoint(t.x, t.y))
return !1;
const e = this.instructions;
let s = !1;
for (let n = 0; n < e.length; n++) {
const a = e[n], o = a.data, h = o.path;
if (!a.action || !h)
continue;
const c = o.style, l = h.shapePath.shapePrimitives;
for (let u = 0; u < l.length; u++) {
const d = l[u].shape;
if (!c || !d)
continue;
const p = l[u].transform, f = p ? p.applyInverse(t, yh) : t;
a.action === "fill" ? s = d.contains(f.x, f.y) : s = d.strokeContains(f.x, f.y, c.width);
const g = o.hole;
if (g) {
const m = (r = g.shapePath) == null ? void 0 : r.shapePrimitives;
if (m)
for (let y = 0; y < m.length; y++)
m[y].shape.contains(f.x, f.y) && (s = !1);
}
if (s)
return !0;
}
}
return s;
}
/**
* Destroys the GraphicsData object.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the current texture of the fill/stroke style?
* @param {boolean} [options.textureSource=false] - Should it destroy the texture source of the fill/stroke style?
*/
destroy(t = !1) {
if (this._stateStack.length = 0, this._transform = null, this.emit("destroy", this), this.removeAllListeners(), typeof t == "boolean" ? t : t == null ? void 0 : t.texture) {
const s = typeof t == "boolean" ? t : t == null ? void 0 : t.textureSource;
this._fillStyle.texture && this._fillStyle.texture.destroy(s), this._strokeStyle.texture && this._strokeStyle.texture.destroy(s);
}
this._fillStyle = null, this._strokeStyle = null, this.instructions = null, this._activePath = null, this._bounds = null, this._stateStack = null, this.customShader = null, this._transform = null;
}
};
ss.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: L.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
ss.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: L.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
let Dt = ss;
function rs(i, t = 1) {
var s;
const e = (s = oe.RETINA_PREFIX) == null ? void 0 : s.exec(i);
return e ? parseFloat(e[1]) : t;
}
function ns(i, t, e) {
i.label = e, i._sourceOrigin = e;
const s = new L({
source: i,
label: e
}), r = () => {
delete t.promiseCache[e], rt.has(e) && rt.remove(e);
};
return s.source.once("destroy", () => {
t.promiseCache[e] && (it("[Assets] A TextureSource managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the TextureSource."), r());
}), s.once("destroy", () => {
i.destroyed || (it("[Assets] A Texture managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the Texture."), r());
}), s;
}
const _h = ".svg", xh = "image/svg+xml", bh = {
extension: {
type: B.LoadParser,
priority: Zt.Low
},
name: "loadSVG",
config: {
crossOrigin: "anonymous",
parseAsGraphicsContext: !1
},
test(i) {
return he(i, xh) || le(i, _h);
},
async load(i, t, e) {
return t.data.parseAsGraphicsContext ?? this.config.parseAsGraphicsContext ? vh(i) : wh(i, t, e, this.config.crossOrigin);
},
unload(i) {
i.destroy(!0);
}
};
async function wh(i, t, e, s) {
var m, y, _;
const n = await (await Y.get().fetch(i)).blob(), a = URL.createObjectURL(n), o = new Image();
o.src = a, o.crossOrigin = s, await o.decode(), URL.revokeObjectURL(a);
const h = document.createElement("canvas"), c = h.getContext("2d"), l = ((m = t.data) == null ? void 0 : m.resolution) || rs(i), u = ((y = t.data) == null ? void 0 : y.width) ?? o.width, d = ((_ = t.data) == null ? void 0 : _.height) ?? o.height;
h.width = u * l, h.height = d * l, c.drawImage(o, 0, 0, u * l, d * l);
const { parseAsGraphicsContext: p, ...f } = t.data, g = new Be({
resource: h,
alphaMode: "premultiply-alpha-on-upload",
resolution: l,
...f
});
return ns(g, e, i);
}
async function vh(i) {
const e = await (await Y.get().fetch(i)).text(), s = new Dt();
return s.svg(e), s;
}
const Ah = `(function () {
'use strict';
const WHITE_PNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=";
async function checkImageBitmap() {
try {
if (typeof createImageBitmap !== "function")
return false;
const response = await fetch(WHITE_PNG);
const imageBlob = await response.blob();
const imageBitmap = await createImageBitmap(imageBlob);
return imageBitmap.width === 1 && imageBitmap.height === 1;
} catch (e) {
return false;
}
}
void checkImageBitmap().then((result) => {
self.postMessage(result);
});
})();
`;
let ie = null, Ni = class {
constructor() {
ie || (ie = URL.createObjectURL(new Blob([Ah], { type: "application/javascript" }))), this.worker = new Worker(ie);
}
};
Ni.revokeObjectURL = function() {
ie && (URL.revokeObjectURL(ie), ie = null);
};
const Sh = `(function () {
'use strict';
async function loadImageBitmap(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(\`[WorkerManager.loadImageBitmap] Failed to fetch \${url}: \${response.status} \${response.statusText}\`);
}
const imageBlob = await response.blob();
const imageBitmap = await createImageBitmap(imageBlob);
return imageBitmap;
}
self.onmessage = async (event) => {
try {
const imageBitmap = await loadImageBitmap(event.data.data[0]);
self.postMessage({
data: imageBitmap,
uuid: event.data.uuid,
id: event.data.id
}, [imageBitmap]);
} catch (e) {
self.postMessage({
error: e,
uuid: event.data.uuid,
id: event.data.id
});
}
};
})();
`;
let se = null;
class en {
constructor() {
se || (se = URL.createObjectURL(new Blob([Sh], { type: "application/javascript" }))), this.worker = new Worker(se);
}
}
en.revokeObjectURL = function() {
se && (URL.revokeObjectURL(se), se = null);
};
let Ys = 0, Mi;
class Ch {
constructor() {
this._initialized = !1, this._createdWorkers = 0, this._workerPool = [], this._queue = [], this._resolveHash = {};
}
isImageBitmapSupported() {
return this._isImageBitmapSupported !== void 0 ? this._isImageBitmapSupported : (this._isImageBitmapSupported = new Promise((t) => {
const { worker: e } = new Ni();
e.addEventListener("message", (s) => {
e.terminate(), Ni.revokeObjectURL(), t(s.data);
});
}), this._isImageBitmapSupported);
}
loadImageBitmap(t) {
return this._run("loadImageBitmap", [t]);
}
async _initWorkers() {
this._initialized || (this._initialized = !0);
}
_getWorker() {
Mi === void 0 && (Mi = navigator.hardwareConcurrency || 4);
let t = this._workerPool.pop();
return !t && this._createdWorkers < Mi && (this._createdWorkers++, t = new en().worker, t.addEventListener("message", (e) => {
this._complete(e.data), this._returnWorker(e.target), this._next();
})), t;
}
_returnWorker(t) {
this._workerPool.push(t);
}
_complete(t) {
t.error !== void 0 ? this._resolveHash[t.uuid].reject(t.error) : this._resolveHash[t.uuid].resolve(t.data), this._resolveHash[t.uuid] = null;
}
async _run(t, e) {
await this._initWorkers();
const s = new Promise((r, n) => {
this._queue.push({ id: t, arguments: e, resolve: r, reject: n });
});
return this._next(), s;
}
_next() {
if (!this._queue.length)
return;
const t = this._getWorker();
if (!t)
return;
const e = this._queue.pop(), s = e.id;
this._resolveHash[Ys] = { resolve: e.resolve, reject: e.reject }, t.postMessage({
data: e.arguments,
uuid: Ys++,
id: s
});
}
}
const Vs = new Ch(), Mh = [".jpeg", ".jpg", ".png", ".webp", ".avif"], Th = [
"image/jpeg",
"image/png",
"image/webp",
"image/avif"
];
async function Ph(i) {
const t = await Y.get().fetch(i);
if (!t.ok)
throw new Error(`[loadImageBitmap] Failed to fetch ${i}: ${t.status} ${t.statusText}`);
const e = await t.blob();
return await createImageBitmap(e);
}
const sn = {
name: "loadTextures",
extension: {
type: B.LoadParser,
priority: Zt.High
},
config: {
preferWorkers: !0,
preferCreateImageBitmap: !0,
crossOrigin: "anonymous"
},
test(i) {
return he(i, Th) || le(i, Mh);
},
async load(i, t, e) {
var n;
let s = null;
globalThis.createImageBitmap && this.config.preferCreateImageBitmap ? this.config.preferWorkers && await Vs.isImageBitmapSupported() ? s = await Vs.loadImageBitmap(i) : s = await Ph(i) : s = await new Promise((a) => {
s = new Image(), s.crossOrigin = this.config.crossOrigin, s.src = i, s.complete ? a(s) : s.onload = () => {
a(s);
};
});
const r = new Be({
resource: s,
alphaMode: "premultiply-alpha-on-upload",
resolution: ((n = t.data) == null ? void 0 : n.resolution) || rs(i),
...t.data
});
return ns(r, e, i);
},
unload(i) {
i.destroy(!0);
}
}, rn = [".mp4", ".m4v", ".webm", ".ogg", ".ogv", ".h264", ".avi", ".mov"], kh = rn.map((i) => `video/${i.substring(1)}`);
function Ih(i, t, e) {
e === void 0 && !t.startsWith("data:") ? i.crossOrigin = Rh(t) : e !== !1 && (i.crossOrigin = typeof e == "string" ? e : "anonymous");
}
function Eh(i) {
return new Promise((t, e) => {
i.addEventListener("canplaythrough", s), i.addEventListener("error", r), i.load();
function s() {
n(), t();
}
function r(a) {
n(), e(a);
}
function n() {
i.removeEventListener("canplaythrough", s), i.removeEventListener("error", r);
}
});
}
function Rh(i, t = globalThis.location) {
if (i.startsWith("data:"))
return "";
t = t || globalThis.location;
const e = new URL(i, document.baseURI);
return e.hostname !== t.hostname || e.port !== t.port || e.protocol !== t.protocol ? "anonymous" : "";
}
const Bh = {
name: "loadVideo",
extension: {
type: B.LoadParser
},
config: null,
test(i) {
const t = he(i, kh), e = le(i, rn);
return t || e;
},
async load(i, t, e) {
var h, c;
const s = {
...$e.defaultOptions,
resolution: ((h = t.data) == null ? void 0 : h.resolution) || rs(i),
alphaMode: ((c = t.data) == null ? void 0 : c.alphaMode) || await Pr(),
...t.data
}, r = document.createElement("video"), n = {
preload: s.autoLoad !== !1 ? "auto" : void 0,
"webkit-playsinline": s.playsinline !== !1 ? "" : void 0,
playsinline: s.playsinline !== !1 ? "" : void 0,
muted: s.muted === !0 ? "" : void 0,
loop: s.loop === !0 ? "" : void 0,
autoplay: s.autoPlay !== !1 ? "" : void 0
};
Object.keys(n).forEach((l) => {
const u = n[l];
u !== void 0 && r.setAttribute(l, u);
}), s.muted === !0 && (r.muted = !0), Ih(r, i, s.crossorigin);
const a = document.createElement("source");
let o;
if (i.startsWith("data:"))
o = i.slice(5, i.indexOf(";"));
else if (!i.startsWith("blob:")) {
const l = i.split("?")[0].slice(i.lastIndexOf(".") + 1).toLowerCase();
o = $e.MIME_TYPES[l] || `video/${l}`;
}
return a.src = i, o && (a.type = o), new Promise((l) => {
const u = async () => {
const d = new $e({ ...s, resource: r });
r.removeEventListener("canplay", u), t.data.preload && await Eh(r), l(ns(d, e, i));
};
r.addEventListener("canplay", u), r.appendChild(a);
});
},
unload(i) {
i.destroy(!0);
}
}, nn = {
extension: B.ResolveParser,
test: sn.test,
parse: (i) => {
var t;
return {
resolution: parseFloat(((t = oe.RETINA_PREFIX.exec(i)) == null ? void 0 : t[1]) ?? "1"),
format: i.split(".").pop(),
src: i
};
}
}, Fh = {
extension: B.ResolveParser,
test: (i) => oe.RETINA_PREFIX.test(i) && i.endsWith(".json"),
parse: nn.parse
};
class Lh {
constructor() {
this._detections = [], this._initialized = !1, this.resolver = new oe(), this.loader = new eo(), this.cache = rt, this._backgroundLoader = new ja(this.loader), this._backgroundLoader.active = !0, this.reset();
}
/**
* Best practice is to call this function before any loading commences
* Initiating is the best time to add any customization to the way things are loaded.
*
* you do not need to call this for the Assets class to work, only if you want to set any initial properties
* @param options - options to initialize the Assets manager with
*/
async init(t = {}) {
var n, a;
if (this._initialized) {
it("[Assets]AssetManager already initialized, did you load before calling this Assets.init()?");
return;
}
if (this._initialized = !0, t.defaultSearchParams && this.resolver.setDefaultSearchParams(t.defaultSearchParams), t.basePath && (this.resolver.basePath = t.basePath), t.bundleIdentifier && this.resolver.setBundleIdentifier(t.bundleIdentifier), t.manifest) {
let o = t.manifest;
typeof o == "string" && (o = await this.load(o)), this.resolver.addManifest(o);
}
const e = ((n = t.texturePreference) == null ? void 0 : n.resolution) ?? 1, s = typeof e == "number" ? [e] : e, r = await this._detectFormats({
preferredFormats: (a = t.texturePreference) == null ? void 0 : a.format,
skipDetections: t.skipDetections,
detections: this._detections
});
this.resolver.prefer({
params: {
format: r,
resolution: s
}
}), t.preferences && this.setPreferences(t.preferences);
}
/**
* Allows you to specify how to resolve any assets load requests.
* There are a few ways to add things here as shown below:
* @example
* import { Assets } from 'pixi.js';
*
* // Simple
* Assets.add({alias: 'bunnyBooBoo', src: 'bunny.png'});
* const bunny = await Assets.load('bunnyBooBoo');
*
* // Multiple keys:
* Assets.add({alias: ['burger', 'chicken'], src: 'bunny.png'});
*
* const bunny = await Assets.load('burger');
* const bunny2 = await Assets.load('chicken');
*
* // passing options to to the object
* Assets.add({
* alias: 'bunnyBooBooSmooth',
* src: 'bunny{png,webp}',
* data: { scaleMode: SCALE_MODES.NEAREST }, // Base texture options
* });
*
* // Multiple assets
*
* // The following all do the same thing:
*
* Assets.add({alias: 'bunnyBooBoo', src: 'bunny{png,webp}'});
*
* Assets.add({
* alias: 'bunnyBooBoo',
* src: [
* 'bunny.png',
* 'bunny.webp',
* ],
* });
*
* const bunny = await Assets.load('bunnyBooBoo'); // Will try to load WebP if available
* @param assets - the unresolved assets to add to the resolver
*/
add(t) {
this.resolver.add(t);
}
async load(t, e) {
this._initialized || await this.init();
const s = Ke(t), r = gt(t).map((o) => {
if (typeof o != "string") {
const h = this.resolver.getAlias(o);
return h.some((c) => !this.resolver.hasKey(c)) && this.add(o), Array.isArray(h) ? h[0] : h;
}
return this.resolver.hasKey(o) || this.add({ alias: o, src: o }), o;
}), n = this.resolver.resolve(r), a = await this._mapLoadToResolve(n, e);
return s ? a[r[0]] : a;
}
/**
* This adds a bundle of assets in one go so that you can load them as a group.
* For example you could add a bundle for each screen in you pixi app
* @example
* import { Assets } from 'pixi.js';
*
* Assets.addBundle('animals', [
* { alias: 'bunny', src: 'bunny.png' },
* { alias: 'chicken', src: 'chicken.png' },
* { alias: 'thumper', src: 'thumper.png' },
* ]);
* // or
* Assets.addBundle('animals', {
* bunny: 'bunny.png',
* chicken: 'chicken.png',
* thumper: 'thumper.png',
* });
*
* const assets = await Assets.loadBundle('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(t, e) {
this.resolver.addBundle(t, e);
}
/**
* Bundles are a way to load multiple assets at once.
* If a manifest has been provided to the init function then you can load a bundle, or bundles.
* you can also add bundles via `addBundle`
* @example
* import { Assets } from 'pixi.js';
*
* // 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',
* },
* ],
* },
* ]
* };
*
* await Assets.init({ manifest });
*
* // Load a bundle...
* loadScreenAssets = await Assets.loadBundle('load-screen');
* // Load another bundle...
* gameScreenAssets = await Assets.loadBundle('game-screen');
* @param bundleIds - the bundle id or ids to load
* @param onProgress - Optional function that is called when progress on asset loading is made.
* The function is passed a single parameter, `progress`, which represents the percentage (0.0 - 1.0)
* of the assets loaded. Do not use this function to detect when assets are complete and available,
* instead use the Promise returned by this function.
* @returns all the bundles assets or a hash of assets for each bundle specified
*/
async loadBundle(t, e) {
this._initialized || await this.init();
let s = !1;
typeof t == "string" && (s = !0, t = [t]);
const r = this.resolver.resolveBundle(t), n = {}, a = Object.keys(r);
let o = 0, h = 0;
const c = () => {
e == null || e(++o / h);
}, l = a.map((u) => {
const d = r[u];
return h += Object.keys(d).length, this._mapLoadToResolve(d, c).then((p) => {
n[u] = p;
});
});
return await Promise.all(l), s ? n[t[0]] : n;
}
/**
* Initiate a background load of some assets. It will passively begin to load these assets in the background.
* So when you actually come to loading them you will get a promise that resolves to the loaded assets immediately
*
* An example of this might be that you would background load game assets after your inital load.
* then when you got to actually load your game screen assets when a player goes to the game - the loading
* would already have stared or may even be complete, saving you having to show an interim load bar.
* @example
* import { Assets } from 'pixi.js';
*
* Assets.backgroundLoad('bunny.png');
*
* // later on in your app...
* await Assets.loadBundle('bunny.png'); // Will resolve quicker as loading may have completed!
* @param urls - the url / urls you want to background load
*/
async backgroundLoad(t) {
this._initialized || await this.init(), typeof t == "string" && (t = [t]);
const e = this.resolver.resolve(t);
this._backgroundLoader.add(Object.values(e));
}
/**
* Initiate a background of a bundle, works exactly like backgroundLoad but for bundles.
* this can only be used if the loader has been initiated with a manifest
* @example
* import { Assets } from 'pixi.js';
*
* await Assets.init({
* manifest: {
* bundles: [
* {
* name: 'load-screen',
* assets: [...],
* },
* ...
* ],
* },
* });
*
* Assets.backgroundLoadBundle('load-screen');
*
* // Later on in your app...
* await Assets.loadBundle('load-screen'); // Will resolve quicker as loading may have completed!
* @param bundleIds - the bundleId / bundleIds you want to background load
*/
async backgroundLoadBundle(t) {
this._initialized || await this.init(), typeof t == "string" && (t = [t]);
const e = this.resolver.resolveBundle(t);
Object.values(e).forEach((s) => {
this._backgroundLoader.add(Object.values(s));
});
}
/**
* Only intended for development purposes.
* This will wipe the resolver and caches.
* You will need to reinitialize the Asset
*/
reset() {
this.resolver.reset(), this.loader.reset(), this.cache.reset(), this._initialized = !1;
}
get(t) {
if (typeof t == "string")
return rt.get(t);
const e = {};
for (let s = 0; s < t.length; s++)
e[s] = rt.get(t[s]);
return e;
}
/**
* helper function to map resolved assets back to loaded assets
* @param resolveResults - the resolve results from the resolver
* @param onProgress - the progress callback
*/
async _mapLoadToResolve(t, e) {
const s = [...new Set(Object.values(t))];
this._backgroundLoader.active = !1;
const r = await this.loader.load(s, e);
this._backgroundLoader.active = !0;
const n = {};
return s.forEach((a) => {
const o = r[a.src], h = [a.src];
a.alias && h.push(...a.alias), h.forEach((c) => {
n[c] = o;
}), rt.set(h, o);
}), n;
}
/**
* Unload an asset or assets. As the Assets class is responsible for creating the assets via the `load` function
* this will make sure to destroy any assets and release them from memory.
* Once unloaded, you will need to load the asset again.
*
* Use this to help manage assets if you find that you have a large app and you want to free up memory.
*
* - it's up to you as the developer to make sure that textures are not actively being used when you unload them,
* Pixi won't break but you will end up with missing assets. Not a good look for the user!
* @example
* import { Assets } from 'pixi.js';
*
* // Load a URL:
* const myImageTexture = await Assets.load('http://some.url.com/image.png'); // => returns a texture
*
* await Assets.unload('http://some.url.com/image.png')
*
* // myImageTexture will be destroyed now.
*
* // Unload multiple assets:
* const textures = await Assets.unload(['thumper', 'chicko']);
* @param urls - the urls to unload
*/
async unload(t) {
this._initialized || await this.init();
const e = gt(t).map((r) => typeof r != "string" ? r.src : r), s = this.resolver.resolve(e);
await this._unloadFromResolved(s);
}
/**
* Bundles are a way to manage multiple assets at once.
* this will unload all files in a bundle.
*
* once a bundle has been unloaded, you need to load it again to have access to the assets.
* @example
* import { Assets } from 'pixi.js';
*
* Assets.addBundle({
* 'thumper': 'http://some.url.com/thumper.png',
* })
*
* const assets = await Assets.loadBundle('thumper');
*
* // Now to unload...
*
* await Assets.unloadBundle('thumper');
*
* // All assets in the assets object will now have been destroyed and purged from the cache
* @param bundleIds - the bundle id or ids to unload
*/
async unloadBundle(t) {
this._initialized || await this.init(), t = gt(t);
const e = this.resolver.resolveBundle(t), s = Object.keys(e).map((r) => this._unloadFromResolved(e[r]));
await Promise.all(s);
}
async _unloadFromResolved(t) {
const e = Object.values(t);
e.forEach((s) => {
rt.remove(s.src);
}), await this.loader.unload(e);
}
/**
* Detects the supported formats for the browser, and returns an array of supported formats, respecting
* the users preferred formats order.
* @param options - the options to use when detecting formats
* @param options.preferredFormats - the preferred formats to use
* @param options.skipDetections - if we should skip the detections altogether
* @param options.detections - the detections to use
* @returns - the detected formats
*/
async _detectFormats(t) {
let e = [];
t.preferredFormats && (e = Array.isArray(t.preferredFormats) ? t.preferredFormats : [t.preferredFormats]);
for (const s of t.detections)
t.skipDetections || await s.test() ? e = await s.add(e) : t.skipDetections || (e = await s.remove(e));
return e = e.filter((s, r) => e.indexOf(s) === r), e;
}
/** All the detection parsers currently added to the Assets class. */
get detections() {
return this._detections;
}
/**
* General setter for preferences. This is a helper function to set preferences on all parsers.
* @param preferences - the preferences to set
*/
setPreferences(t) {
this.loader.parsers.forEach((e) => {
e.config && Object.keys(e.config).filter((s) => s in t).forEach((s) => {
e.config[s] = t[s];
});
});
}
}
const yt = new Lh();
dt.handleByList(B.LoadParser, yt.loader.parsers).handleByList(B.ResolveParser, yt.resolver.parsers).handleByList(B.CacheParser, yt.cache.parsers).handleByList(B.DetectionParser, yt.detections);
dt.add(
Xa,
qa,
$a,
to,
Za,
Ja,
Qa,
ro,
oo,
go,
bh,
sn,
Bh,
nn,
Fh
);
const js = {
loader: B.LoadParser,
resolver: B.ResolveParser,
cache: B.CacheParser,
detection: B.DetectionParser
};
dt.handle(B.Asset, (i) => {
const t = i.ref;
Object.entries(js).filter(([e]) => !!t[e]).forEach(([e, s]) => dt.add(Object.assign(
t[e],
// Allow the function to optionally define it's own
// ExtensionMetadata, the use cases here is priority for LoaderParsers
{ extension: t[e].extension ?? s }
)));
}, (i) => {
const t = i.ref;
Object.keys(js).filter((e) => !!t[e]).forEach((e) => dt.remove(t[e]));
});
class Ze extends O {
/**
* @param options - Options for the Graphics.
*/
constructor(t) {
t instanceof Dt && (t = { context: t });
const { context: e, roundPixels: s, ...r } = t || {};
super({
label: "Graphics",
...r
}), this.canBundle = !0, this.renderPipeId = "graphics", this._roundPixels = 0, e ? this._context = e : this._context = this._ownedContext = new Dt(), this._context.on("update", this.onViewUpdate, this), this.allowChildren = !1, this.roundPixels = s ?? !1;
}
set context(t) {
t !== this._context && (this._context.off("update", this.onViewUpdate, this), this._context = t, this._context.on("update", this.onViewUpdate, this), this.onViewUpdate());
}
get context() {
return this._context;
}
/**
* The local bounds of the graphic.
* @type {rendering.Bounds}
*/
get bounds() {
return this._context.bounds;
}
/**
* Adds the bounds of this object to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(t) {
t.addBounds(this._context.bounds);
}
/**
* Checks if the object contains the given point.
* @param point - The point to check
*/
containsPoint(t) {
return this._context.containsPoint(t);
}
/**
* Whether or not to round the x/y position of the graphic.
* @type {boolean}
*/
get roundPixels() {
return !!this._roundPixels;
}
set roundPixels(t) {
this._roundPixels = t ? 1 : 0;
}
onViewUpdate() {
if (this._didChangeId += 4096, this._didGraphicsUpdate = !0, this.didViewUpdate)
return;
this.didViewUpdate = !0;
const t = this.renderGroup || this.parentRenderGroup;
t && t.onChildViewUpdate(this);
}
/**
* 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
* @param {boolean} [options.texture=false] - Should destroy the texture of the graphics context
* @param {boolean} [options.textureSource=false] - Should destroy the texture source of the graphics context
* @param {boolean} [options.context=false] - Should destroy the context
*/
destroy(t) {
this._ownedContext && !t ? this._ownedContext.destroy(t) : (t === !0 || (t == null ? void 0 : t.context) === !0) && this._context.destroy(t), this._ownedContext = null, this._context = null, super.destroy(t);
}
_callContextMethod(t, e) {
return this.context[t](...e), this;
}
// --------------------------------------- GraphicsContext methods ---------------------------------------
/**
* 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 {FillStyleInputs} args - 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(...t) {
return this._callContextMethod("setFillStyle", t);
}
/**
* 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 {FillStyleInputs} args - 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(...t) {
return this._callContextMethod("setStrokeStyle", t);
}
fill(...t) {
return this._callContextMethod("fill", t);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillStyleInputs parameter to define the stroke's appearance, including its color, width, and other properties.
* @param {FillStyleInputs} args - (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(...t) {
return this._callContextMethod("stroke", t);
}
texture(...t) {
return this._callContextMethod("texture", t);
}
/**
* 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._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!
*/
cut() {
return this._callContextMethod("cut", []);
}
arc(...t) {
return this._callContextMethod("arc", t);
}
arcTo(...t) {
return this._callContextMethod("arcTo", t);
}
arcToSvg(...t) {
return this._callContextMethod("arcToSvg", t);
}
bezierCurveTo(...t) {
return this._callContextMethod("bezierCurveTo", t);
}
/**
* 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._callContextMethod("closePath", []);
}
ellipse(...t) {
return this._callContextMethod("ellipse", t);
}
circle(...t) {
return this._callContextMethod("circle", t);
}
path(...t) {
return this._callContextMethod("path", t);
}
lineTo(...t) {
return this._callContextMethod("lineTo", t);
}
moveTo(...t) {
return this._callContextMethod("moveTo", t);
}
quadraticCurveTo(...t) {
return this._callContextMethod("quadraticCurveTo", t);
}
rect(...t) {
return this._callContextMethod("rect", t);
}
roundRect(...t) {
return this._callContextMethod("roundRect", t);
}
poly(...t) {
return this._callContextMethod("poly", t);
}
regularPoly(...t) {
return this._callContextMethod("regularPoly", t);
}
roundPoly(...t) {
return this._callContextMethod("roundPoly", t);
}
roundShape(...t) {
return this._callContextMethod("roundShape", t);
}
filletRect(...t) {
return this._callContextMethod("filletRect", t);
}
chamferRect(...t) {
return this._callContextMethod("chamferRect", t);
}
star(...t) {
return this._callContextMethod("star", t);
}
svg(...t) {
return this._callContextMethod("svg", t);
}
restore(...t) {
return this._callContextMethod("restore", t);
}
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save() {
return this._callContextMethod("save", []);
}
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform() {
return this.context.getTransform();
}
/**
* 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._callContextMethod("resetTransform", []);
}
rotateTransform(...t) {
return this._callContextMethod("rotate", t);
}
scaleTransform(...t) {
return this._callContextMethod("scale", t);
}
setTransform(...t) {
return this._callContextMethod("setTransform", t);
}
transform(...t) {
return this._callContextMethod("transform", t);
}
translateTransform(...t) {
return this._callContextMethod("translate", t);
}
/**
* 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._callContextMethod("clear", []);
}
/**
* The fill style to use.
* @type {ConvertedFillStyle}
*/
get fillStyle() {
return this._context.fillStyle;
}
set fillStyle(t) {
this._context.fillStyle = t;
}
/**
* The stroke style to use.
* @type {ConvertedStrokeStyle}
*/
get strokeStyle() {
return this._context.strokeStyle;
}
set strokeStyle(t) {
this._context.strokeStyle = t;
}
/**
* Creates a new Graphics object.
* Note that only the context of the object is cloned, not its transform (position,scale,etc)
* @param deep - Whether to create a deep clone of the graphics object. If false, the context
* will be shared between the two objects (default false). If true, the context will be
* cloned (recommended if you need to modify the context in any way).
* @returns - A clone of the graphics object
*/
clone(t = !1) {
return t ? new Ze(this._context.clone()) : (this._ownedContext = null, new Ze(this._context));
}
// -------- v7 deprecations ---------
/**
* @param width
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
*/
lineStyle(t, e, s) {
q($, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style.");
const r = {};
return t && (r.width = t), e && (r.color = e), s && (r.alpha = s), this.context.strokeStyle = r, this;
}
/**
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
beginFill(t, e) {
q($, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
const s = {};
return t && (s.color = t), e && (s.alpha = e), this.context.fillStyle = s, this;
}
/**
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
endFill() {
q($, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."), this.context.fill();
const t = this.context.strokeStyle;
return (t.width !== Dt.defaultStrokeStyle.width || t.color !== Dt.defaultStrokeStyle.color || t.alpha !== Dt.defaultStrokeStyle.alpha) && this.context.stroke(), this;
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#circle} instead
*/
drawCircle(...t) {
return q($, "Graphics#drawCircle has been renamed to Graphics#circle"), this._callContextMethod("circle", t);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
*/
drawEllipse(...t) {
return q($, "Graphics#drawEllipse has been renamed to Graphics#ellipse"), this._callContextMethod("ellipse", t);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#poly} instead
*/
drawPolygon(...t) {
return q($, "Graphics#drawPolygon has been renamed to Graphics#poly"), this._callContextMethod("poly", t);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#rect} instead
*/
drawRect(...t) {
return q($, "Graphics#drawRect has been renamed to Graphics#rect"), this._callContextMethod("rect", t);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
*/
drawRoundedRect(...t) {
return q($, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect"), this._callContextMethod("roundRect", t);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#star} instead
*/
drawStar(...t) {
return q($, "Graphics#drawStar has been renamed to Graphics#star"), this._callContextMethod("star", t);
}
}
class Re extends xt {
/**
* @param textures - An array of {@link Texture} or frame
* objects that make up the animation.
* @param {boolean} [autoUpdate=true] - Whether to use Ticker.shared to auto update animation time.
*/
constructor(t, e = !0) {
super(t[0] instanceof L ? t[0] : t[0].texture), this._textures = null, this._durations = null, this._autoUpdate = e, this._isConnectedToTicker = !1, this.animationSpeed = 1, this.loop = !0, this.updateAnchor = !1, this.onComplete = null, this.onFrameChange = null, this.onLoop = null, this._currentTime = 0, this._playing = !1, this._previousFrame = null, this.textures = t;
}
/** Stops the AnimatedSprite. */
stop() {
this._playing && (this._playing = !1, this._autoUpdate && this._isConnectedToTicker && (ot.shared.remove(this.update, this), this._isConnectedToTicker = !1));
}
/** Plays the AnimatedSprite. */
play() {
this._playing || (this._playing = !0, this._autoUpdate && !this._isConnectedToTicker && (ot.shared.add(this.update, this, Te.HIGH), this._isConnectedToTicker = !0));
}
/**
* Stops the AnimatedSprite and goes to a specific frame.
* @param frameNumber - Frame index to stop at.
*/
gotoAndStop(t) {
this.stop(), this.currentFrame = t;
}
/**
* Goes to a specific frame and begins playing the AnimatedSprite.
* @param frameNumber - Frame index to start at.
*/
gotoAndPlay(t) {
this.currentFrame = t, this.play();
}
/**
* Updates the object transform for rendering.
* @param ticker - the ticker to use to update the object.
*/
update(t) {
if (!this._playing)
return;
const e = t.deltaTime, s = this.animationSpeed * e, r = this.currentFrame;
if (this._durations !== null) {
let n = this._currentTime % 1 * this._durations[this.currentFrame];
for (n += s / 60 * 1e3; n < 0; )
this._currentTime--, n += this._durations[this.currentFrame];
const a = Math.sign(this.animationSpeed * e);
for (this._currentTime = Math.floor(this._currentTime); n >= this._durations[this.currentFrame]; )
n -= this._durations[this.currentFrame] * a, this._currentTime += a;
this._currentTime += n / this._durations[this.currentFrame];
} else
this._currentTime += s;
this._currentTime < 0 && !this.loop ? (this.gotoAndStop(0), this.onComplete && this.onComplete()) : this._currentTime >= this._textures.length && !this.loop ? (this.gotoAndStop(this._textures.length - 1), this.onComplete && this.onComplete()) : r !== this.currentFrame && (this.loop && this.onLoop && (this.animationSpeed > 0 && this.currentFrame < r || this.animationSpeed < 0 && this.currentFrame > r) && this.onLoop(), this._updateTexture());
}
/** Updates the displayed texture to match the current frame index. */
_updateTexture() {
const t = this.currentFrame;
this._previousFrame !== t && (this._previousFrame = t, this.texture = this._textures[t], this.updateAnchor && this.anchor.copyFrom(this.texture.defaultAnchor), this.onFrameChange && this.onFrameChange(this.currentFrame));
}
/** Stops the AnimatedSprite and destroys it. */
destroy() {
this.stop(), super.destroy(), this.onComplete = null, this.onFrameChange = null, this.onLoop = null;
}
/**
* A short hand way of creating an AnimatedSprite from an array of frame ids.
* @param frames - The array of frames ids the AnimatedSprite will use as its texture frames.
* @returns - The new animated sprite with the specified frames.
*/
static fromFrames(t) {
const e = [];
for (let s = 0; s < t.length; ++s)
e.push(L.from(t[s]));
return new Re(e);
}
/**
* A short hand way of creating an AnimatedSprite from an array of image ids.
* @param images - The array of image urls the AnimatedSprite will use as its texture frames.
* @returns The new animate sprite with the specified images as frames.
*/
static fromImages(t) {
const e = [];
for (let s = 0; s < t.length; ++s)
e.push(L.from(t[s]));
return new Re(e);
}
/**
* The total number of frames in the AnimatedSprite. This is the same as number of textures
* assigned to the AnimatedSprite.
* @readonly
* @default 0
*/
get totalFrames() {
return this._textures.length;
}
/** The array of textures used for this AnimatedSprite. */
get textures() {
return this._textures;
}
set textures(t) {
if (t[0] instanceof L)
this._textures = t, this._durations = null;
else {
this._textures = [], this._durations = [];
for (let e = 0; e < t.length; e++)
this._textures.push(t[e].texture), this._durations.push(t[e].time);
}
this._previousFrame = null, this.gotoAndStop(0), this._updateTexture();
}
/** The AnimatedSprite's current frame index. */
get currentFrame() {
let t = Math.floor(this._currentTime) % this._textures.length;
return t < 0 && (t += this._textures.length), t;
}
set currentFrame(t) {
if (t < 0 || t > this.totalFrames - 1)
throw new Error(`[AnimatedSprite]: Invalid frame index value ${t}, expected to be between 0 and totalFrames ${this.totalFrames}.`);
const e = this.currentFrame;
this._currentTime = t, e !== this.currentFrame && this._updateTexture();
}
/**
* Indicates if the AnimatedSprite is currently playing.
* @readonly
*/
get playing() {
return this._playing;
}
/** Whether to use Ticker.shared to auto update animation time. */
get autoUpdate() {
return this._autoUpdate;
}
set autoUpdate(t) {
t !== this._autoUpdate && (this._autoUpdate = t, !this._autoUpdate && this._isConnectedToTicker ? (ot.shared.remove(this.update, this), this._isConnectedToTicker = !1) : this._autoUpdate && !this._isConnectedToTicker && this._playing && (ot.shared.add(this.update, this), this._isConnectedToTicker = !0));
}
}
class Dh extends O {
constructor(t, e) {
const { text: s, resolution: r, style: n, anchor: a, width: o, height: h, roundPixels: c, ...l } = t;
super({
...l
}), this.batched = !0, this.resolution = null, this._didTextUpdate = !0, this._roundPixels = 0, this._bounds = new St(), this._boundsDirty = !0, this._styleClass = e, this.text = s ?? "", this.style = n, this.resolution = r ?? null, this.allowChildren = !1, this._anchor = new nt(
{
_onUpdate: () => {
this.onViewUpdate();
}
}
), a && (this.anchor = a), this.roundPixels = c ?? !1, o && (this.width = o), h && (this.height = h);
}
/**
* The anchor sets the origin point of the text.
* The default is `(0,0)`, this means the text's origin is the top left.
*
* Setting the anchor to `(0.5,0.5)` means the text's origin is centered.
*
* Setting the anchor to `(1,1)` would mean the text'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
* import { Text } from 'pixi.js';
*
* const text = new Text('hello world');
* text.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
*/
get anchor() {
return this._anchor;
}
set anchor(t) {
typeof t == "number" ? this._anchor.set(t) : this._anchor.copyFrom(t);
}
/**
* Whether or not to round the x/y position of the text.
* @type {boolean}
*/
get roundPixels() {
return !!this._roundPixels;
}
set roundPixels(t) {
this._roundPixels = t ? 1 : 0;
}
/** Set the copy for the text object. To split a line you can use '\n'. */
set text(t) {
t = t.toString(), this._text !== t && (this._text = t, this.onViewUpdate());
}
get text() {
return this._text;
}
get style() {
return this._style;
}
/**
* Set the style of the text.
*
* Set up an event listener to listen for changes on the style object and mark the text as dirty.
*
* If setting the `style` can also be partial {@link AnyTextStyleOptions}.
* @type {
* text.TextStyle |
* Partial<text.TextStyle> |
* text.TextStyleOptions |
* text.HTMLTextStyle |
* Partial<text.HTMLTextStyle> |
* text.HTMLTextStyleOptions
* }
*/
set style(t) {
var e;
t = t || {}, (e = this._style) == null || e.off("update", this.onViewUpdate, this), t instanceof this._styleClass ? this._style = t : this._style = new this._styleClass(t), this._style.on("update", this.onViewUpdate, this), this.onViewUpdate();
}
/**
* The local bounds of the Text.
* @type {rendering.Bounds}
*/
get bounds() {
return this._boundsDirty && (this._updateBounds(), this._boundsDirty = !1), this._bounds;
}
/** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
get width() {
return Math.abs(this.scale.x) * this.bounds.width;
}
set width(t) {
this._setWidth(t, this.bounds.width);
}
/** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
get height() {
return Math.abs(this.scale.y) * this.bounds.height;
}
set height(t) {
this._setHeight(t, this.bounds.height);
}
/**
* Retrieves the size of the Text as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the Text.
*/
getSize(t) {
return t || (t = {}), t.width = Math.abs(this.scale.x) * this.bounds.width, t.height = Math.abs(this.scale.y) * this.bounds.height, t;
}
/**
* Sets the size of the Text to the specified width and height.
* This is faster than setting the width and height separately.
* @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(t, e) {
let s, r;
typeof t != "object" ? (s = t, r = e ?? t) : (s = t.width, r = t.height ?? t.width), s !== void 0 && this._setWidth(s, this.bounds.width), r !== void 0 && this._setHeight(r, this.bounds.height);
}
/**
* Adds the bounds of this text to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(t) {
const e = this.bounds;
t.addFrame(
e.minX,
e.minY,
e.maxX,
e.maxY
);
}
/**
* Checks if the text contains the given point.
* @param point - The point to check
*/
containsPoint(t) {
const e = this.bounds.maxX, s = this.bounds.maxY, r = -e * this.anchor.x;
let n = 0;
return t.x >= r && t.x <= r + e && (n = -s * this.anchor.y, t.y >= n && t.y <= n + s);
}
onViewUpdate() {
if (this._didChangeId += 4096, this._boundsDirty = !0, this.didViewUpdate)
return;
this.didViewUpdate = !0, this._didTextUpdate = !0;
const t = this.renderGroup || this.parentRenderGroup;
t && t.onChildViewUpdate(this);
}
_getKey() {
return `${this.text}:${this._style.styleKey}`;
}
/**
* Destroys this text renderable and optionally its style texture.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the text style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the text style
* @param {boolean} [options.style=false] - Should it destroy the style of the text
*/
destroy(t = !1) {
super.destroy(t), this.owner = null, this._bounds = null, this._anchor = null, (typeof t == "boolean" ? t : t != null && t.style) && this._style.destroy(t), this._style = null, this._text = null;
}
}
function Uh(i, t) {
let e = i[0] ?? {};
return (typeof e == "string" || i[1]) && (q($, `use new ${t}({ text: "hi!", style }) instead`), e = {
text: e,
style: i[1]
}), e;
}
const Oh = [
"serif",
"sans-serif",
"monospace",
"cursive",
"fantasy",
"system-ui"
];
function Gh(i) {
const t = typeof i.fontSize == "number" ? `${i.fontSize}px` : i.fontSize;
let e = i.fontFamily;
Array.isArray(i.fontFamily) || (e = i.fontFamily.split(","));
for (let s = e.length - 1; s >= 0; s--) {
let r = e[s].trim();
!/([\"\'])[^\'\"]+\1/.test(r) && !Oh.includes(r) && (r = `"${r}"`), e[s] = r;
}
return `${i.fontStyle} ${i.fontVariant} ${i.fontWeight} ${t} ${e.join(",")}`;
}
const Ti = {
// TextMetrics requires getImageData readback for measuring fonts.
willReadFrequently: !0
}, wt = class T {
/**
* Checking that we can use modern canvas 2D API.
*
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
* @see TextMetrics.experimentalLetterSpacing
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
*/
static get experimentalLetterSpacingSupported() {
let t = T._experimentalLetterSpacingSupported;
if (t !== void 0) {
const e = Y.get().getCanvasRenderingContext2D().prototype;
t = T._experimentalLetterSpacingSupported = "letterSpacing" in e || "textLetterSpacing" in e;
}
return t;
}
/**
* @param text - the text that was measured
* @param style - the style that was measured
* @param width - the measured width of the text
* @param height - the measured height of the text
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
* @param lineWidths - an array of the line widths for each line matched to `lines`
* @param lineHeight - the measured line height for this style
* @param maxLineWidth - the maximum line width for all measured lines
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
*/
constructor(t, e, s, r, n, a, o, h, c) {
this.text = t, this.style = e, this.width = s, this.height = r, this.lines = n, this.lineWidths = a, this.lineHeight = o, this.maxLineWidth = h, this.fontProperties = c;
}
/**
* Measures the supplied string of text and returns a Rectangle.
* @param text - The text to measure.
* @param style - The text style to use for measuring
* @param canvas - optional specification of the canvas to use for measuring.
* @param wordWrap
* @returns Measured width and height of the text.
*/
static measureText(t = " ", e, s = T._canvas, r = e.wordWrap) {
var _;
const n = `${t}:${e.styleKey}`;
if (T._measurementCache[n])
return T._measurementCache[n];
const a = Gh(e), o = T.measureFont(a);
o.fontSize === 0 && (o.fontSize = e.fontSize, o.ascent = e.fontSize);
const h = T.__context;
h.font = a;
const l = (r ? T._wordWrap(t, e, s) : t).split(/(?:\r\n|\r|\n)/), u = new Array(l.length);
let d = 0;
for (let x = 0; x < l.length; x++) {
const b = T._measureText(l[x], e.letterSpacing, h);
u[x] = b, d = Math.max(d, b);
}
const p = ((_ = e._stroke) == null ? void 0 : _.width) || 0;
let f = d + p;
e.dropShadow && (f += e.dropShadow.distance);
const g = e.lineHeight || o.fontSize + p;
let m = Math.max(g, o.fontSize + p * 2) + (l.length - 1) * (g + e.leading);
return e.dropShadow && (m += e.dropShadow.distance), new T(
t,
e,
f,
m,
l,
u,
g + e.leading,
d,
o
);
}
static _measureText(t, e, s) {
let r = !1;
T.experimentalLetterSpacingSupported && (T.experimentalLetterSpacing ? (s.letterSpacing = `${e}px`, s.textLetterSpacing = `${e}px`, r = !0) : (s.letterSpacing = "0px", s.textLetterSpacing = "0px"));
let n = s.measureText(t).width;
return n > 0 && (r ? n -= e : n += (T.graphemeSegmenter(t).length - 1) * e), n;
}
/**
* Applies newlines to a string to have it optimally fit into the horizontal
* bounds set by the Text object's wordWrapWidth property.
* @param text - String to apply word wrapping to
* @param style - the style to use when wrapping
* @param canvas - optional specification of the canvas to use for measuring.
* @returns New string with new lines applied where required
*/
static _wordWrap(t, e, s = T._canvas) {
const r = s.getContext("2d", Ti);
let n = 0, a = "", o = "";
const h = /* @__PURE__ */ Object.create(null), { letterSpacing: c, whiteSpace: l } = e, u = T._collapseSpaces(l), d = T._collapseNewlines(l);
let p = !u;
const f = e.wordWrapWidth + c, g = T._tokenize(t);
for (let m = 0; m < g.length; m++) {
let y = g[m];
if (T._isNewline(y)) {
if (!d) {
o += T._addLine(a), p = !u, a = "", n = 0;
continue;
}
y = " ";
}
if (u) {
const x = T.isBreakingSpace(y), b = T.isBreakingSpace(a[a.length - 1]);
if (x && b)
continue;
}
const _ = T._getFromCache(y, c, h, r);
if (_ > f)
if (a !== "" && (o += T._addLine(a), a = "", n = 0), T.canBreakWords(y, e.breakWords)) {
const x = T.wordWrapSplit(y);
for (let b = 0; b < x.length; b++) {
let S = x[b], k = S, M = 1;
for (; x[b + M]; ) {
const v = x[b + M];
if (!T.canBreakChars(k, v, y, b, e.breakWords))
S += v;
else
break;
k = v, M++;
}
b += M - 1;
const C = T._getFromCache(S, c, h, r);
C + n > f && (o += T._addLine(a), p = !1, a = "", n = 0), a += S, n += C;
}
} else {
a.length > 0 && (o += T._addLine(a), a = "", n = 0);
const x = m === g.length - 1;
o += T._addLine(y, !x), p = !1, a = "", n = 0;
}
else
_ + n > f && (p = !1, o += T._addLine(a), a = "", n = 0), (a.length > 0 || !T.isBreakingSpace(y) || p) && (a += y, n += _);
}
return o += T._addLine(a, !1), o;
}
/**
* Convienience function for logging each line added during the wordWrap method.
* @param line - The line of text to add
* @param newLine - Add new line character to end
* @returns A formatted line
*/
static _addLine(t, e = !0) {
return t = T._trimRight(t), t = e ? `${t}
` : t, t;
}
/**
* Gets & sets the widths of calculated characters in a cache object
* @param key - The key
* @param letterSpacing - The letter spacing
* @param cache - The cache
* @param context - The canvas context
* @returns The from cache.
*/
static _getFromCache(t, e, s, r) {
let n = s[t];
return typeof n != "number" && (n = T._measureText(t, e, r) + e, s[t] = n), n;
}
/**
* Determines whether we should collapse breaking spaces.
* @param whiteSpace - The TextStyle property whiteSpace
* @returns Should collapse
*/
static _collapseSpaces(t) {
return t === "normal" || t === "pre-line";
}
/**
* Determines whether we should collapse newLine chars.
* @param whiteSpace - The white space
* @returns should collapse
*/
static _collapseNewlines(t) {
return t === "normal";
}
/**
* Trims breaking whitespaces from string.
* @param text - The text
* @returns Trimmed string
*/
static _trimRight(t) {
if (typeof t != "string")
return "";
for (let e = t.length - 1; e >= 0; e--) {
const s = t[e];
if (!T.isBreakingSpace(s))
break;
t = t.slice(0, -1);
}
return t;
}
/**
* Determines if char is a newline.
* @param char - The character
* @returns True if newline, False otherwise.
*/
static _isNewline(t) {
return typeof t != "string" ? !1 : T._newlines.includes(t.charCodeAt(0));
}
/**
* Determines if char is a breaking whitespace.
*
* It allows one to determine whether char should be a breaking whitespace
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param char - The character
* @param [_nextChar] - The next character
* @returns True if whitespace, False otherwise.
*/
static isBreakingSpace(t, e) {
return typeof t != "string" ? !1 : T._breakingSpaces.includes(t.charCodeAt(0));
}
/**
* Splits a string into words, breaking-spaces and newLine characters
* @param text - The text
* @returns A tokenized array
*/
static _tokenize(t) {
const e = [];
let s = "";
if (typeof t != "string")
return e;
for (let r = 0; r < t.length; r++) {
const n = t[r], a = t[r + 1];
if (T.isBreakingSpace(n, a) || T._isNewline(n)) {
s !== "" && (e.push(s), s = ""), e.push(n);
continue;
}
s += n;
}
return s !== "" && e.push(s), e;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to customise which words should break
* Examples are if the token is CJK or numbers.
* It must return a boolean.
* @param _token - The token
* @param breakWords - The style attr break words
* @returns Whether to break word or not
*/
static canBreakWords(t, e) {
return e;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to determine whether a pair of characters
* should be broken by newlines
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param _char - The character
* @param _nextChar - The next character
* @param _token - The token/word the characters are from
* @param _index - The index in the token of the char
* @param _breakWords - The style attr break words
* @returns whether to break word or not
*/
static canBreakChars(t, e, s, r, n) {
return !0;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It is called when a token (usually a word) has to be split into separate pieces
* in order to determine the point to break a word.
* It must return an array of characters.
* @param token - The token to split
* @returns The characters of the token
* @see CanvasTextMetrics.graphemeSegmenter
*/
static wordWrapSplit(t) {
return T.graphemeSegmenter(t);
}
/**
* Calculates the ascent, descent and fontSize of a given font-style
* @param font - String representing the style of the font
* @returns Font properties object
*/
static measureFont(t) {
if (T._fonts[t])
return T._fonts[t];
const e = T._context;
e.font = t;
const s = e.measureText(T.METRICS_STRING + T.BASELINE_SYMBOL), r = {
ascent: s.actualBoundingBoxAscent,
descent: s.actualBoundingBoxDescent,
fontSize: s.actualBoundingBoxAscent + s.actualBoundingBoxDescent
};
return T._fonts[t] = r, r;
}
/**
* Clear font metrics in metrics cache.
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
*/
static clearMetrics(t = "") {
t ? delete T._fonts[t] : T._fonts = {};
}
/**
* Cached canvas element for measuring text
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _canvas() {
if (!T.__canvas) {
let t;
try {
const e = new OffscreenCanvas(0, 0), s = e.getContext("2d", Ti);
if (s != null && s.measureText)
return T.__canvas = e, e;
t = Y.get().createCanvas();
} catch {
t = Y.get().createCanvas();
}
t.width = t.height = 10, T.__canvas = t;
}
return T.__canvas;
}
/**
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _context() {
return T.__context || (T.__context = T._canvas.getContext("2d", Ti)), T.__context;
}
};
wt.METRICS_STRING = "|ÉqÅ";
wt.BASELINE_SYMBOL = "M";
wt.BASELINE_MULTIPLIER = 1.4;
wt.HEIGHT_MULTIPLIER = 2;
wt.graphemeSegmenter = (() => {
if (typeof (Intl == null ? void 0 : Intl.Segmenter) == "function") {
const i = new Intl.Segmenter();
return (t) => [...i.segment(t)].map((e) => e.segment);
}
return (i) => [...i];
})();
wt.experimentalLetterSpacing = !1;
wt._fonts = {};
wt._newlines = [
10,
// line feed
13
// carriage return
];
wt._breakingSpaces = [
9,
// character tabulation
32,
// space
8192,
// en quad
8193,
// em quad
8194,
// en space
8195,
// em space
8196,
// three-per-em space
8197,
// four-per-em space
8198,
// six-per-em space
8200,
// punctuation space
8201,
// thin space
8202,
// hair space
8287,
// medium mathematical space
12288
// ideographic space
];
wt._measurementCache = {};
let an = wt;
const Xs = [
"_fontFamily",
"_fontStyle",
"_fontSize",
"_fontVariant",
"_fontWeight",
"_breakWords",
"_align",
"_leading",
"_letterSpacing",
"_lineHeight",
"_textBaseline",
"_whiteSpace",
"_wordWrap",
"_wordWrapWidth",
"_padding",
"_cssOverrides",
"_trim"
];
function zh(i) {
const t = [];
let e = 0;
for (let s = 0; s < Xs.length; s++) {
const r = Xs[s];
t[e++] = i[r];
}
return e = on(i._fill, t, e), e = Hh(i._stroke, t, e), t.join("-");
}
function on(i, t, e) {
var s;
return i && (t[e++] = i.color, t[e++] = i.alpha, t[e++] = (s = i.fill) == null ? void 0 : s.uid), e;
}
function Hh(i, t, e) {
return i && (e = on(i, t, e), t[e++] = i.width, t[e++] = i.alignment, t[e++] = i.cap, t[e++] = i.join, t[e++] = i.miterLimit), e;
}
const as = class Qt extends Bt {
constructor(t = {}) {
super(), Wh(t);
const e = { ...Qt.defaultTextStyle, ...t };
for (const s in e) {
const r = s;
this[r] = e[s];
}
this.update();
}
/**
* Alignment for multiline text, does not affect single line text.
* @member {'left'|'center'|'right'|'justify'}
*/
get align() {
return this._align;
}
set align(t) {
this._align = t, this.update();
}
/** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
get breakWords() {
return this._breakWords;
}
set breakWords(t) {
this._breakWords = t, this.update();
}
/** Set a drop shadow for the text. */
get dropShadow() {
return this._dropShadow;
}
set dropShadow(t) {
t !== null && typeof t == "object" ? this._dropShadow = {
...Qt.defaultDropShadow,
...t
} : this._dropShadow = t ? {
...Qt.defaultDropShadow
} : null, this.update();
}
/** The font family, can be a single font name, or a list of names where the first is the preferred font. */
get fontFamily() {
return this._fontFamily;
}
set fontFamily(t) {
this._fontFamily = t, this.update();
}
/** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
get fontSize() {
return this._fontSize;
}
set fontSize(t) {
typeof t == "string" ? this._fontSize = parseInt(t, 10) : this._fontSize = t, this.update();
}
/**
* The font style.
* @member {'normal'|'italic'|'oblique'}
*/
get fontStyle() {
return this._fontStyle;
}
set fontStyle(t) {
this._fontStyle = t, this.update();
}
/**
* The font variant.
* @member {'normal'|'small-caps'}
*/
get fontVariant() {
return this._fontVariant;
}
set fontVariant(t) {
this._fontVariant = t, this.update();
}
/**
* The font weight.
* @member {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
get fontWeight() {
return this._fontWeight;
}
set fontWeight(t) {
this._fontWeight = t, this.update();
}
/** The space between lines. */
get leading() {
return this._leading;
}
set leading(t) {
this._leading = t, this.update();
}
/** The amount of spacing between letters, default is 0. */
get letterSpacing() {
return this._letterSpacing;
}
set letterSpacing(t) {
this._letterSpacing = t, this.update();
}
/** The line height, a number that represents the vertical space that a letter uses. */
get lineHeight() {
return this._lineHeight;
}
set lineHeight(t) {
this._lineHeight = t, this.update();
}
/**
* Occasionally some fonts are cropped. Adding some padding will prevent this from happening
* by adding padding to all sides of the text.
*/
get padding() {
return this._padding;
}
set padding(t) {
this._padding = t, this.update();
}
/** Trim transparent borders. This is an expensive operation so only use this if you have to! */
get trim() {
return this._trim;
}
set trim(t) {
this._trim = t, this.update();
}
/**
* The baseline of the text that is rendered.
* @member {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
get textBaseline() {
return this._textBaseline;
}
set textBaseline(t) {
this._textBaseline = t, this.update();
}
/**
* How newlines and spaces should be handled.
* Default is 'pre' (preserve, preserve).
*
* value | New lines | Spaces
* --- | --- | ---
* 'normal' | Collapse | Collapse
* 'pre' | Preserve | Preserve
* 'pre-line' | Preserve | Collapse
* @member {'normal'|'pre'|'pre-line'}
*/
get whiteSpace() {
return this._whiteSpace;
}
set whiteSpace(t) {
this._whiteSpace = t, this.update();
}
/** Indicates if word wrap should be used. */
get wordWrap() {
return this._wordWrap;
}
set wordWrap(t) {
this._wordWrap = t, this.update();
}
/** The width at which text will wrap, it needs wordWrap to be set to true. */
get wordWrapWidth() {
return this._wordWrapWidth;
}
set wordWrapWidth(t) {
this._wordWrapWidth = t, this.update();
}
/** A fillstyle that will be used on the text e.g., 'red', '#00FF00'. */
get fill() {
return this._originalFill;
}
set fill(t) {
t !== this._originalFill && (this._originalFill = t, this._fill = Lt(
t === 0 ? "black" : t,
Dt.defaultFillStyle
), this.update());
}
/** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
get stroke() {
return this._originalStroke;
}
set stroke(t) {
t !== this._originalStroke && (this._originalStroke = t, this._stroke = Lt(t, Dt.defaultStrokeStyle), this.update());
}
_generateKey() {
return this._styleKey = zh(this), this._styleKey;
}
update() {
this._styleKey = null, this.emit("update", this);
}
/** Resets all properties to the default values */
reset() {
const t = Qt.defaultTextStyle;
for (const e in t)
this[e] = t[e];
}
get styleKey() {
return this._styleKey || this._generateKey();
}
/**
* Creates a new TextStyle object with the same values as this one.
* @returns New cloned TextStyle object
*/
clone() {
return new Qt({
align: this.align,
breakWords: this.breakWords,
dropShadow: this.dropShadow,
fill: this._fill,
fontFamily: this.fontFamily,
fontSize: this.fontSize,
fontStyle: this.fontStyle,
fontVariant: this.fontVariant,
fontWeight: this.fontWeight,
leading: this.leading,
letterSpacing: this.letterSpacing,
lineHeight: this.lineHeight,
padding: this.padding,
stroke: this._stroke,
textBaseline: this.textBaseline,
whiteSpace: this.whiteSpace,
wordWrap: this.wordWrap,
wordWrapWidth: this.wordWrapWidth
});
}
/**
* Destroys this text style.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the this style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the this style
*/
destroy(t = !1) {
var s, r, n, a;
if (this.removeAllListeners(), typeof t == "boolean" ? t : t == null ? void 0 : t.texture) {
const o = typeof t == "boolean" ? t : t == null ? void 0 : t.textureSource;
(s = this._fill) != null && s.texture && this._fill.texture.destroy(o), (r = this._originalFill) != null && r.texture && this._originalFill.texture.destroy(o), (n = this._stroke) != null && n.texture && this._stroke.texture.destroy(o), (a = this._originalStroke) != null && a.texture && this._originalStroke.texture.destroy(o);
}
this._fill = null, this._stroke = null, this.dropShadow = null, this._originalStroke = null, this._originalFill = null;
}
};
as.defaultDropShadow = {
/** Set alpha for the drop shadow */
alpha: 1,
/** Set a angle of the drop shadow */
angle: Math.PI / 6,
/** Set a shadow blur radius */
blur: 0,
/** A fill style to be used on the e.g., 'red', '#00FF00' */
color: "black",
/** Set a distance of the drop shadow */
distance: 5
};
as.defaultTextStyle = {
/**
* See {@link TextStyle.align}
* @type {'left'|'center'|'right'|'justify'}
*/
align: "left",
/** See {@link TextStyle.breakWords} */
breakWords: !1,
/** See {@link TextStyle.dropShadow} */
dropShadow: null,
/**
* See {@link TextStyle.fill}
* @type {string|string[]|number|number[]|CanvasGradient|CanvasPattern}
*/
fill: "black",
/**
* See {@link TextStyle.fontFamily}
* @type {string|string[]}
*/
fontFamily: "Arial",
/**
* See {@link TextStyle.fontSize}
* @type {number|string}
*/
fontSize: 26,
/**
* See {@link TextStyle.fontStyle}
* @type {'normal'|'italic'|'oblique'}
*/
fontStyle: "normal",
/**
* See {@link TextStyle.fontVariant}
* @type {'normal'|'small-caps'}
*/
fontVariant: "normal",
/**
* See {@link TextStyle.fontWeight}
* @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
fontWeight: "normal",
/** See {@link TextStyle.leading} */
leading: 0,
/** See {@link TextStyle.letterSpacing} */
letterSpacing: 0,
/** See {@link TextStyle.lineHeight} */
lineHeight: 0,
/** See {@link TextStyle.padding} */
padding: 0,
/**
* See {@link TextStyle.stroke}
* @type {string|number}
*/
stroke: null,
/**
* See {@link TextStyle.textBaseline}
* @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
textBaseline: "alphabetic",
/** See {@link TextStyle.trim} */
trim: !1,
/**
* See {@link TextStyle.whiteSpace}
* @type {'normal'|'pre'|'pre-line'}
*/
whiteSpace: "pre",
/** See {@link TextStyle.wordWrap} */
wordWrap: !1,
/** See {@link TextStyle.wordWrapWidth} */
wordWrapWidth: 100
};
let hn = as;
function Wh(i) {
const t = i;
if (typeof t.dropShadow == "boolean" && t.dropShadow) {
const e = hn.defaultDropShadow;
i.dropShadow = {
alpha: t.dropShadowAlpha ?? e.alpha,
angle: t.dropShadowAngle ?? e.angle,
blur: t.dropShadowBlur ?? e.blur,
color: t.dropShadowColor ?? e.color,
distance: t.dropShadowDistance ?? e.distance
};
}
if (t.strokeThickness !== void 0) {
q($, "strokeThickness is now a part of stroke");
const e = t.stroke;
i.stroke = {
color: e,
width: t.strokeThickness
};
}
if (Array.isArray(t.fill)) {
q($, "gradient fill is now a fill pattern: `new FillGradient(...)`");
const e = new tn(0, 0, 0, i.fontSize * 1.7), s = t.fill.map((r) => J.shared.setValue(r).toNumber());
s.forEach((r, n) => {
const a = t.fillGradientStops[n] ?? n / s.length;
e.addColorStop(a, r);
}), i.fill = {
fill: e
};
}
}
class Je extends Dh {
constructor(...t) {
const e = Uh(t, "Text");
super(e, hn), this.renderPipeId = "text";
}
_updateBounds() {
const t = this._bounds, e = this._style.padding, s = this._anchor, r = an.measureText(
this._text,
this._style
), { width: n, height: a } = r;
t.minX = -s._x * n - e, t.maxX = t.minX + n + e * 2, t.minY = -s._y * a - e, t.maxY = t.minY + a + e * 2;
}
}
dt.add(vn, An);
const Ut = 0.02 * 1e3, Nh = (i) => i.name == "jump", Yh = (i) => i.name == "color", Vh = (i) => i.name == "grow", jh = (i) => i.name == "dash", Xh = (i) => i.name == "sprite", $h = (i) => i.name == "add_jump_hits", qh = (i) => i.name == "resurrect";
function Qe(i) {
"@babel/helpers - typeof";
return Qe = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(t) {
return typeof t;
} : function(t) {
return t && typeof Symbol == "function" && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t;
}, Qe(i);
}
var Kh = /^\s+/, Zh = /\s+$/;
function P(i, t) {
if (i = i || "", t = t || {}, i instanceof P)
return i;
if (!(this instanceof P))
return new P(i, t);
var e = Jh(i);
this._originalInput = i, this._r = e.r, this._g = e.g, this._b = e.b, this._a = e.a, this._roundA = Math.round(100 * this._a) / 100, this._format = t.format || e.format, this._gradientType = t.gradientType, this._r < 1 && (this._r = Math.round(this._r)), this._g < 1 && (this._g = Math.round(this._g)), this._b < 1 && (this._b = Math.round(this._b)), this._ok = e.ok;
}
P.prototype = {
isDark: function() {
return this.getBrightness() < 128;
},
isLight: function() {
return !this.isDark();
},
isValid: function() {
return this._ok;
},
getOriginalInput: function() {
return this._originalInput;
},
getFormat: function() {
return this._format;
},
getAlpha: function() {
return this._a;
},
getBrightness: function() {
var t = this.toRgb();
return (t.r * 299 + t.g * 587 + t.b * 114) / 1e3;
},
getLuminance: function() {
var t = this.toRgb(), e, s, r, n, a, o;
return e = t.r / 255, s = t.g / 255, r = t.b / 255, e <= 0.03928 ? n = e / 12.92 : n = Math.pow((e + 0.055) / 1.055, 2.4), s <= 0.03928 ? a = s / 12.92 : a = Math.pow((s + 0.055) / 1.055, 2.4), r <= 0.03928 ? o = r / 12.92 : o = Math.pow((r + 0.055) / 1.055, 2.4), 0.2126 * n + 0.7152 * a + 0.0722 * o;
},
setAlpha: function(t) {
return this._a = ln(t), this._roundA = Math.round(100 * this._a) / 100, this;
},
toHsv: function() {
var t = qs(this._r, this._g, this._b);
return {
h: t.h * 360,
s: t.s,
v: t.v,
a: this._a
};
},
toHsvString: function() {
var t = qs(this._r, this._g, this._b), e = Math.round(t.h * 360), s = Math.round(t.s * 100), r = Math.round(t.v * 100);
return this._a == 1 ? "hsv(" + e + ", " + s + "%, " + r + "%)" : "hsva(" + e + ", " + s + "%, " + r + "%, " + this._roundA + ")";
},
toHsl: function() {
var t = $s(this._r, this._g, this._b);
return {
h: t.h * 360,
s: t.s,
l: t.l,
a: this._a
};
},
toHslString: function() {
var t = $s(this._r, this._g, this._b), e = Math.round(t.h * 360), s = Math.round(t.s * 100), r = Math.round(t.l * 100);
return this._a == 1 ? "hsl(" + e + ", " + s + "%, " + r + "%)" : "hsla(" + e + ", " + s + "%, " + r + "%, " + this._roundA + ")";
},
toHex: function(t) {
return Ks(this._r, this._g, this._b, t);
},
toHexString: function(t) {
return "#" + this.toHex(t);
},
toHex8: function(t) {
return il(this._r, this._g, this._b, this._a, t);
},
toHex8String: function(t) {
return "#" + this.toHex8(t);
},
toRgb: function() {
return {
r: Math.round(this._r),
g: Math.round(this._g),
b: Math.round(this._b),
a: this._a
};
},
toRgbString: function() {
return this._a == 1 ? "rgb(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ")" : "rgba(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ", " + this._roundA + ")";
},
toPercentageRgb: function() {
return {
r: Math.round(G(this._r, 255) * 100) + "%",
g: Math.round(G(this._g, 255) * 100) + "%",
b: Math.round(G(this._b, 255) * 100) + "%",
a: this._a
};
},
toPercentageRgbString: function() {
return this._a == 1 ? "rgb(" + Math.round(G(this._r, 255) * 100) + "%, " + Math.round(G(this._g, 255) * 100) + "%, " + Math.round(G(this._b, 255) * 100) + "%)" : "rgba(" + Math.round(G(this._r, 255) * 100) + "%, " + Math.round(G(this._g, 255) * 100) + "%, " + Math.round(G(this._b, 255) * 100) + "%, " + this._roundA + ")";
},
toName: function() {
return this._a === 0 ? "transparent" : this._a < 1 ? !1 : pl[Ks(this._r, this._g, this._b, !0)] || !1;
},
toFilter: function(t) {
var e = "#" + Zs(this._r, this._g, this._b, this._a), s = e, r = this._gradientType ? "GradientType = 1, " : "";
if (t) {
var n = P(t);
s = "#" + Zs(n._r, n._g, n._b, n._a);
}
return "progid:DXImageTransform.Microsoft.gradient(" + r + "startColorstr=" + e + ",endColorstr=" + s + ")";
},
toString: function(t) {
var e = !!t;
t = t || this._format;
var s = !1, r = this._a < 1 && this._a >= 0, n = !e && r && (t === "hex" || t === "hex6" || t === "hex3" || t === "hex4" || t === "hex8" || t === "name");
return n ? t === "name" && this._a === 0 ? this.toName() : this.toRgbString() : (t === "rgb" && (s = this.toRgbString()), t === "prgb" && (s = this.toPercentageRgbString()), (t === "hex" || t === "hex6") && (s = this.toHexString()), t === "hex3" && (s = this.toHexString(!0)), t === "hex4" && (s = this.toHex8String(!0)), t === "hex8" && (s = this.toHex8String()), t === "name" && (s = this.toName()), t === "hsl" && (s = this.toHslString()), t === "hsv" && (s = this.toHsvString()), s || this.toHexString());
},
clone: function() {
return P(this.toString());
},
_applyModification: function(t, e) {
var s = t.apply(null, [this].concat([].slice.call(e)));
return this._r = s._r, this._g = s._g, this._b = s._b, this.setAlpha(s._a), this;
},
lighten: function() {
return this._applyModification(al, arguments);
},
brighten: function() {
return this._applyModification(ol, arguments);
},
darken: function() {
return this._applyModification(hl, arguments);
},
desaturate: function() {
return this._applyModification(sl, arguments);
},
saturate: function() {
return this._applyModification(rl, arguments);
},
greyscale: function() {
return this._applyModification(nl, arguments);
},
spin: function() {
return this._applyModification(ll, arguments);
},
_applyCombination: function(t, e) {
return t.apply(null, [this].concat([].slice.call(e)));
},
analogous: function() {
return this._applyCombination(dl, arguments);
},
complement: function() {
return this._applyCombination(cl, arguments);
},
monochromatic: function() {
return this._applyCombination(fl, arguments);
},
splitcomplement: function() {
return this._applyCombination(ul, arguments);
},
// Disabled until https://github.com/bgrins/TinyColor/issues/254
// polyad: function (number) {
// return this._applyCombination(polyad, [number]);
// },
triad: function() {
return this._applyCombination(Js, [3]);
},
tetrad: function() {
return this._applyCombination(Js, [4]);
}
};
P.fromRatio = function(i, t) {
if (Qe(i) == "object") {
var e = {};
for (var s in i)
i.hasOwnProperty(s) && (s === "a" ? e[s] = i[s] : e[s] = be(i[s]));
i = e;
}
return P(i, t);
};
function Jh(i) {
var t = {
r: 0,
g: 0,
b: 0
}, e = 1, s = null, r = null, n = null, a = !1, o = !1;
return typeof i == "string" && (i = _l(i)), Qe(i) == "object" && (Pt(i.r) && Pt(i.g) && Pt(i.b) ? (t = Qh(i.r, i.g, i.b), a = !0, o = String(i.r).substr(-1) === "%" ? "prgb" : "rgb") : Pt(i.h) && Pt(i.s) && Pt(i.v) ? (s = be(i.s), r = be(i.v), t = el(i.h, s, r), a = !0, o = "hsv") : Pt(i.h) && Pt(i.s) && Pt(i.l) && (s = be(i.s), n = be(i.l), t = tl(i.h, s, n), a = !0, o = "hsl"), i.hasOwnProperty("a") && (e = i.a)), e = ln(e), {
ok: a,
format: i.format || o,
r: Math.min(255, Math.max(t.r, 0)),
g: Math.min(255, Math.max(t.g, 0)),
b: Math.min(255, Math.max(t.b, 0)),
a: e
};
}
function Qh(i, t, e) {
return {
r: G(i, 255) * 255,
g: G(t, 255) * 255,
b: G(e, 255) * 255
};
}
function $s(i, t, e) {
i = G(i, 255), t = G(t, 255), e = G(e, 255);
var s = Math.max(i, t, e), r = Math.min(i, t, e), n, a, o = (s + r) / 2;
if (s == r)
n = a = 0;
else {
var h = s - r;
switch (a = o > 0.5 ? h / (2 - s - r) : h / (s + r), s) {
case i:
n = (t - e) / h + (t < e ? 6 : 0);
break;
case t:
n = (e - i) / h + 2;
break;
case e:
n = (i - t) / h + 4;
break;
}
n /= 6;
}
return {
h: n,
s: a,
l: o
};
}
function tl(i, t, e) {
var s, r, n;
i = G(i, 360), t = G(t, 100), e = G(e, 100);
function a(c, l, u) {
return u < 0 && (u += 1), u > 1 && (u -= 1), u < 1 / 6 ? c + (l - c) * 6 * u : u < 1 / 2 ? l : u < 2 / 3 ? c + (l - c) * (2 / 3 - u) * 6 : c;
}
if (t === 0)
s = r = n = e;
else {
var o = e < 0.5 ? e * (1 + t) : e + t - e * t, h = 2 * e - o;
s = a(h, o, i + 1 / 3), r = a(h, o, i), n = a(h, o, i - 1 / 3);
}
return {
r: s * 255,
g: r * 255,
b: n * 255
};
}
function qs(i, t, e) {
i = G(i, 255), t = G(t, 255), e = G(e, 255);
var s = Math.max(i, t, e), r = Math.min(i, t, e), n, a, o = s, h = s - r;
if (a = s === 0 ? 0 : h / s, s == r)
n = 0;
else {
switch (s) {
case i:
n = (t - e) / h + (t < e ? 6 : 0);
break;
case t:
n = (e - i) / h + 2;
break;
case e:
n = (i - t) / h + 4;
break;
}
n /= 6;
}
return {
h: n,
s: a,
v: o
};
}
function el(i, t, e) {
i = G(i, 360) * 6, t = G(t, 100), e = G(e, 100);
var s = Math.floor(i), r = i - s, n = e * (1 - t), a = e * (1 - r * t), o = e * (1 - (1 - r) * t), h = s % 6, c = [e, a, n, n, o, e][h], l = [o, e, e, a, n, n][h], u = [n, n, o, e, e, a][h];
return {
r: c * 255,
g: l * 255,
b: u * 255
};
}
function Ks(i, t, e, s) {
var r = [_t(Math.round(i).toString(16)), _t(Math.round(t).toString(16)), _t(Math.round(e).toString(16))];
return s && r[0].charAt(0) == r[0].charAt(1) && r[1].charAt(0) == r[1].charAt(1) && r[2].charAt(0) == r[2].charAt(1) ? r[0].charAt(0) + r[1].charAt(0) + r[2].charAt(0) : r.join("");
}
function il(i, t, e, s, r) {
var n = [_t(Math.round(i).toString(16)), _t(Math.round(t).toString(16)), _t(Math.round(e).toString(16)), _t(cn(s))];
return r && n[0].charAt(0) == n[0].charAt(1) && n[1].charAt(0) == n[1].charAt(1) && n[2].charAt(0) == n[2].charAt(1) && n[3].charAt(0) == n[3].charAt(1) ? n[0].charAt(0) + n[1].charAt(0) + n[2].charAt(0) + n[3].charAt(0) : n.join("");
}
function Zs(i, t, e, s) {
var r = [_t(cn(s)), _t(Math.round(i).toString(16)), _t(Math.round(t).toString(16)), _t(Math.round(e).toString(16))];
return r.join("");
}
P.equals = function(i, t) {
return !i || !t ? !1 : P(i).toRgbString() == P(t).toRgbString();
};
P.random = function() {
return P.fromRatio({
r: Math.random(),
g: Math.random(),
b: Math.random()
});
};
function sl(i, t) {
t = t === 0 ? 0 : t || 10;
var e = P(i).toHsl();
return e.s -= t / 100, e.s = ri(e.s), P(e);
}
function rl(i, t) {
t = t === 0 ? 0 : t || 10;
var e = P(i).toHsl();
return e.s += t / 100, e.s = ri(e.s), P(e);
}
function nl(i) {
return P(i).desaturate(100);
}
function al(i, t) {
t = t === 0 ? 0 : t || 10;
var e = P(i).toHsl();
return e.l += t / 100, e.l = ri(e.l), P(e);
}
function ol(i, t) {
t = t === 0 ? 0 : t || 10;
var e = P(i).toRgb();
return e.r = Math.max(0, Math.min(255, e.r - Math.round(255 * -(t / 100)))), e.g = Math.max(0, Math.min(255, e.g - Math.round(255 * -(t / 100)))), e.b = Math.max(0, Math.min(255, e.b - Math.round(255 * -(t / 100)))), P(e);
}
function hl(i, t) {
t = t === 0 ? 0 : t || 10;
var e = P(i).toHsl();
return e.l -= t / 100, e.l = ri(e.l), P(e);
}
function ll(i, t) {
var e = P(i).toHsl(), s = (e.h + t) % 360;
return e.h = s < 0 ? 360 + s : s, P(e);
}
function cl(i) {
var t = P(i).toHsl();
return t.h = (t.h + 180) % 360, P(t);
}
function Js(i, t) {
if (isNaN(t) || t <= 0)
throw new Error("Argument to polyad must be a positive number");
for (var e = P(i).toHsl(), s = [P(i)], r = 360 / t, n = 1; n < t; n++)
s.push(P({
h: (e.h + n * r) % 360,
s: e.s,
l: e.l
}));
return s;
}
function ul(i) {
var t = P(i).toHsl(), e = t.h;
return [P(i), P({
h: (e + 72) % 360,
s: t.s,
l: t.l
}), P({
h: (e + 216) % 360,
s: t.s,
l: t.l
})];
}
function dl(i, t, e) {
t = t || 6, e = e || 30;
var s = P(i).toHsl(), r = 360 / e, n = [P(i)];
for (s.h = (s.h - (r * t >> 1) + 720) % 360; --t; )
s.h = (s.h + r) % 360, n.push(P(s));
return n;
}
function fl(i, t) {
t = t || 6;
for (var e = P(i).toHsv(), s = e.h, r = e.s, n = e.v, a = [], o = 1 / t; t--; )
a.push(P({
h: s,
s: r,
v: n
})), n = (n + o) % 1;
return a;
}
P.mix = function(i, t, e) {
e = e === 0 ? 0 : e || 50;
var s = P(i).toRgb(), r = P(t).toRgb(), n = e / 100, a = {
r: (r.r - s.r) * n + s.r,
g: (r.g - s.g) * n + s.g,
b: (r.b - s.b) * n + s.b,
a: (r.a - s.a) * n + s.a
};
return P(a);
};
P.readability = function(i, t) {
var e = P(i), s = P(t);
return (Math.max(e.getLuminance(), s.getLuminance()) + 0.05) / (Math.min(e.getLuminance(), s.getLuminance()) + 0.05);
};
P.isReadable = function(i, t, e) {
var s = P.readability(i, t), r, n;
switch (n = !1, r = xl(e), r.level + r.size) {
case "AAsmall":
case "AAAlarge":
n = s >= 4.5;
break;
case "AAlarge":
n = s >= 3;
break;
case "AAAsmall":
n = s >= 7;
break;
}
return n;
};
P.mostReadable = function(i, t, e) {
var s = null, r = 0, n, a, o, h;
e = e || {}, a = e.includeFallbackColors, o = e.level, h = e.size;
for (var c = 0; c < t.length; c++)
n = P.readability(i, t[c]), n > r && (r = n, s = P(t[c]));
return P.isReadable(i, s, {
level: o,
size: h
}) || !a ? s : (e.includeFallbackColors = !1, P.mostReadable(i, ["#fff", "#000"], e));
};
var Yi = P.names = {
aliceblue: "f0f8ff",
antiquewhite: "faebd7",
aqua: "0ff",
aquamarine: "7fffd4",
azure: "f0ffff",
beige: "f5f5dc",
bisque: "ffe4c4",
black: "000",
blanchedalmond: "ffebcd",
blue: "00f",
blueviolet: "8a2be2",
brown: "a52a2a",
burlywood: "deb887",
burntsienna: "ea7e5d",
cadetblue: "5f9ea0",
chartreuse: "7fff00",
chocolate: "d2691e",
coral: "ff7f50",
cornflowerblue: "6495ed",
cornsilk: "fff8dc",
crimson: "dc143c",
cyan: "0ff",
darkblue: "00008b",
darkcyan: "008b8b",
darkgoldenrod: "b8860b",
darkgray: "a9a9a9",
darkgreen: "006400",
darkgrey: "a9a9a9",
darkkhaki: "bdb76b",
darkmagenta: "8b008b",
darkolivegreen: "556b2f",
darkorange: "ff8c00",
darkorchid: "9932cc",
darkred: "8b0000",
darksalmon: "e9967a",
darkseagreen: "8fbc8f",
darkslateblue: "483d8b",
darkslategray: "2f4f4f",
darkslategrey: "2f4f4f",
darkturquoise: "00ced1",
darkviolet: "9400d3",
deeppink: "ff1493",
deepskyblue: "00bfff",
dimgray: "696969",
dimgrey: "696969",
dodgerblue: "1e90ff",
firebrick: "b22222",
floralwhite: "fffaf0",
forestgreen: "228b22",
fuchsia: "f0f",
gainsboro: "dcdcdc",
ghostwhite: "f8f8ff",
gold: "ffd700",
goldenrod: "daa520",
gray: "808080",
green: "008000",
greenyellow: "adff2f",
grey: "808080",
honeydew: "f0fff0",
hotpink: "ff69b4",
indianred: "cd5c5c",
indigo: "4b0082",
ivory: "fffff0",
khaki: "f0e68c",
lavender: "e6e6fa",
lavenderblush: "fff0f5",
lawngreen: "7cfc00",
lemonchiffon: "fffacd",
lightblue: "add8e6",
lightcoral: "f08080",
lightcyan: "e0ffff",
lightgoldenrodyellow: "fafad2",
lightgray: "d3d3d3",
lightgreen: "90ee90",
lightgrey: "d3d3d3",
lightpink: "ffb6c1",
lightsalmon: "ffa07a",
lightseagreen: "20b2aa",
lightskyblue: "87cefa",
lightslategray: "789",
lightslategrey: "789",
lightsteelblue: "b0c4de",
lightyellow: "ffffe0",
lime: "0f0",
limegreen: "32cd32",
linen: "faf0e6",
magenta: "f0f",
maroon: "800000",
mediumaquamarine: "66cdaa",
mediumblue: "0000cd",
mediumorchid: "ba55d3",
mediumpurple: "9370db",
mediumseagreen: "3cb371",
mediumslateblue: "7b68ee",
mediumspringgreen: "00fa9a",
mediumturquoise: "48d1cc",
mediumvioletred: "c71585",
midnightblue: "191970",
mintcream: "f5fffa",
mistyrose: "ffe4e1",
moccasin: "ffe4b5",
navajowhite: "ffdead",
navy: "000080",
oldlace: "fdf5e6",
olive: "808000",
olivedrab: "6b8e23",
orange: "ffa500",
orangered: "ff4500",
orchid: "da70d6",
palegoldenrod: "eee8aa",
palegreen: "98fb98",
paleturquoise: "afeeee",
palevioletred: "db7093",
papayawhip: "ffefd5",
peachpuff: "ffdab9",
peru: "cd853f",
pink: "ffc0cb",
plum: "dda0dd",
powderblue: "b0e0e6",
purple: "800080",
rebeccapurple: "663399",
red: "f00",
rosybrown: "bc8f8f",
royalblue: "4169e1",
saddlebrown: "8b4513",
salmon: "fa8072",
sandybrown: "f4a460",
seagreen: "2e8b57",
seashell: "fff5ee",
sienna: "a0522d",
silver: "c0c0c0",
skyblue: "87ceeb",
slateblue: "6a5acd",
slategray: "708090",
slategrey: "708090",
snow: "fffafa",
springgreen: "00ff7f",
steelblue: "4682b4",
tan: "d2b48c",
teal: "008080",
thistle: "d8bfd8",
tomato: "ff6347",
turquoise: "40e0d0",
violet: "ee82ee",
wheat: "f5deb3",
white: "fff",
whitesmoke: "f5f5f5",
yellow: "ff0",
yellowgreen: "9acd32"
}, pl = P.hexNames = ml(Yi);
function ml(i) {
var t = {};
for (var e in i)
i.hasOwnProperty(e) && (t[i[e]] = e);
return t;
}
function ln(i) {
return i = parseFloat(i), (isNaN(i) || i < 0 || i > 1) && (i = 1), i;
}
function G(i, t) {
gl(i) && (i = "100%");
var e = yl(i);
return i = Math.min(t, Math.max(0, parseFloat(i))), e && (i = parseInt(i * t, 10) / 100), Math.abs(i - t) < 1e-6 ? 1 : i % t / parseFloat(t);
}
function ri(i) {
return Math.min(1, Math.max(0, i));
}
function lt(i) {
return parseInt(i, 16);
}
function gl(i) {
return typeof i == "string" && i.indexOf(".") != -1 && parseFloat(i) === 1;
}
function yl(i) {
return typeof i == "string" && i.indexOf("%") != -1;
}
function _t(i) {
return i.length == 1 ? "0" + i : "" + i;
}
function be(i) {
return i <= 1 && (i = i * 100 + "%"), i;
}
function cn(i) {
return Math.round(parseFloat(i) * 255).toString(16);
}
function Qs(i) {
return lt(i) / 255;
}
var mt = function() {
var i = "[-\\+]?\\d+%?", t = "[-\\+]?\\d*\\.\\d+%?", e = "(?:" + t + ")|(?:" + i + ")", s = "[\\s|\\(]+(" + e + ")[,|\\s]+(" + e + ")[,|\\s]+(" + e + ")\\s*\\)?", r = "[\\s|\\(]+(" + e + ")[,|\\s]+(" + e + ")[,|\\s]+(" + e + ")[,|\\s]+(" + e + ")\\s*\\)?";
return {
CSS_UNIT: new RegExp(e),
rgb: new RegExp("rgb" + s),
rgba: new RegExp("rgba" + r),
hsl: new RegExp("hsl" + s),
hsla: new RegExp("hsla" + r),
hsv: new RegExp("hsv" + s),
hsva: new RegExp("hsva" + r),
hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
};
}();
function Pt(i) {
return !!mt.CSS_UNIT.exec(i);
}
function _l(i) {
i = i.replace(Kh, "").replace(Zh, "").toLowerCase();
var t = !1;
if (Yi[i])
i = Yi[i], t = !0;
else if (i == "transparent")
return {
r: 0,
g: 0,
b: 0,
a: 0,
format: "name"
};
var e;
return (e = mt.rgb.exec(i)) ? {
r: e[1],
g: e[2],
b: e[3]
} : (e = mt.rgba.exec(i)) ? {
r: e[1],
g: e[2],
b: e[3],
a: e[4]
} : (e = mt.hsl.exec(i)) ? {
h: e[1],
s: e[2],
l: e[3]
} : (e = mt.hsla.exec(i)) ? {
h: e[1],
s: e[2],
l: e[3],
a: e[4]
} : (e = mt.hsv.exec(i)) ? {
h: e[1],
s: e[2],
v: e[3]
} : (e = mt.hsva.exec(i)) ? {
h: e[1],
s: e[2],
v: e[3],
a: e[4]
} : (e = mt.hex8.exec(i)) ? {
r: lt(e[1]),
g: lt(e[2]),
b: lt(e[3]),
a: Qs(e[4]),
format: t ? "name" : "hex8"
} : (e = mt.hex6.exec(i)) ? {
r: lt(e[1]),
g: lt(e[2]),
b: lt(e[3]),
format: t ? "name" : "hex"
} : (e = mt.hex4.exec(i)) ? {
r: lt(e[1] + "" + e[1]),
g: lt(e[2] + "" + e[2]),
b: lt(e[3] + "" + e[3]),
a: Qs(e[4] + "" + e[4]),
format: t ? "name" : "hex8"
} : (e = mt.hex3.exec(i)) ? {
r: lt(e[1] + "" + e[1]),
g: lt(e[2] + "" + e[2]),
b: lt(e[3] + "" + e[3]),
format: t ? "name" : "hex"
} : !1;
}
function xl(i) {
var t, e;
return i = i || {
level: "AA",
size: "small"
}, t = (i.level || "AA").toUpperCase(), e = (i.size || "small").toLowerCase(), t !== "AA" && t !== "AAA" && (t = "AA"), e !== "small" && e !== "large" && (e = "small"), {
level: t,
size: e
};
}
var Me = Object.freeze({
Linear: Object.freeze({
None: function(i) {
return i;
},
In: function(i) {
return i;
},
Out: function(i) {
return i;
},
InOut: function(i) {
return i;
}
}),
Quadratic: Object.freeze({
In: function(i) {
return i * i;
},
Out: function(i) {
return i * (2 - i);
},
InOut: function(i) {
return (i *= 2) < 1 ? 0.5 * i * i : -0.5 * (--i * (i - 2) - 1);
}
}),
Cubic: Object.freeze({
In: function(i) {
return i * i * i;
},
Out: function(i) {
return --i * i * i + 1;
},
InOut: function(i) {
return (i *= 2) < 1 ? 0.5 * i * i * i : 0.5 * ((i -= 2) * i * i + 2);
}
}),
Quartic: Object.freeze({
In: function(i) {
return i * i * i * i;
},
Out: function(i) {
return 1 - --i * i * i * i;
},
InOut: function(i) {
return (i *= 2) < 1 ? 0.5 * i * i * i * i : -0.5 * ((i -= 2) * i * i * i - 2);
}
}),
Quintic: Object.freeze({
In: function(i) {
return i * i * i * i * i;
},
Out: function(i) {
return --i * i * i * i * i + 1;
},
InOut: function(i) {
return (i *= 2) < 1 ? 0.5 * i * i * i * i * i : 0.5 * ((i -= 2) * i * i * i * i + 2);
}
}),
Sinusoidal: Object.freeze({
In: function(i) {
return 1 - Math.sin((1 - i) * Math.PI / 2);
},
Out: function(i) {
return Math.sin(i * Math.PI / 2);
},
InOut: function(i) {
return 0.5 * (1 - Math.sin(Math.PI * (0.5 - i)));
}
}),
Exponential: Object.freeze({
In: function(i) {
return i === 0 ? 0 : Math.pow(1024, i - 1);
},
Out: function(i) {
return i === 1 ? 1 : 1 - Math.pow(2, -10 * i);
},
InOut: function(i) {
return i === 0 ? 0 : i === 1 ? 1 : (i *= 2) < 1 ? 0.5 * Math.pow(1024, i - 1) : 0.5 * (-Math.pow(2, -10 * (i - 1)) + 2);
}
}),
Circular: Object.freeze({
In: function(i) {
return 1 - Math.sqrt(1 - i * i);
},
Out: function(i) {
return Math.sqrt(1 - --i * i);
},
InOut: function(i) {
return (i *= 2) < 1 ? -0.5 * (Math.sqrt(1 - i * i) - 1) : 0.5 * (Math.sqrt(1 - (i -= 2) * i) + 1);
}
}),
Elastic: Object.freeze({
In: function(i) {
return i === 0 ? 0 : i === 1 ? 1 : -Math.pow(2, 10 * (i - 1)) * Math.sin((i - 1.1) * 5 * Math.PI);
},
Out: function(i) {
return i === 0 ? 0 : i === 1 ? 1 : Math.pow(2, -10 * i) * Math.sin((i - 0.1) * 5 * Math.PI) + 1;
},
InOut: function(i) {
return i === 0 ? 0 : i === 1 ? 1 : (i *= 2, i < 1 ? -0.5 * Math.pow(2, 10 * (i - 1)) * Math.sin((i - 1.1) * 5 * Math.PI) : 0.5 * Math.pow(2, -10 * (i - 1)) * Math.sin((i - 1.1) * 5 * Math.PI) + 1);
}
}),
Back: Object.freeze({
In: function(i) {
var t = 1.70158;
return i === 1 ? 1 : i * i * ((t + 1) * i - t);
},
Out: function(i) {
var t = 1.70158;
return i === 0 ? 0 : --i * i * ((t + 1) * i + t) + 1;
},
InOut: function(i) {
var t = 2.5949095;
return (i *= 2) < 1 ? 0.5 * (i * i * ((t + 1) * i - t)) : 0.5 * ((i -= 2) * i * ((t + 1) * i + t) + 2);
}
}),
Bounce: Object.freeze({
In: function(i) {
return 1 - Me.Bounce.Out(1 - i);
},
Out: function(i) {
return i < 1 / 2.75 ? 7.5625 * i * i : i < 2 / 2.75 ? 7.5625 * (i -= 1.5 / 2.75) * i + 0.75 : i < 2.5 / 2.75 ? 7.5625 * (i -= 2.25 / 2.75) * i + 0.9375 : 7.5625 * (i -= 2.625 / 2.75) * i + 0.984375;
},
InOut: function(i) {
return i < 0.5 ? Me.Bounce.In(i * 2) * 0.5 : Me.Bounce.Out(i * 2 - 1) * 0.5 + 0.5;
}
}),
generatePow: function(i) {
return i === void 0 && (i = 4), i = i < Number.EPSILON ? Number.EPSILON : i, i = i > 1e4 ? 1e4 : i, {
In: function(t) {
return Math.pow(t, i);
},
Out: function(t) {
return 1 - Math.pow(1 - t, i);
},
InOut: function(t) {
return t < 0.5 ? Math.pow(t * 2, i) / 2 : (1 - Math.pow(2 - t * 2, i)) / 2 + 0.5;
}
};
}
}), we = function() {
return performance.now();
}, bl = (
/** @class */
function() {
function i() {
this._tweens = {}, this._tweensAddedDuringUpdate = {};
}
return i.prototype.getAll = function() {
var t = this;
return Object.keys(this._tweens).map(function(e) {
return t._tweens[e];
});
}, i.prototype.removeAll = function() {
this._tweens = {};
}, i.prototype.add = function(t) {
this._tweens[t.getId()] = t, this._tweensAddedDuringUpdate[t.getId()] = t;
}, i.prototype.remove = function(t) {
delete this._tweens[t.getId()], delete this._tweensAddedDuringUpdate[t.getId()];
}, i.prototype.update = function(t, e) {
t === void 0 && (t = we()), e === void 0 && (e = !1);
var s = Object.keys(this._tweens);
if (s.length === 0)
return !1;
for (; s.length > 0; ) {
this._tweensAddedDuringUpdate = {};
for (var r = 0; r < s.length; r++) {
var n = this._tweens[s[r]], a = !e;
n && n.update(t, a) === !1 && !e && delete this._tweens[s[r]];
}
s = Object.keys(this._tweensAddedDuringUpdate);
}
return !0;
}, i;
}()
), ee = {
Linear: function(i, t) {
var e = i.length - 1, s = e * t, r = Math.floor(s), n = ee.Utils.Linear;
return t < 0 ? n(i[0], i[1], s) : t > 1 ? n(i[e], i[e - 1], e - s) : n(i[r], i[r + 1 > e ? e : r + 1], s - r);
},
Bezier: function(i, t) {
for (var e = 0, s = i.length - 1, r = Math.pow, n = ee.Utils.Bernstein, a = 0; a <= s; a++)
e += r(1 - t, s - a) * r(t, a) * i[a] * n(s, a);
return e;
},
CatmullRom: function(i, t) {
var e = i.length - 1, s = e * t, r = Math.floor(s), n = ee.Utils.CatmullRom;
return i[0] === i[e] ? (t < 0 && (r = Math.floor(s = e * (1 + t))), n(i[(r - 1 + e) % e], i[r], i[(r + 1) % e], i[(r + 2) % e], s - r)) : t < 0 ? i[0] - (n(i[0], i[0], i[1], i[1], -s) - i[0]) : t > 1 ? i[e] - (n(i[e], i[e], i[e - 1], i[e - 1], s - e) - i[e]) : n(i[r ? r - 1 : 0], i[r], i[e < r + 1 ? e : r + 1], i[e < r + 2 ? e : r + 2], s - r);
},
Utils: {
Linear: function(i, t, e) {
return (t - i) * e + i;
},
Bernstein: function(i, t) {
var e = ee.Utils.Factorial;
return e(i) / e(t) / e(i - t);
},
Factorial: /* @__PURE__ */ function() {
var i = [1];
return function(t) {
var e = 1;
if (i[t])
return i[t];
for (var s = t; s > 1; s--)
e *= s;
return i[t] = e, e;
};
}(),
CatmullRom: function(i, t, e, s, r) {
var n = (e - i) * 0.5, a = (s - t) * 0.5, o = r * r, h = r * o;
return (2 * t - 2 * e + n + a) * h + (-3 * t + 3 * e - 2 * n - a) * o + n * r + t;
}
}
}, wl = (
/** @class */
function() {
function i() {
}
return i.nextId = function() {
return i._nextId++;
}, i._nextId = 0, i;
}()
), Vi = new bl(), $t = (
/** @class */
function() {
function i(t, e) {
e === void 0 && (e = Vi), this._object = t, this._group = e, this._isPaused = !1, this._pauseStart = 0, this._valuesStart = {}, this._valuesEnd = {}, this._valuesStartRepeat = {}, this._duration = 1e3, this._isDynamic = !1, this._initialRepeat = 0, this._repeat = 0, this._yoyo = !1, this._isPlaying = !1, this._reversed = !1, this._delayTime = 0, this._startTime = 0, this._easingFunction = Me.Linear.None, this._interpolationFunction = ee.Linear, this._chainedTweens = [], this._onStartCallbackFired = !1, this._onEveryStartCallbackFired = !1, this._id = wl.nextId(), this._isChainStopped = !1, this._propertiesAreSetUp = !1, this._goToEnd = !1;
}
return i.prototype.getId = function() {
return this._id;
}, i.prototype.isPlaying = function() {
return this._isPlaying;
}, i.prototype.isPaused = function() {
return this._isPaused;
}, i.prototype.getDuration = function() {
return this._duration;
}, i.prototype.to = function(t, e) {
if (e === void 0 && (e = 1e3), this._isPlaying)
throw new Error("Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.");
return this._valuesEnd = t, this._propertiesAreSetUp = !1, this._duration = e < 0 ? 0 : e, this;
}, i.prototype.duration = function(t) {
return t === void 0 && (t = 1e3), this._duration = t < 0 ? 0 : t, this;
}, i.prototype.dynamic = function(t) {
return t === void 0 && (t = !1), this._isDynamic = t, this;
}, i.prototype.start = function(t, e) {
if (t === void 0 && (t = we()), e === void 0 && (e = !1), this._isPlaying)
return this;
if (this._group && this._group.add(this), this._repeat = this._initialRepeat, this._reversed) {
this._reversed = !1;
for (var s in this._valuesStartRepeat)
this._swapEndStartRepeatValues(s), this._valuesStart[s] = this._valuesStartRepeat[s];
}
if (this._isPlaying = !0, this._isPaused = !1, this._onStartCallbackFired = !1, this._onEveryStartCallbackFired = !1, this._isChainStopped = !1, this._startTime = t, this._startTime += this._delayTime, !this._propertiesAreSetUp || e) {
if (this._propertiesAreSetUp = !0, !this._isDynamic) {
var r = {};
for (var n in this._valuesEnd)
r[n] = this._valuesEnd[n];
this._valuesEnd = r;
}
this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, e);
}
return this;
}, i.prototype.startFromCurrentValues = function(t) {
return this.start(t, !0);
}, i.prototype._setupProperties = function(t, e, s, r, n) {
for (var a in s) {
var o = t[a], h = Array.isArray(o), c = h ? "array" : typeof o, l = !h && Array.isArray(s[a]);
if (!(c === "undefined" || c === "function")) {
if (l) {
var u = s[a];
if (u.length === 0)
continue;
for (var d = [o], p = 0, f = u.length; p < f; p += 1) {
var g = this._handleRelativeValue(o, u[p]);
if (isNaN(g)) {
l = !1, console.warn("Found invalid interpolation list. Skipping.");
break;
}
d.push(g);
}
l && (s[a] = d);
}
if ((c === "object" || h) && o && !l) {
e[a] = h ? [] : {};
var m = o;
for (var y in m)
e[a][y] = m[y];
r[a] = h ? [] : {};
var u = s[a];
if (!this._isDynamic) {
var _ = {};
for (var y in u)
_[y] = u[y];
s[a] = u = _;
}
this._setupProperties(m, e[a], u, r[a], n);
} else
(typeof e[a] > "u" || n) && (e[a] = o), h || (e[a] *= 1), l ? r[a] = s[a].slice().reverse() : r[a] = e[a] || 0;
}
}
}, i.prototype.stop = function() {
return this._isChainStopped || (this._isChainStopped = !0, this.stopChainedTweens()), this._isPlaying ? (this._group && this._group.remove(this), this._isPlaying = !1, this._isPaused = !1, this._onStopCallback && this._onStopCallback(this._object), this) : this;
}, i.prototype.end = function() {
return this._goToEnd = !0, this.update(1 / 0), this;
}, i.prototype.pause = function(t) {
return t === void 0 && (t = we()), this._isPaused || !this._isPlaying ? this : (this._isPaused = !0, this._pauseStart = t, this._group && this._group.remove(this), this);
}, i.prototype.resume = function(t) {
return t === void 0 && (t = we()), !this._isPaused || !this._isPlaying ? this : (this._isPaused = !1, this._startTime += t - this._pauseStart, this._pauseStart = 0, this._group && this._group.add(this), this);
}, i.prototype.stopChainedTweens = function() {
for (var t = 0, e = this._chainedTweens.length; t < e; t++)
this._chainedTweens[t].stop();
return this;
}, i.prototype.group = function(t) {
return t === void 0 && (t = Vi), this._group = t, this;
}, i.prototype.delay = function(t) {
return t === void 0 && (t = 0), this._delayTime = t, this;
}, i.prototype.repeat = function(t) {
return t === void 0 && (t = 0), this._initialRepeat = t, this._repeat = t, this;
}, i.prototype.repeatDelay = function(t) {
return this._repeatDelayTime = t, this;
}, i.prototype.yoyo = function(t) {
return t === void 0 && (t = !1), this._yoyo = t, this;
}, i.prototype.easing = function(t) {
return t === void 0 && (t = Me.Linear.None), this._easingFunction = t, this;
}, i.prototype.interpolation = function(t) {
return t === void 0 && (t = ee.Linear), this._interpolationFunction = t, this;
}, i.prototype.chain = function() {
for (var t = [], e = 0; e < arguments.length; e++)
t[e] = arguments[e];
return this._chainedTweens = t, this;
}, i.prototype.onStart = function(t) {
return this._onStartCallback = t, this;
}, i.prototype.onEveryStart = function(t) {
return this._onEveryStartCallback = t, this;
}, i.prototype.onUpdate = function(t) {
return this._onUpdateCallback = t, this;
}, i.prototype.onRepeat = function(t) {
return this._onRepeatCallback = t, this;
}, i.prototype.onComplete = function(t) {
return this._onCompleteCallback = t, this;
}, i.prototype.onStop = function(t) {
return this._onStopCallback = t, this;
}, i.prototype.update = function(t, e) {
var s;
if (t === void 0 && (t = we()), e === void 0 && (e = !0), this._isPaused)
return !0;
var r = this._startTime + this._duration;
if (!this._goToEnd && !this._isPlaying) {
if (t > r)
return !1;
e && this.start(t, !0);
}
if (this._goToEnd = !1, t < this._startTime)
return !0;
this._onStartCallbackFired === !1 && (this._onStartCallback && this._onStartCallback(this._object), this._onStartCallbackFired = !0), this._onEveryStartCallbackFired === !1 && (this._onEveryStartCallback && this._onEveryStartCallback(this._object), this._onEveryStartCallbackFired = !0);
var n = t - this._startTime, a = this._duration + ((s = this._repeatDelayTime) !== null && s !== void 0 ? s : this._delayTime), o = this._duration + this._repeat * a, h = this._calculateElapsedPortion(n, a, o), c = this._easingFunction(h), l = this._calculateCompletionStatus(n, a);
if (l === "repeat" && this._processRepetition(n, a), this._updateProperties(this._object, this._valuesStart, this._valuesEnd, c), l === "about-to-repeat" && this._processRepetition(n, a), this._onUpdateCallback && this._onUpdateCallback(this._object, h), l === "repeat" || l === "about-to-repeat")
this._onRepeatCallback && this._onRepeatCallback(this._object), this._onEveryStartCallbackFired = !1;
else if (l === "completed") {
this._isPlaying = !1, this._onCompleteCallback && this._onCompleteCallback(this._object);
for (var u = 0, d = this._chainedTweens.length; u < d; u++)
this._chainedTweens[u].start(this._startTime + this._duration, !1);
}
return l !== "completed";
}, i.prototype._calculateElapsedPortion = function(t, e, s) {
if (this._duration === 0 || t > s)
return 1;
var r = t % e, n = Math.min(r / this._duration, 1);
return n === 0 && t !== 0 && t % this._duration === 0 ? 1 : n;
}, i.prototype._calculateCompletionStatus = function(t, e) {
return this._duration !== 0 && t < this._duration ? "playing" : this._repeat <= 0 ? "completed" : t === this._duration ? "about-to-repeat" : "repeat";
}, i.prototype._processRepetition = function(t, e) {
var s = Math.min(Math.trunc((t - this._duration) / e) + 1, this._repeat);
isFinite(this._repeat) && (this._repeat -= s);
for (var r in this._valuesStartRepeat) {
var n = this._valuesEnd[r];
!this._yoyo && typeof n == "string" && (this._valuesStartRepeat[r] = this._valuesStartRepeat[r] + parseFloat(n)), this._yoyo && this._swapEndStartRepeatValues(r), this._valuesStart[r] = this._valuesStartRepeat[r];
}
this._yoyo && (this._reversed = !this._reversed), this._startTime += e * s;
}, i.prototype._updateProperties = function(t, e, s, r) {
for (var n in s)
if (e[n] !== void 0) {
var a = e[n] || 0, o = s[n], h = Array.isArray(t[n]), c = Array.isArray(o), l = !h && c;
l ? t[n] = this._interpolationFunction(o, r) : typeof o == "object" && o ? this._updateProperties(t[n], a, o, r) : (o = this._handleRelativeValue(a, o), typeof o == "number" && (t[n] = a + (o - a) * r));
}
}, i.prototype._handleRelativeValue = function(t, e) {
return typeof e != "string" ? e : e.charAt(0) === "+" || e.charAt(0) === "-" ? t + parseFloat(e) : parseFloat(e);
}, i.prototype._swapEndStartRepeatValues = function(t) {
var e = this._valuesStartRepeat[t], s = this._valuesEnd[t];
typeof s == "string" ? this._valuesStartRepeat[t] = this._valuesStartRepeat[t] + parseFloat(s) : this._valuesStartRepeat[t] = this._valuesEnd[t], this._valuesEnd[t] = e;
}, i;
}()
), Ct = Vi;
Ct.getAll.bind(Ct);
Ct.removeAll.bind(Ct);
Ct.add.bind(Ct);
Ct.remove.bind(Ct);
Ct.update.bind(Ct);
class It {
constructor(t = 0, e) {
w(this, "isCompleted", !1);
this.current = t, this.onComplete = e;
}
tick(t = Ut) {
this.isCompleted || (this.current -= t, this.current < 0 && this.complete());
}
complete() {
var t;
this.isCompleted = !0, (t = this.onComplete) == null || t.call(this);
}
}
class vl {
constructor() {
w(this, "timers", []);
}
add(t, e) {
this.timers.push(new It(t, e));
}
tick(t = Ut) {
const e = [];
for (const s of this.timers)
s.isCompleted || (s.tick(t), e.push(s));
this.timers = e;
}
}
const ji = new vl();
class Al {
constructor() {
w(this, "assets", {});
}
async initialize(t) {
this.assets = Object.fromEntries(
Array.from(Object.entries(t ?? {})).map(([e, s]) => [e, new Audio(s.src)])
);
}
play(t) {
const e = this.assets[t];
e && (e.volume = 0.3, e.pause(), e.currentTime = 0, e.play());
}
}
const un = new Al();
var Q = /* @__PURE__ */ ((i) => (i.Idle = "Idle", i.Jump = "Jump", i.Fall = "Fall", i.Land = "Land", i.Run = "Run", i.Die = "Die", i))(Q || {});
class Sl {
constructor() {
w(this, "spriteLoaderFn");
w(this, "sprites", {});
}
initialize(t) {
this.spriteLoaderFn = t;
}
async getSpriteData(t) {
const e = await this.spriteLoaderFn(t);
if (!e)
return;
if (this.sprites[t])
return this.sprites[t];
const s = await yt.load(e.image), r = new Fi(s, e.sprite);
return await r.parse(), this.sprites[t] = {
sheet: r,
data: {
...e.data,
scale: e.data.scale ?? 1
}
}, this.sprites[t];
}
createAnimatedSprite(t, e) {
for (const s of e.data.meta.frameTags ?? []) {
const r = [];
for (let a = s.from; a <= s.to; a++) {
const o = a.toString(), h = t + "_" + o, c = e.textures[h], l = e.data.frames[h].duration;
r.push({ texture: c, time: l });
}
const n = new Re(r);
return n.texture.source.scaleMode = "nearest", n;
}
}
getAnimatedSprites(t) {
if (!t)
throw Error("Sheet is not defined");
if (!this.sprites[t])
throw Error("Sprite is not loaded");
const e = this.sprites[t].data, s = this.sprites[t].sheet, r = {};
for (const n of s.data.meta.frameTags ?? []) {
if (!s.data.meta.layers)
throw Error("Layers are not defined");
const a = {};
for (const o of s.data.meta.layers) {
const h = [];
for (let l = n.from; l <= n.to; l++) {
const u = l.toString(), d = e.name + "_" + o.name + "_" + u, p = s.textures[d], f = s.data.frames[d].duration;
h.push({ texture: p, time: f });
}
const c = new Re(h);
c.texture.source.scaleMode = "nearest", a[o.name] = c;
}
n.name && (r[n.name] = a);
}
return r;
}
}
const ti = new Sl();
var qt = {}, dn = {}, Rt = {};
Object.defineProperty(Rt, "__esModule", {
value: !0
});
Rt.loop = Rt.conditional = Rt.parse = void 0;
var Cl = function i(t, e) {
var s = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, r = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : s;
if (Array.isArray(e))
e.forEach(function(a) {
return i(t, a, s, r);
});
else if (typeof e == "function")
e(t, s, r, i);
else {
var n = Object.keys(e)[0];
Array.isArray(e[n]) ? (r[n] = {}, i(t, e[n], s, r[n])) : r[n] = e[n](t, s, r, i);
}
return s;
};
Rt.parse = Cl;
var Ml = function(t, e) {
return function(s, r, n, a) {
e(s, r, n) && a(s, t, r, n);
};
};
Rt.conditional = Ml;
var Tl = function(t, e) {
return function(s, r, n, a) {
for (var o = [], h = s.pos; e(s, r, n); ) {
var c = {};
if (a(s, t, r, c), s.pos === h)
break;
h = s.pos, o.push(c);
}
return o;
};
};
Rt.loop = Tl;
var V = {};
Object.defineProperty(V, "__esModule", {
value: !0
});
V.readBits = V.readArray = V.readUnsigned = V.readString = V.peekBytes = V.readBytes = V.peekByte = V.readByte = V.buildStream = void 0;
var Pl = function(t) {
return {
data: t,
pos: 0
};
};
V.buildStream = Pl;
var fn = function() {
return function(t) {
return t.data[t.pos++];
};
};
V.readByte = fn;
var kl = function() {
var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
return function(e) {
return e.data[e.pos + t];
};
};
V.peekByte = kl;
var ni = function(t) {
return function(e) {
return e.data.subarray(e.pos, e.pos += t);
};
};
V.readBytes = ni;
var Il = function(t) {
return function(e) {
return e.data.subarray(e.pos, e.pos + t);
};
};
V.peekBytes = Il;
var El = function(t) {
return function(e) {
return Array.from(ni(t)(e)).map(function(s) {
return String.fromCharCode(s);
}).join("");
};
};
V.readString = El;
var Rl = function(t) {
return function(e) {
var s = ni(2)(e);
return t ? (s[1] << 8) + s[0] : (s[0] << 8) + s[1];
};
};
V.readUnsigned = Rl;
var Bl = function(t, e) {
return function(s, r, n) {
for (var a = typeof e == "function" ? e(s, r, n) : e, o = ni(t), h = new Array(a), c = 0; c < a; c++)
h[c] = o(s);
return h;
};
};
V.readArray = Bl;
var Fl = function(t, e, s) {
for (var r = 0, n = 0; n < s; n++)
r += t[e + n] && Math.pow(2, s - n - 1);
return r;
}, Ll = function(t) {
return function(e) {
for (var s = fn()(e), r = new Array(8), n = 0; n < 8; n++)
r[7 - n] = !!(s & 1 << n);
return Object.keys(t).reduce(function(a, o) {
var h = t[o];
return h.length ? a[o] = Fl(r, h.index, h.length) : a[o] = r[h.index], a;
}, {});
};
};
V.readBits = Ll;
(function(i) {
Object.defineProperty(i, "__esModule", {
value: !0
}), i.default = void 0;
var t = Rt, e = V, s = {
blocks: function(d) {
for (var p = 0, f = [], g = d.data.length, m = 0, y = (0, e.readByte)()(d); y !== p && y; y = (0, e.readByte)()(d)) {
if (d.pos + y >= g) {
var _ = g - d.pos;
f.push((0, e.readBytes)(_)(d)), m += _;
break;
}
f.push((0, e.readBytes)(y)(d)), m += y;
}
for (var x = new Uint8Array(m), b = 0, S = 0; S < f.length; S++)
x.set(f[S], b), b += f[S].length;
return x;
}
}, r = (0, t.conditional)({
gce: [{
codes: (0, e.readBytes)(2)
}, {
byteSize: (0, e.readByte)()
}, {
extras: (0, e.readBits)({
future: {
index: 0,
length: 3
},
disposal: {
index: 3,
length: 3
},
userInput: {
index: 6
},
transparentColorGiven: {
index: 7
}
})
}, {
delay: (0, e.readUnsigned)(!0)
}, {
transparentColorIndex: (0, e.readByte)()
}, {
terminator: (0, e.readByte)()
}]
}, function(u) {
var d = (0, e.peekBytes)(2)(u);
return d[0] === 33 && d[1] === 249;
}), n = (0, t.conditional)({
image: [{
code: (0, e.readByte)()
}, {
descriptor: [{
left: (0, e.readUnsigned)(!0)
}, {
top: (0, e.readUnsigned)(!0)
}, {
width: (0, e.readUnsigned)(!0)
}, {
height: (0, e.readUnsigned)(!0)
}, {
lct: (0, e.readBits)({
exists: {
index: 0
},
interlaced: {
index: 1
},
sort: {
index: 2
},
future: {
index: 3,
length: 2
},
size: {
index: 5,
length: 3
}
})
}]
}, (0, t.conditional)({
lct: (0, e.readArray)(3, function(u, d, p) {
return Math.pow(2, p.descriptor.lct.size + 1);
})
}, function(u, d, p) {
return p.descriptor.lct.exists;
}), {
data: [{
minCodeSize: (0, e.readByte)()
}, s]
}]
}, function(u) {
return (0, e.peekByte)()(u) === 44;
}), a = (0, t.conditional)({
text: [{
codes: (0, e.readBytes)(2)
}, {
blockSize: (0, e.readByte)()
}, {
preData: function(d, p, f) {
return (0, e.readBytes)(f.text.blockSize)(d);
}
}, s]
}, function(u) {
var d = (0, e.peekBytes)(2)(u);
return d[0] === 33 && d[1] === 1;
}), o = (0, t.conditional)({
application: [{
codes: (0, e.readBytes)(2)
}, {
blockSize: (0, e.readByte)()
}, {
id: function(d, p, f) {
return (0, e.readString)(f.blockSize)(d);
}
}, s]
}, function(u) {
var d = (0, e.peekBytes)(2)(u);
return d[0] === 33 && d[1] === 255;
}), h = (0, t.conditional)({
comment: [{
codes: (0, e.readBytes)(2)
}, s]
}, function(u) {
var d = (0, e.peekBytes)(2)(u);
return d[0] === 33 && d[1] === 254;
}), c = [
{
header: [{
signature: (0, e.readString)(3)
}, {
version: (0, e.readString)(3)
}]
},
{
lsd: [{
width: (0, e.readUnsigned)(!0)
}, {
height: (0, e.readUnsigned)(!0)
}, {
gct: (0, e.readBits)({
exists: {
index: 0
},
resolution: {
index: 1,
length: 3
},
sort: {
index: 4
},
size: {
index: 5,
length: 3
}
})
}, {
backgroundColorIndex: (0, e.readByte)()
}, {
pixelAspectRatio: (0, e.readByte)()
}]
},
(0, t.conditional)({
gct: (0, e.readArray)(3, function(u, d) {
return Math.pow(2, d.lsd.gct.size + 1);
})
}, function(u, d) {
return d.lsd.gct.exists;
}),
// content frames
{
frames: (0, t.loop)([r, o, h, n, a], function(u) {
var d = (0, e.peekByte)()(u);
return d === 33 || d === 44;
})
}
], l = c;
i.default = l;
})(dn);
var ai = {};
Object.defineProperty(ai, "__esModule", {
value: !0
});
ai.deinterlace = void 0;
var Dl = function(t, e) {
for (var s = new Array(t.length), r = t.length / e, n = function(d, p) {
var f = t.slice(p * e, (p + 1) * e);
s.splice.apply(s, [d * e, e].concat(f));
}, a = [0, 4, 2, 1], o = [8, 8, 4, 2], h = 0, c = 0; c < 4; c++)
for (var l = a[c]; l < r; l += o[c])
n(l, h), h++;
return s;
};
ai.deinterlace = Dl;
var oi = {};
Object.defineProperty(oi, "__esModule", {
value: !0
});
oi.lzw = void 0;
var Ul = function(t, e, s) {
var r = 4096, n = -1, a = s, o, h, c, l, u, d, p, k, f, g, S, m, M, C, A, v, y = new Array(s), _ = new Array(r), x = new Array(r), b = new Array(r + 1);
for (m = t, h = 1 << m, u = h + 1, o = h + 2, p = n, l = m + 1, c = (1 << l) - 1, f = 0; f < h; f++)
_[f] = 0, x[f] = f;
var S, k, M, C, v, A;
for (S = k = M = C = v = A = 0, g = 0; g < a; ) {
if (C === 0) {
if (k < l) {
S += e[A] << k, k += 8, A++;
continue;
}
if (f = S & c, S >>= l, k -= l, f > o || f == u)
break;
if (f == h) {
l = m + 1, c = (1 << l) - 1, o = h + 2, p = n;
continue;
}
if (p == n) {
b[C++] = x[f], p = f, M = f;
continue;
}
for (d = f, f == o && (b[C++] = M, f = p); f > h; )
b[C++] = x[f], f = _[f];
M = x[f] & 255, b[C++] = M, o < r && (_[o] = p, x[o] = M, o++, !(o & c) && o < r && (l++, c += o)), p = d;
}
C--, y[v++] = b[C], g++;
}
for (g = v; g < a; g++)
y[g] = 0;
return y;
};
oi.lzw = Ul;
Object.defineProperty(qt, "__esModule", {
value: !0
});
var pn = qt.decompressFrames = qt.decompressFrame = mn = qt.parseGIF = void 0, Ol = Nl(dn), Gl = Rt, zl = V, Hl = ai, Wl = oi;
function Nl(i) {
return i && i.__esModule ? i : { default: i };
}
var Yl = function(t) {
var e = new Uint8Array(t);
return (0, Gl.parse)((0, zl.buildStream)(e), Ol.default);
}, mn = qt.parseGIF = Yl, Vl = function(t) {
for (var e = t.pixels.length, s = new Uint8ClampedArray(e * 4), r = 0; r < e; r++) {
var n = r * 4, a = t.pixels[r], o = t.colorTable[a] || [0, 0, 0];
s[n] = o[0], s[n + 1] = o[1], s[n + 2] = o[2], s[n + 3] = a !== t.transparentIndex ? 255 : 0;
}
return s;
}, gn = function(t, e, s) {
if (!t.image) {
console.warn("gif frame does not have associated image.");
return;
}
var r = t.image, n = r.descriptor.width * r.descriptor.height, a = (0, Wl.lzw)(r.data.minCodeSize, r.data.blocks, n);
r.descriptor.lct.interlaced && (a = (0, Hl.deinterlace)(a, r.descriptor.width));
var o = {
pixels: a,
dims: {
top: t.image.descriptor.top,
left: t.image.descriptor.left,
width: t.image.descriptor.width,
height: t.image.descriptor.height
}
};
return r.descriptor.lct && r.descriptor.lct.exists ? o.colorTable = r.lct : o.colorTable = e, t.gce && (o.delay = (t.gce.delay || 10) * 10, o.disposalType = t.gce.extras.disposal, t.gce.extras.transparentColorGiven && (o.transparentIndex = t.gce.transparentColorIndex)), s && (o.patch = Vl(o)), o;
};
qt.decompressFrame = gn;
var jl = function(t, e) {
return t.frames.filter(function(s) {
return s.image;
}).map(function(s) {
return gn(s, t.gct, e);
});
};
pn = qt.decompressFrames = jl;
const ve = class extends xt {
constructor(i, t) {
super(L.EMPTY), this.animationSpeed = 1, this.loop = !0, this.duration = 0, this.autoPlay = !0, this.dirty = !1, this._currentFrame = 0, this._autoUpdate = !1, this._isConnectedToTicker = !1, this._playing = !1, this._currentTime = 0, this.onRender = () => this.updateFrame();
const { scaleMode: e, width: s, height: r, ...n } = Object.assign(
{},
ve.defaultOptions,
t
), a = Y.get().createCanvas(s, r), o = a.getContext("2d");
this.texture = L.from(a), this.texture.source.scaleMode = e, this.duration = i[i.length - 1].end, this._frames = i, this._context = o, this._playing = !1, this._currentTime = 0, this._isConnectedToTicker = !1, Object.assign(this, n), this.currentFrame = 0, n.autoPlay && this.play();
}
static fromBuffer(i, t) {
if (!i || i.byteLength === 0)
throw new Error("Invalid buffer");
const e = (m) => {
let y = null;
for (const _ of m.frames)
y = _.gce ?? y, "image" in _ && !("gce" in _) && (_.gce = y);
}, s = mn(i);
e(s);
const r = pn(s, !0), n = [], a = Y.get().createCanvas(s.lsd.width, s.lsd.height), o = a.getContext("2d", {
willReadFrequently: !0
}), h = Y.get().createCanvas(), c = h.getContext("2d");
let l = 0, u = null;
const { fps: d } = Object.assign({}, ve.defaultOptions, t), p = 1e3 / d;
for (let m = 0; m < r.length; m++) {
const {
disposalType: y = 2,
delay: _ = p,
patch: x,
dims: { width: b, height: S, left: k, top: M }
} = r[m];
h.width = b, h.height = S, c.clearRect(0, 0, b, S);
const C = c.createImageData(b, S);
C.data.set(x), c.putImageData(C, 0, 0), y === 3 && (u = o.getImageData(0, 0, a.width, a.height)), o.drawImage(h, k, M);
const v = o.getImageData(0, 0, a.width, a.height);
y === 2 ? o.clearRect(0, 0, a.width, a.height) : y === 3 && o.putImageData(u, 0, 0), n.push({
start: l,
end: l + _,
imageData: v
}), l += _;
}
a.width = a.height = 0, h.width = h.height = 0;
const { width: f, height: g } = s.lsd;
return new ve(n, { width: f, height: g, ...t });
}
stop() {
this._playing && (this._playing = !1, this._autoUpdate && this._isConnectedToTicker && (ot.shared.remove(this.update, this), this._isConnectedToTicker = !1));
}
play() {
this._playing || (this._playing = !0, this._autoUpdate && !this._isConnectedToTicker && (ot.shared.add(this.update, this, Te.HIGH), this._isConnectedToTicker = !0), !this.loop && this.currentFrame === this._frames.length - 1 && (this._currentTime = 0));
}
get progress() {
return this._currentTime / this.duration;
}
get playing() {
return this._playing;
}
update(i) {
var n, a;
if (!this._playing)
return;
const t = this.animationSpeed * i.deltaTime / ot.targetFPMS, e = this._currentTime + t, s = e % this.duration, r = this._frames.findIndex((o) => o.start <= s && o.end > s);
e >= this.duration ? this.loop ? (this._currentTime = s, this.updateFrameIndex(r), (n = this.onLoop) == null || n.call(this)) : (this._currentTime = this.duration, this.updateFrameIndex(this._frames.length - 1), (a = this.onComplete) == null || a.call(this), this.stop()) : (this._currentTime = s, this.updateFrameIndex(r));
}
updateFrame() {
if (!this.dirty)
return;
const { imageData: i } = this._frames[this._currentFrame];
this._context.putImageData(i, 0, 0), this._context.fillStyle = "transparent", this._context.fillRect(0, 0, 0, 1), this.texture.source.update(), this.dirty = !1;
}
get autoUpdate() {
return this._autoUpdate;
}
set autoUpdate(i) {
i !== this._autoUpdate && (this._autoUpdate = i, !this._autoUpdate && this._isConnectedToTicker ? (ot.shared.remove(this.update, this), this._isConnectedToTicker = !1) : this._autoUpdate && !this._isConnectedToTicker && this._playing && (ot.shared.add(this.update, this), this._isConnectedToTicker = !0));
}
get currentFrame() {
return this._currentFrame;
}
set currentFrame(i) {
this.updateFrameIndex(i), this._currentTime = this._frames[i].start;
}
updateFrameIndex(i) {
var t;
if (i < 0 || i >= this._frames.length)
throw new Error(`Frame index out of range, expecting 0 to ${this.totalFrames}, got ${i}`);
this._currentFrame !== i && (this._currentFrame = i, this.dirty = !0, (t = this.onFrameChange) == null || t.call(this, i));
}
get totalFrames() {
return this._frames.length;
}
destroy() {
this.stop(), super.destroy(!0);
const i = null;
this._context = i, this._frames = i, this.onComplete = i, this.onFrameChange = i, this.onLoop = i;
}
clone() {
const i = new ve([...this._frames], {
autoUpdate: this._autoUpdate,
loop: this.loop,
autoPlay: this.autoPlay,
scaleMode: this.texture.source.scaleMode,
animationSpeed: this.animationSpeed,
width: this._context.canvas.width,
height: this._context.canvas.height,
onComplete: this.onComplete,
onFrameChange: this.onFrameChange,
onLoop: this.onLoop
});
return i.dirty = !0, i;
}
};
let os = ve;
os.defaultOptions = {
scaleMode: "linear",
fps: 30,
loop: !0,
animationSpeed: 1,
autoPlay: !0,
autoUpdate: !0,
onComplete: null,
onFrameChange: null,
onLoop: null
};
const Xl = {
extension: B.Asset,
detection: {
test: async () => !0,
add: async (i) => [...i, "gif"],
remove: async (i) => i.filter((t) => t !== "gif")
},
loader: {
name: "gifLoader",
test: (i) => bt.extname(i) === ".gif",
load: async (i, t) => {
const s = await (await Y.get().fetch(i)).arrayBuffer();
return os.fromBuffer(s, t == null ? void 0 : t.data);
},
unload: async (i) => {
i.destroy();
}
}
};
dt.add(Xl);
const tr = {};
class $l {
constructor() {
w(this, "container", new O());
w(this, "emotes", []);
w(this, "moveSpeed", 50);
w(this, "alphaSpeed", 1);
w(this, "scaleSpeed", 0.5);
w(this, "timer");
}
async add(t) {
const e = tr[t];
let s;
if (e)
s = e.clone();
else {
const r = await fetch(t), n = r.headers.get("content-type");
switch (n) {
case "image/gif": {
const a = await r.arrayBuffer();
s = os.fromBuffer(a), tr[t] = s;
break;
}
case "image/png": {
s = xt.from(t);
break;
}
default: {
console.warn("Unsupported content type: ", n);
return;
}
}
}
s && (s.anchor.set(0.5, 0.5), s.scale.set(0, 0), this.emotes.push(s));
}
isAnimatedGIF(t) {
return t.currentFrame;
}
update(t) {
var e;
(e = this.timer) == null || e.tick(), (!this.timer || this.timer.isCompleted) && this.emotes.length > 0 && (this.timer = new It(2e3, () => {
const s = this.emotes.shift();
s && (this.isAnimatedGIF(s) && (s.currentFrame = 0), this.container.addChild(s));
})), this.container.position.x = t.position.x ?? this.container.position.x, this.container.position.y = t.position.y ?? this.container.position.y;
for (const s of this.container.children)
s.position.y -= Ut * this.moveSpeed / 1e3, s.scale.x += Ut * this.scaleSpeed / 1e3, s.scale.y += Ut * this.scaleSpeed / 1e3, s.scale.x > 1 && (s.alpha -= Ut * this.alphaSpeed / 1e3), s.alpha <= 0 && this.container.removeChild(s);
}
}
class ql {
constructor(t) {
w(this, "container", new O());
w(this, "animated", new O());
w(this, "text", new Je({
text: void 0,
style: {
fontFamily: "Custom Font",
fontSize: 20,
fill: 2236962,
align: "left",
breakWords: !0,
wordWrap: !0,
wordWrapWidth: 200
}
}));
w(this, "padding", 10);
w(this, "borderRadius", 10);
w(this, "boxColor", 15658734);
w(this, "boxBorderColor", 2236962);
w(this, "fadeShift", 10);
w(this, "isChecking", !0);
w(this, "showTween");
w(this, "hideTween");
w(this, "timer");
this.beforeShow = t, this.container.addChild(this.animated), this.text.anchor.set(0.5, 1), this.text.position.set(0, -this.padding);
}
trim(t) {
const e = an.measureText(t.text, t.style);
return e.lines.length > 4 ? e.lines.slice(0, 4).join(" ").slice(0, -3) + "..." : t.text;
}
update(t) {
var s, r, n, a, o;
(s = this.timer) == null || s.tick(), (r = this.showTween) == null || r.update(), (n = this.hideTween) == null || n.update(), this.container.position.x = t.position.x ?? this.container.position.x, this.container.position.y = t.position.y ?? this.container.position.y;
const e = ((a = this.showTween) == null ? void 0 : a.isPlaying()) || ((o = this.hideTween) == null ? void 0 : o.isPlaying());
!this.isChecking && !e && this.timer && (this.animated.position.y = Math.sin(this.timer.current * 25e-4) * 4 - 2);
}
add(t) {
var e, s;
this.isChecking = !1, (e = this.hideTween) == null || e.stop(), (s = this.showTween) == null || s.stop(), t && (this.beforeShow(), this.show(t));
}
drawBox(t) {
const e = {
x: t.x - this.padding - t.width * t.anchor.x,
y: t.y - this.padding - t.height * t.anchor.y,
w: t.width + this.padding * 2,
h: t.height + this.padding * 2
}, s = 20, r = 5, n = new Ze();
return n.moveTo(e.x + this.borderRadius, e.y), n.quadraticCurveTo(
e.x,
e.y,
e.x,
e.y + this.borderRadius,
5
), n.lineTo(
e.x,
e.y + e.h - this.borderRadius
), n.quadraticCurveTo(
e.x,
e.y + e.h,
e.x + this.borderRadius,
e.y + e.h,
5
), n.lineTo(
e.x + e.w / 2 - s / 2,
e.y + e.h
), n.lineTo(
e.x + e.w / 2,
e.y + e.h + r
), n.lineTo(
e.x + e.w / 2 + s / 2,
e.y + e.h
), n.lineTo(
e.x + e.w - this.borderRadius,
e.y + e.h
), n.quadraticCurveTo(
e.x + e.w,
e.y + e.h,
e.x + e.w,
e.y + e.h - this.borderRadius,
5
), n.lineTo(
e.x + e.w,
e.y + this.borderRadius
), n.quadraticCurveTo(
e.x + e.w,
e.y,
e.x + e.w - this.borderRadius,
e.y,
5
), n.lineTo(e.x + this.borderRadius, e.y), n.fill({
color: this.boxColor
}), n.stroke({
color: this.boxBorderColor,
width: 2
}), n;
}
show(t) {
this.text.text = t, this.text.text = this.trim(this.text), this.animated.alpha = 0, this.animated.position.y = this.fadeShift;
const e = this.drawBox(this.text);
this.animated.removeChildren(), this.animated.addChild(e, this.text);
const s = {
alpha: 1,
y: this.animated.y - this.fadeShift
}, r = {
alpha: 0,
y: this.animated.y + this.fadeShift
};
this.hideTween = new $t(this.animated).to(r, 500).onComplete(() => {
this.isChecking = !0;
}), this.showTween = new $t(this.animated).to(s, 500).onComplete(() => {
this.timer = new It(1e4, () => {
var n;
(n = this.hideTween) == null || n.start();
});
}), this.showTween.start();
}
}
class Kl {
constructor() {
w(this, "text", new Je({
text: void 0,
style: {
fontFamily: "Custom Font",
fontSize: 18,
fill: 16777215,
align: "center",
stroke: {
width: 4,
color: "black",
join: "round"
}
}
}));
this.text.anchor.set(0.5, 1), this.text.zIndex = 100;
}
update(t) {
this.text.text = t.name ?? "", this.text.visible = t.isVisible, this.text.position.x = t.position.x ?? this.text.position.x, this.text.position.y = t.position.y ?? this.text.position.y;
}
}
class Zl {
constructor(t, e) {
w(this, "container", new O());
w(this, "currentTag", Q.Idle);
this.sprites = t, this.data = e, this.container.pivot.set(0, e.collider.y + e.collider.h), this.container.sortableChildren = !0;
let s = 0;
for (const r in this.sprites) {
const n = this.sprites[r];
for (const a in n) {
const o = n[a];
o.zIndex = ++s, o.anchor.set(0.5, 0), o.autoUpdate = !1, o.play();
}
}
}
getLayersByTag(t) {
return this.sprites[t];
}
setTag(t = Q.Idle) {
this.currentTag != t && this.container.removeChildren(), this.currentTag = t;
const e = this.sprites[this.currentTag];
for (const s in e) {
const r = e[s];
this.container.addChild(r);
}
}
update(t) {
const e = this.sprites[this.currentTag];
for (const s in e) {
const r = e[s];
if (t.play && r.update(N.ticker), t.color) {
for (const n in t.color)
if (n == s) {
const a = t.color[n];
a && (r.alpha = a.alpha, r.tint = a);
}
}
t.scale.x && (r.animationSpeed = 4 / Math.abs(t.scale.x));
}
this.container.scale.set(t.scale.x, t.scale.y);
}
}
class Jl {
constructor() {
w(this, "container", new O());
w(this, "timer");
w(this, "sprite");
w(this, "opacityStep", 0.1);
w(this, "shadowStep", 50);
N.stage.addChild(this.container), this.container.zIndex = -100;
}
setSprite(t) {
this.sprite = t;
}
update(t) {
for (const e of this.container.children)
e.alpha > 0 && (e.alpha = e.alpha - this.opacityStep);
if (this.timer && !this.timer.isCompleted)
this.timer.tick();
else if (t.play) {
this.timer = new It(this.shadowStep);
const e = new O();
if (this.sprite) {
const s = this.sprite.getLayersByTag(Q.Idle);
for (const r in s) {
const n = s[r], a = n.texture, o = new xt(a);
o.anchor.set(0.5, 0), o.alpha = n.alpha, o.tint = n.tint, e.addChild(o), e.scale.set(
this.sprite.container.scale.x,
this.sprite.container.scale.y
), e.pivot.set(
this.sprite.container.pivot.x,
this.sprite.container.pivot.y
);
const h = this.sprite.container.getGlobalPosition();
e.position.set(h.x, h.y);
}
}
this.container.addChild(e);
}
}
}
const Ql = async (i) => {
await new Promise(
(t) => setTimeout(() => {
t(void 0);
}, i)
);
}, er = {
fontFamily: "Custom Font",
fontSize: 14,
fill: "white",
align: "center",
stroke: {
width: 4,
color: "black",
join: "round"
}
};
class tc {
constructor() {
w(this, "container", new O());
w(this, "killText", new Je({
text: void 0,
style: er
}));
w(this, "killSprite");
w(this, "jumpText", new Je({
text: void 0,
style: er
}));
w(this, "jumpSprite");
w(this, "kills", 0);
w(this, "jumps", 0);
this.container.zIndex = 100, this.killSprite = this.createSprite("skull"), this.killText.anchor.set(0, 0.5), this.jumpSprite = this.createSprite("weight"), this.jumpText.anchor.set(0, 0.5);
}
addJumps(t) {
this.jumps += t, this.draw();
}
addKill() {
this.kills += 1, this.draw();
}
useJump() {
this.jumps -= 1, this.draw();
}
createSprite(t) {
const e = yt.get(t), s = xt.from(e);
return s.anchor.set(0, 0.5), s.scale.set(2, 2), s.texture.source.scaleMode = "nearest", s;
}
draw() {
const t = [];
this.kills > 0 && (t.push(this.killSprite), t.push(this.killText), this.killText.text = this.kills), this.jumps > 0 && (t.push(this.jumpSprite), t.push(this.jumpText), this.jumpText.text = this.jumps);
const e = 4;
let r = -(t.reduce((n, a) => n + a.width, 0) + e * (t.length - 1)) / 2;
this.container.removeChildren();
for (const n of t)
n.position.set(r, 0), r += n.width + e, this.container.addChild(n);
}
update(t) {
this.container.position.x = t.position.x ?? this.container.position.x, this.container.position.y = t.position.y ?? this.container.position.y;
}
}
const ec = (i, t) => i.x < t.x + t.w && i.x + i.w > t.x && i.y < t.y + t.h && i.y + i.h > t.y, ic = (i, t, e) => {
const s = {
...i,
x: i.x + (e.x ?? 0),
y: i.y + (e.y ?? 0)
};
return ec(s, t) ? i.y + i.h < t.y && s.y + s.h >= t.y : !1;
};
class ir {
constructor() {
w(this, "container", new O());
w(this, "userState", {});
w(this, "state", {
name: "",
sprite: "",
color: new J("#969696"),
direction: 1,
scale: 1,
isAnonymous: !1,
isImmortal: !1,
zIndex: 0
});
w(this, "animationState", Q.Idle);
w(this, "sprite");
w(this, "trail", new Jl());
w(this, "name", new Kl());
w(this, "info", new tc());
w(this, "message", new ql(() => {
this.state.zIndex = ct.zIndexEvotarMax(this.container.zIndex);
}));
w(this, "emoteSpitter", new $l());
w(this, "velocity", {
x: 0,
y: 0
});
w(this, "runSpeed", 0.05);
w(this, "gravity", 0.2);
w(this, "dashAcc", 3);
w(this, "isJumping", !1);
w(this, "isHitJumping", !1);
w(this, "isDashing", !1);
w(this, "isDespawned", !1);
w(this, "isDead", !1);
w(this, "deathTimer");
w(this, "landTimer");
w(this, "stateTimer");
w(this, "scaleTimer");
w(this, "spawnTween");
w(this, "fadeTween");
w(this, "scaleTween");
w(this, "offset", 0);
this.container.addChild(this.name.text), this.container.addChild(this.info.container), this.container.addChild(this.emoteSpitter.container), this.container.addChild(this.message.container), this.container.sortableChildren = !0;
}
get screenBounds() {
return { left: this.offset, right: N.renderer.width - this.offset };
}
getCenterOffsetY() {
return this.sprite ? this.sprite.data.collider.h / 2 * this.getScale() : 0;
}
getCenterPosition() {
return {
x: this.container.position.x,
y: this.container.position.y - this.getCenterOffsetY()
};
}
setPosition(t) {
this.container.position = t;
}
getScale() {
return this.sprite ? this.state.scale * this.sprite.data.scale : this.state.scale;
}
getCollider() {
if (this.sprite) {
const t = this.sprite.data.collider.x * this.getScale(), e = this.sprite.data.collider.h * this.getScale();
return {
x: this.container.position.x - t,
y: this.container.position.y - e,
w: this.sprite.data.collider.w * this.getScale(),
h: this.sprite.data.collider.h * this.getScale()
};
}
return {
x: 0,
y: 0,
w: 0,
h: 0
};
}
async resurrect() {
this.deathTimer && this.deathTimer.complete();
}
async die() {
this.state.isImmortal || (this.isDead = !0, this.container.visible = !1, ct.kill(this), this.deathTimer = new It(1e3 * 60 * 1, () => {
!this.isDespawned && this.isDead && (this.isDead = !1, this.container.visible = !0, this.state.scale = 1, ct.resurrect(this));
}));
}
spawn(t = { isFalling: !1 }) {
if (!this.sprite)
return;
const e = this.sprite.data.collider, s = this.sprite.data.size, r = -(e.y + e.h - s.h / 2), n = t.isFalling ? r : N.renderer.height, a = s.w * this.getScale(), o = t.positionX != null ? t.positionX * this.screenBounds.right : Math.random() * (this.screenBounds.right - a) + a / 2, h = n * this.getScale();
if (this.container.x = o, this.container.y = h, this.state.direction = Math.random() > 0.5 ? 1 : -1, !t.isFalling) {
const c = ct.zIndexEvotarMin(this.container.zIndex);
this.state.zIndex = c, this.container.alpha = 0, this.spawnTween = new $t(this.container).to({ alpha: 1 }, 500).onComplete(t.onComplete).start();
}
this.stateTimer = new It(5e3, () => {
this.isJumping || this.setAnimationState(Q.Run);
});
}
despawn(t = {}) {
this.fadeTween && this.fadeTween.isPlaying() || (this.fadeTween = new $t(this.container).to({ alpha: 0 }, 1e3).onComplete(() => {
this.isDespawned = !0, t.onComplete && t.onComplete();
}).start());
}
scale(t) {
this.scaleTween && this.scaleTween.isPlaying() || this.scaleTimer && !this.scaleTimer.isCompleted || (this.scaleTween = new $t(this).to({ state: { scale: t.value ?? 2 } }, 2e3).onComplete(() => {
this.scaleTimer = new It((t.duration ?? 10) * 1e3, () => {
this.scaleTween = new $t(this).to({ state: { scale: 1 } }, 2e3).start();
});
}).start());
}
addJumpHit(t) {
this.info.addJumps(t);
}
canDoAction() {
return !this.isDespawned && !this.isDead;
}
async jump(t) {
this.canDoAction() && (this.isJumping || (this.isJumping = !0, un.play("jump"), await Ql(300), this.velocity.x = this.state.direction * ((t == null ? void 0 : t.velocityX) ?? 3.5), this.velocity.y = (t == null ? void 0 : t.velocityY) ?? -8, this.setAnimationState(Q.Jump), this.info.jumps > 0 && (this.info.useJump(), this.isHitJumping = !0)));
}
dash(t) {
this.canDoAction() && (this.isDashing || (this.isDashing = !0, this.velocity.x = this.state.direction * (t.force ?? 14)));
}
async setSprite(t) {
if (t && t != this.state.sprite) {
const e = await ti.getSpriteData(t);
if (!e)
return;
this.sprite && this.container.removeChild(this.sprite.container), this.state.sprite = t;
const s = ti.getAnimatedSprites(t);
this.sprite = new Zl(s, e.data), this.container.addChild(this.sprite.container), this.trail.setSprite(this.sprite), this.setAnimationState(this.animationState, !0);
}
}
async setProps(t) {
t.sprite && await this.setSprite(t.sprite), this.state = { ...this.state, ...t };
}
setUserProps(t) {
this.userState = { ...this.userState, ...t };
}
move() {
var s;
if (!this.sprite)
return;
const t = this.sprite.data.collider, e = {
x: this.container.position.x,
y: this.container.position.y
};
if (this.isDashing) {
const r = Math.sign(this.velocity.x);
this.velocity.x = this.velocity.x - r * this.dashAcc / Math.abs(this.velocity.x), r != Math.sign(this.velocity.x) ? (this.isDashing = !1, this.velocity.x = 0) : e.x += this.velocity.x;
} else {
if ((s = this.stateTimer) != null && s.isCompleted && (this.stateTimer = new It(Math.random() * 5e3, () => {
this.animationState == Q.Idle ? this.setAnimationState(Q.Run) : this.animationState == Q.Run && this.setAnimationState(Q.Idle);
})), this.animationState == Q.Run) {
const r = this.runSpeed * this.state.direction;
this.velocity.x = r * Ut;
}
this.velocity.y = this.velocity.y + this.gravity, e.x += this.velocity.x, e.y += this.velocity.y, this.isOnGround(e.y) && (this.velocity.y = 0, this.velocity.x = 0, e.y = N.renderer.height, this.animationState == Q.Fall && (this.setAnimationState(Q.Land), this.landTimer = new It(200, () => {
this.setAnimationState(Q.Idle), this.isJumping = !1, this.isHitJumping = !1;
}))), this.velocity.y > 0 && this.setAnimationState(Q.Fall);
}
if (this.animationState != Q.Idle || this.isDashing) {
const r = t.w / 2 * this.getScale(), n = this.container.x - r < this.screenBounds.left, a = this.container.x + r > this.screenBounds.right;
(n || a) && (this.state.direction = -this.state.direction, this.velocity.x = -this.velocity.x, n && (e.x = this.screenBounds.left + r), a && (e.x = this.screenBounds.right - r));
}
this.container.position.set(e.x, e.y), this.isHitJumping && this.jumpHit();
}
jumpHit() {
const t = ct.getEvotars();
for (const e in t) {
const s = t[e];
if (s) {
const r = this.getCollider(), n = s.getCollider();
s != this && ic(r, n, {
x: this.velocity.x,
y: this.velocity.y
}) && !s.isDead && !s.state.isImmortal && (s.die(), this.info.addKill());
}
}
}
update() {
var r, n, a, o, h, c, l;
if (this.isDespawned || !this.sprite)
return;
(r = this.landTimer) == null || r.tick(), (n = this.stateTimer) == null || n.tick(), (a = this.scaleTimer) == null || a.tick(), (o = this.fadeTween) == null || o.update(), (h = this.spawnTween) == null || h.update(), (c = this.scaleTween) == null || c.update(), (l = this.deathTimer) == null || l.tick(), this.container.zIndex = this.state.zIndex;
const t = this.sprite.data.collider;
this.name.update({
name: this.state.name,
isVisible: !this.state.isAnonymous,
position: {
y: -t.h * this.getScale()
}
}), this.info.update({
position: {
y: this.name.text.position.y - this.name.text.height - 6
}
}), this.message.update({
position: {
y: this.info.container.position.y - this.info.container.height - 6
}
}), this.emoteSpitter.update({
position: {
y: this.message.container.position.y - this.message.container.height
}
}), this.isDead || this.move();
const e = Object.fromEntries(
this.sprite.data.colored.map((u) => [
u,
this.userState.color ? this.userState.color : this.state.color
])
), s = this.sprite.data.flip ? this.state.direction : 1;
this.sprite.update({
color: e,
scale: {
x: s * this.getScale(),
y: this.getScale()
},
play: !this.isDashing
}), this.trail.update({
play: this.isDashing
});
}
isOnGround(t) {
return t > N.renderer.height;
}
addMessage(t) {
var e;
this.message.add(t), this.state.isAnonymous = !1, (e = this.fadeTween) == null || e.stop(), this.fadeTween = void 0, this.container.alpha = 1;
}
async spitEmotes(t) {
for (const e of t)
await this.emoteSpitter.add(e);
}
async setAnimationState(t, e = !1) {
this.animationState == t && !e || (this.animationState = t, this.sprite && this.sprite.setTag(t));
}
}
class sc {
play(t, e, s) {
const r = yt.get(t), n = ti.createAnimatedSprite(t, r);
n && (N.stage.addChild(n), n.zIndex = 1e3, n.scale.set(s, s), n.position.set(e.x, e.y), n.anchor.set(0.5, 0.5), n.loop = !1, n.texture.source.scaleMode = "nearest", n.play(), n.onComplete = () => {
N.stage.removeChild(n);
});
}
}
const sr = new sc(), rc = 4;
class nc {
constructor(t) {
w(this, "container", new O());
w(this, "sprite");
w(this, "gravity", 0.2);
w(this, "velocity", {
x: 0,
y: 0
});
w(this, "fadeTween");
this.evotar = t;
const e = Math.random() > 0.5 ? "rip1" : "rip2", s = yt.get(e);
this.sprite = xt.from(s);
}
isOnGround(t) {
return t > N.renderer.height;
}
update() {
var e;
(e = this.fadeTween) == null || e.update();
const t = {
x: this.container.position.x,
y: this.container.position.y
};
this.velocity.y = this.velocity.y + this.gravity, t.x += this.velocity.x, t.y += this.velocity.y, this.isOnGround(t.y) && (this.velocity.y = 0, this.velocity.x = 0, t.y = N.renderer.height), this.container.position.set(t.x, t.y);
}
despawn(t = !1, e = () => {
}) {
if (t)
this.fadeTween = new $t(this.container).to({ alpha: 0 }, 1e3).onComplete(e).start();
else {
const s = {
x: this.container.position.x,
y: this.container.position.y - 8 * this.container.scale.x
};
sr.play("poof", s, this.container.scale.x), e();
}
}
spawn() {
const t = this.evotar.getCenterPosition(), e = this.evotar.getScale();
this.container.removeChildren(), this.container.addChild(this.sprite), this.container.position.set(
t.x,
(t.y ?? 0) + this.sprite.height / 2 * e
), this.container.scale.set(rc), this.sprite.anchor.set(0.5, 1), this.sprite.texture.source.scaleMode = "nearest", sr.play(
"poof",
{
x: t.x,
y: t.y
},
e
);
}
}
const ac = 1e3 * 60 * 5;
class oc {
constructor() {
w(this, "viewers", {});
w(this, "viewerArray", []);
w(this, "tombstones", []);
w(this, "raiders", []);
w(this, "recentEvotarActivity", {});
w(this, "subscriptions", []);
w(this, "hasActivity", (t) => !!this.recentEvotarActivity[t]);
}
subscribe(t) {
this.subscriptions.push(t);
}
update() {
for (const t in this.viewers) {
const e = this.viewers[t];
e && e.update();
}
for (const t of this.raiders)
t.update();
for (const t of this.tombstones)
t.update();
}
getEvotars() {
return Object.values(this.viewers).concat(this.raiders);
}
async spawnViewerEvotar(t, e, s) {
const r = new ir();
if (this.addViewer(t, r), N.settings.maxEvotars && this.viewerArray.length > N.settings.maxEvotars) {
const n = this.viewerArray.shift(), a = n != null ? this.viewers[n] : void 0;
n && a && this.deleteViewer(n, a);
}
return await r.setProps(e), r.spawn(s), this.recentEvotarActivity[t] = performance.now(), r;
}
async processRaid(t) {
if (!N.settings.fallingRaiders)
return;
const e = 1 / t.viewers.count * 5e3;
let s = t.viewers.count;
N.settings.maxEvotars && (s = Math.min(s, N.settings.maxEvotars));
for (let o = 0; o < t.viewers.count; o++) {
const h = new ir();
await h.setProps({
isAnonymous: !0,
zIndex: -1,
sprite: t.viewers.sprite,
color: new J(t.broadcaster.info.color)
}), ji.add(e * o, () => {
this.addRaider(h), h.spawn({ isFalling: !0 });
}), ji.add(o * e + 6e4, () => {
this.despawnRaider(h);
});
}
const r = this.viewers[t.broadcaster.id], n = {
...this.prepareEvotarProps(
t.broadcaster.info.displayName,
t.broadcaster.info.color,
t.broadcaster.info.sprite
),
scale: 2,
isImmortal: !0
}, a = async () => {
await this.spawnViewerEvotar(t.broadcaster.id, n, {
isFalling: !0,
positionX: 0.5
});
};
this.recentEvotarActivity[t.broadcaster.id] = performance.now(), r ? r.despawn({
onComplete: () => {
a();
}
}) : a();
}
despawnTombStone(t) {
const e = this.tombstones.find((s) => s.evotar == t);
e && e.despawn(!0, () => {
this.deleteTombStone(e);
});
}
despawnRaider(t) {
t.despawn({
onComplete: () => {
this.deleteRaider(t);
}
}), this.despawnTombStone(t);
}
despawnViewer(t, e) {
e.despawn({
onComplete: () => {
this.deleteViewer(t, e);
}
}), this.despawnTombStone(e);
}
async processChatters(t) {
for (const e in this.viewers) {
const s = this.recentEvotarActivity[e], r = !!s && performance.now() - s < ac;
if (t.every((n) => n.userId != e) && !r) {
const n = this.viewers[e];
n && this.despawnViewer(e, n);
}
}
if (N.settings.showAnonymousEvotars) {
for (const e of t)
if (!this.viewers[e.userId]) {
const r = {
name: e.name,
isAnonymous: !this.hasActivity(e.userId),
sprite: "default"
};
await this.spawnViewerEvotar(e.userId, r, {});
}
}
}
doAction(t, e) {
if (Nh(t) && e.jump({
velocityX: t.data.velocityX,
velocityY: t.data.velocityY
}), jh(t) && e.dash({ force: t.data.force }), Yh(t)) {
const s = P(t.data.color);
s && s.isValid() && e.setUserProps({ color: new J(t.data.color) });
}
Vh(t) && e.scale({
value: t.data.scale,
duration: t.data.duration
}), Xh(t) && e.setSprite(t.data.sprite), $h(t) && e.addJumpHit(t.data.count), qh(t) && e.resurrect();
}
prepareEvotarProps(t, e, s) {
const r = {
name: t,
isAnonymous: !1
};
if (s && (r.sprite = s), e)
try {
r.color = new J(e);
} catch {
}
return r;
}
async processAction(t) {
const e = this.viewers[t.userId], s = this.prepareEvotarProps(
t.info.displayName,
t.info.color,
t.info.sprite
);
e ? (await e.setProps(s), this.doAction(t, e)) : await this.spawnViewerEvotar(t.userId, s, {
onComplete: () => {
const r = this.viewers[t.userId];
r && this.doAction(t, r);
}
});
}
async processMessage(t) {
const e = this.prepareEvotarProps(
t.info.displayName,
t.info.color,
t.info.sprite
);
let s = this.viewers[t.userId];
if (s)
s.setProps(e);
else {
const r = N.settings.fallingEvotars ? !this.hasActivity(t.userId) : !1;
s = await this.spawnViewerEvotar(t.userId, e, {
isFalling: r
});
}
this.recentEvotarActivity[t.userId] = performance.now(), t.message && s.addMessage(t.message), t.emotes.length > 0 && s.spitEmotes(t.emotes);
}
resurrect(t) {
const e = this.tombstones.find((s) => s.evotar == t);
e && (t.setPosition(e.container.position), e.despawn(), this.deleteTombStone(e));
}
kill(t) {
const e = new nc(t);
this.addTombStone(e), e.spawn();
}
addTombStone(t) {
N.stage.addChild(t.container), this.tombstones.push(t);
}
deleteTombStone(t) {
N.stage.removeChild(t.container), this.tombstones = this.tombstones.filter((e) => e != t);
}
addViewer(t, e) {
this.subscriptions.forEach((s) => s.onAdd(e)), this.viewers[t] = e, this.viewerArray.push(t);
}
deleteViewer(t, e) {
this.subscriptions.forEach((s) => s.onDelete(e)), delete this.viewers[t];
}
addRaider(t) {
this.subscriptions.forEach((e) => e.onAdd(t)), this.raiders.push(t);
}
deleteRaider(t) {
this.subscriptions.forEach((e) => e.onDelete(t)), this.raiders = this.raiders.filter((e) => e != t);
}
zIndexEvotarMax(t) {
return Object.values(this.viewers).reduce((e, s) => s && e <= s.container.zIndex ? s.container.zIndex + 1 : e, t);
}
zIndexEvotarMin(t) {
return Object.values(this.viewers).reduce((e, s) => s && e >= s.container.zIndex ? s.container.zIndex - 1 : e, t);
}
}
const ct = new oc();
class hc {
constructor() {
w(this, "stage", new O());
w(this, "evotars", {});
w(this, "chatterIds", []);
w(this, "settings", {});
w(this, "renderer");
w(this, "ticker");
}
async initialize(t, e) {
ti.initialize(e.spriteLoaderFn), un.initialize(e.sounds), e.font && await yt.load({
src: e.font,
data: { family: "Custom Font" }
});
for (const s in e.assets)
yt.add({
alias: s,
src: e.assets[s]
});
await yt.load(["skull", "weight", "poof", "rip1", "rip2"]), this.ticker = new ot(), this.ticker.deltaTime = Ut * 0.06, this.renderer = await Va({
preference: "webgl"
}), await this.renderer.init({
width: t.clientWidth,
height: t.clientHeight,
backgroundAlpha: 0
}), t.appendChild(this.renderer.canvas), window.onresize = () => {
this.renderer.resize(t.clientWidth, t.clientHeight);
}, this.stage.sortableChildren = !0, ct.subscribe({
onAdd: (s) => this.stage.addChild(s.container),
onDelete: (s) => {
this.stage.removeChild(s.container), this.stage.removeChild(s.trail.container);
}
});
}
updateSettings(t) {
this.settings = t;
}
update() {
ji.tick(), ct.update(), this.renderer.render(this.stage);
}
}
const N = new hc();
class fc {
constructor(t, e) {
w(this, "isRendered", !1);
w(this, "processMessage", (t) => ct.processMessage(t));
w(this, "processAction", (t) => ct.processAction(t));
w(this, "processChatters", (t) => ct.processChatters(t));
w(this, "processRaid", (t) => ct.processRaid(t));
this.root = t, this.options = e;
}
get manager() {
return ct;
}
updateSettings(t) {
N.updateSettings(t);
}
async run() {
if (this.isRendered)
return;
this.isRendered = !0, await (async () => {
await N.initialize(this.root, this.options), performance.now();
let e = -1;
const r = 1e3 / 60;
requestAnimationFrame(n);
function n(a = performance.now()) {
const o = a - e | 0;
o > r && (e = a - o % r, N.update()), requestAnimationFrame(n);
}
})();
}
}
export {
zh as $,
Gr as A,
at as B,
O as C,
Y as D,
B as E,
Ss as F,
aa as G,
_i as H,
J as I,
gr as J,
q as K,
$ as L,
D as M,
To as N,
ne as O,
st as P,
gh as Q,
tt as R,
Fo as S,
ot as T,
Te as U,
tn as V,
Gh as W,
an as X,
Be as Y,
rt as Z,
hn as _,
Bt as a,
Xr as a0,
Zt as a1,
bt as a2,
ks as a3,
Ze as a4,
Ln as a5,
qr as a6,
fc as a7,
Nh as a8,
Yh as a9,
Vh as aa,
jh as ab,
Xh as ac,
$h as ad,
qh as ae,
Ee as b,
wa as c,
Dr as d,
dt as e,
Fs as f,
Eo as g,
Mr as h,
Ot as i,
L as j,
ba as k,
Fn as l,
Wr as m,
uc as n,
Lo as o,
Io as p,
kt as q,
jn as r,
pr as s,
St as t,
et as u,
xt as v,
it as w,
Aa as x,
Ha as y,
Ts as z
};