wave-roll
Version:
JavaScript Library for Comparative MIDI Piano-Roll Visualization
1,565 lines (1,523 loc) • 86.2 kB
JavaScript
import { q as Le, G as ae, t as ne, u as He, k as ie, M as v, v as oe, E as u, e as O, x as S, y as ze, z as F, F as b, R as L, H as le, I as We, s as m, S as f, h as B, w as H, J, K as Ve, b as X, B as k, i as U, L as M, j as T, N as w, O as Ne, a as je, Q as ue, V as de, W as ce, X as he, C as P, Y as $e, Z as A, D as z, _ as qe, P as Ke, c as Ye, T as Q, $ as Z, a0 as Je, a1 as Xe, a2 as Qe } from "./index-B5Sv2rNJ.js";
import { S as fe, B as pe, c as Ze } from "./colorToUniform-zJcCVLeu.js";
const me = class I extends Le {
/**
* @param options - The optional parameters of this filter.
*/
constructor(e) {
e = { ...I.defaultOptions, ...e }, super(e), this.enabled = !0, this._state = fe.for2d(), this.blendMode = e.blendMode, this.padding = e.padding, typeof e.antialias == "boolean" ? this.antialias = e.antialias ? "on" : "off" : this.antialias = e.antialias, this.resolution = e.resolution, this.blendRequired = e.blendRequired, this.clipToViewport = e.clipToViewport, this.addResource("uTexture", 0, 1);
}
/**
* Applies the filter
* @param filterManager - The renderer to retrieve the filter from
* @param input - The input render target.
* @param output - The target to output to.
* @param clearMode - Should the output be cleared before rendering to it
*/
apply(e, t, r, s) {
e.applyFilter(this, t, r, s);
}
/**
* Get the blend mode of the filter.
* @default "normal"
*/
get blendMode() {
return this._state.blendMode;
}
/** Sets the blend mode of the filter. */
set blendMode(e) {
this._state.blendMode = e;
}
/**
* A short hand function to create a filter based of a vertex and fragment shader src.
* @param options
* @returns A shiny new PixiJS filter!
*/
static from(e) {
const { gpu: t, gl: r, ...s } = e;
let n, i;
return t && (n = ae.from(t)), r && (i = ne.from(r)), new I({
gpuProgram: n,
glProgram: i,
...s
});
}
};
me.defaultOptions = {
blendMode: "normal",
resolution: 1,
padding: 0,
antialias: "off",
blendRequired: !1,
clipToViewport: !0
};
let et = me;
var tt = `in vec2 vMaskCoord;
in vec2 vTextureCoord;
uniform sampler2D uTexture;
uniform sampler2D uMaskTexture;
uniform float uAlpha;
uniform vec4 uMaskClamp;
uniform float uInverse;
out vec4 finalColor;
void main(void)
{
float clip = step(3.5,
step(uMaskClamp.x, vMaskCoord.x) +
step(uMaskClamp.y, vMaskCoord.y) +
step(vMaskCoord.x, uMaskClamp.z) +
step(vMaskCoord.y, uMaskClamp.w));
// TODO look into why this is needed
float npmAlpha = uAlpha;
vec4 original = texture(uTexture, vTextureCoord);
vec4 masky = texture(uMaskTexture, vMaskCoord);
float alphaMul = 1.0 - npmAlpha * (1.0 - masky.a);
float a = alphaMul * masky.r * npmAlpha * clip;
if (uInverse == 1.0) {
a = 1.0 - a;
}
finalColor = original * a;
}
`, rt = `in vec2 aPosition;
out vec2 vTextureCoord;
out vec2 vMaskCoord;
uniform vec4 uInputSize;
uniform vec4 uOutputFrame;
uniform vec4 uOutputTexture;
uniform mat3 uFilterMatrix;
vec4 filterVertexPosition( vec2 aPosition )
{
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
vec2 filterTextureCoord( vec2 aPosition )
{
return aPosition * (uOutputFrame.zw * uInputSize.zw);
}
vec2 getFilterCoord( vec2 aPosition )
{
return ( uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0) ).xy;
}
void main(void)
{
gl_Position = filterVertexPosition(aPosition);
vTextureCoord = filterTextureCoord(aPosition);
vMaskCoord = getFilterCoord(aPosition);
}
`, ee = `struct GlobalFilterUniforms {
uInputSize:vec4<f32>,
uInputPixel:vec4<f32>,
uInputClamp:vec4<f32>,
uOutputFrame:vec4<f32>,
uGlobalFrame:vec4<f32>,
uOutputTexture:vec4<f32>,
};
struct MaskUniforms {
uFilterMatrix:mat3x3<f32>,
uMaskClamp:vec4<f32>,
uAlpha:f32,
uInverse:f32,
};
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
@group(0) @binding(1) var uTexture: texture_2d<f32>;
@group(0) @binding(2) var uSampler : sampler;
@group(1) @binding(0) var<uniform> filterUniforms : MaskUniforms;
@group(1) @binding(1) var uMaskTexture: texture_2d<f32>;
struct VSOutput {
@builtin(position) position: vec4<f32>,
@location(0) uv : vec2<f32>,
@location(1) filterUv : vec2<f32>,
};
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
{
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
{
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
}
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
{
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
}
fn getFilterCoord(aPosition:vec2<f32> ) -> vec2<f32>
{
return ( filterUniforms.uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0) ).xy;
}
fn getSize() -> vec2<f32>
{
return gfu.uGlobalFrame.zw;
}
@vertex
fn mainVertex(
@location(0) aPosition : vec2<f32>,
) -> VSOutput {
return VSOutput(
filterVertexPosition(aPosition),
filterTextureCoord(aPosition),
getFilterCoord(aPosition)
);
}
@fragment
fn mainFragment(
@location(0) uv: vec2<f32>,
@location(1) filterUv: vec2<f32>,
@builtin(position) position: vec4<f32>
) -> @location(0) vec4<f32> {
var maskClamp = filterUniforms.uMaskClamp;
var uAlpha = filterUniforms.uAlpha;
var clip = step(3.5,
step(maskClamp.x, filterUv.x) +
step(maskClamp.y, filterUv.y) +
step(filterUv.x, maskClamp.z) +
step(filterUv.y, maskClamp.w));
var mask = textureSample(uMaskTexture, uSampler, filterUv);
var source = textureSample(uTexture, uSampler, uv);
var alphaMul = 1.0 - uAlpha * (1.0 - mask.a);
var a: f32 = alphaMul * mask.r * uAlpha * clip;
if (filterUniforms.uInverse == 1.0) {
a = 1.0 - a;
}
return source * a;
}
`;
class st extends et {
constructor(e) {
const { sprite: t, ...r } = e, s = new He(t.texture), n = new ie({
uFilterMatrix: { value: new v(), type: "mat3x3<f32>" },
uMaskClamp: { value: s.uClampFrame, type: "vec4<f32>" },
uAlpha: { value: 1, type: "f32" },
uInverse: { value: e.inverse ? 1 : 0, type: "f32" }
}), i = ae.from({
vertex: {
source: ee,
entryPoint: "mainVertex"
},
fragment: {
source: ee,
entryPoint: "mainFragment"
}
}), o = ne.from({
vertex: rt,
fragment: tt,
name: "mask-filter"
});
super({
...r,
gpuProgram: i,
glProgram: o,
clipToViewport: !1,
resources: {
filterUniforms: n,
uMaskTexture: t.texture.source
}
}), this.sprite = t, this._textureMatrix = s;
}
set inverse(e) {
this.resources.filterUniforms.uniforms.uInverse = e ? 1 : 0;
}
get inverse() {
return this.resources.filterUniforms.uniforms.uInverse === 1;
}
apply(e, t, r, s) {
this._textureMatrix.texture = this.sprite.texture, e.calculateSpriteMatrix(
this.resources.filterUniforms.uniforms.uFilterMatrix,
this.sprite
).prepend(this._textureMatrix.mapCoord), this.resources.uMaskTexture = this.sprite.texture.source, e.applyFilter(this, t, r, s);
}
}
const W = class ve {
constructor(e, t) {
this.state = fe.for2d(), this._batchersByInstructionSet = /* @__PURE__ */ Object.create(null), this._activeBatches = /* @__PURE__ */ Object.create(null), this.renderer = e, this._adaptor = t, this._adaptor.init?.(this);
}
static getBatcher(e) {
return new this._availableBatchers[e]();
}
buildStart(e) {
let t = this._batchersByInstructionSet[e.uid];
t || (t = this._batchersByInstructionSet[e.uid] = /* @__PURE__ */ Object.create(null), t.default || (t.default = new oe({
maxTextures: this.renderer.limits.maxBatchableTextures
}))), this._activeBatches = t, this._activeBatch = this._activeBatches.default;
for (const r in this._activeBatches)
this._activeBatches[r].begin();
}
addToBatch(e, t) {
if (this._activeBatch.name !== e.batcherName) {
this._activeBatch.break(t);
let r = this._activeBatches[e.batcherName];
r || (r = this._activeBatches[e.batcherName] = ve.getBatcher(e.batcherName), r.begin()), this._activeBatch = r;
}
this._activeBatch.add(e);
}
break(e) {
this._activeBatch.break(e);
}
buildEnd(e) {
this._activeBatch.break(e);
const t = this._activeBatches;
for (const r in t) {
const s = t[r], n = s.geometry;
n.indexBuffer.setDataWithSize(s.indexBuffer, s.indexSize, !0), n.buffers[0].setDataWithSize(s.attributeBuffer.float32View, s.attributeSize, !1);
}
}
upload(e) {
const t = this._batchersByInstructionSet[e.uid];
for (const r in t) {
const s = t[r], n = s.geometry;
s.dirty && (s.dirty = !1, n.buffers[0].update(s.attributeSize * 4));
}
}
execute(e) {
if (e.action === "startBatch") {
const t = e.batcher, r = t.geometry, s = t.shader;
this._adaptor.start(this, r, s);
}
this._adaptor.execute(this, e);
}
destroy() {
this.state = null, this.renderer = null, this._adaptor = null;
for (const e in this._activeBatches)
this._activeBatches[e].destroy();
this._activeBatches = null;
}
};
W.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "batch"
};
W._availableBatchers = /* @__PURE__ */ Object.create(null);
let ge = W;
O.handleByMap(u.Batcher, ge._availableBatchers);
O.add(oe);
const Ut = {
name: "texture-bit",
vertex: {
header: (
/* wgsl */
`
struct TextureUniforms {
uTextureMatrix:mat3x3<f32>,
}
@group(2) @binding(2) var<uniform> textureUniforms : TextureUniforms;
`
),
main: (
/* wgsl */
`
uv = (textureUniforms.uTextureMatrix * vec3(uv, 1.0)).xy;
`
)
},
fragment: {
header: (
/* wgsl */
`
@group(2) @binding(0) var uTexture: texture_2d<f32>;
@group(2) @binding(1) var uSampler: sampler;
`
),
main: (
/* wgsl */
`
outColor = textureSample(uTexture, uSampler, vUV);
`
)
}
}, At = {
name: "texture-bit",
vertex: {
header: (
/* glsl */
`
uniform mat3 uTextureMatrix;
`
),
main: (
/* glsl */
`
uv = (uTextureMatrix * vec3(uv, 1.0)).xy;
`
)
},
fragment: {
header: (
/* glsl */
`
uniform sampler2D uTexture;
`
),
main: (
/* glsl */
`
outColor = texture(uTexture, vUV);
`
)
}
}, at = new F();
class nt extends le {
constructor() {
super(), this.filters = [new st({
sprite: new We(m.EMPTY),
inverse: !1,
resolution: "inherit",
antialias: "inherit"
})];
}
get sprite() {
return this.filters[0].sprite;
}
set sprite(e) {
this.filters[0].sprite = e;
}
get inverse() {
return this.filters[0].inverse;
}
set inverse(e) {
this.filters[0].inverse = e;
}
}
class xe {
constructor(e) {
this._activeMaskStage = [], this._renderer = e;
}
push(e, t, r) {
const s = this._renderer;
if (s.renderPipes.batch.break(r), r.add({
renderPipeId: "alphaMask",
action: "pushMaskBegin",
mask: e,
inverse: t._maskOptions.inverse,
canBundle: !1,
maskedContainer: t
}), e.inverse = t._maskOptions.inverse, e.renderMaskToTexture) {
const n = e.mask;
n.includeInBuild = !0, n.collectRenderables(
r,
s,
null
), n.includeInBuild = !1;
}
s.renderPipes.batch.break(r), r.add({
renderPipeId: "alphaMask",
action: "pushMaskEnd",
mask: e,
maskedContainer: t,
inverse: t._maskOptions.inverse,
canBundle: !1
});
}
pop(e, t, r) {
this._renderer.renderPipes.batch.break(r), r.add({
renderPipeId: "alphaMask",
action: "popMaskEnd",
mask: e,
inverse: t._maskOptions.inverse,
canBundle: !1
});
}
execute(e) {
const t = this._renderer, r = e.mask.renderMaskToTexture;
if (e.action === "pushMaskBegin") {
const s = S.get(nt);
if (s.inverse = e.inverse, r) {
e.mask.mask.measurable = !0;
const n = ze(e.mask.mask, !0, at);
e.mask.mask.measurable = !1, n.ceil();
const i = t.renderTarget.renderTarget.colorTexture.source, o = b.getOptimalTexture(
n.width,
n.height,
i._resolution,
i.antialias
);
t.renderTarget.push(o, !0), t.globalUniforms.push({
offset: n,
worldColor: 4294967295
});
const l = s.sprite;
l.texture = o, l.worldTransform.tx = n.minX, l.worldTransform.ty = n.minY, this._activeMaskStage.push({
filterEffect: s,
maskedContainer: e.maskedContainer,
filterTexture: o
});
} else
s.sprite = e.mask.mask, this._activeMaskStage.push({
filterEffect: s,
maskedContainer: e.maskedContainer
});
} else if (e.action === "pushMaskEnd") {
const s = this._activeMaskStage[this._activeMaskStage.length - 1];
r && (t.type === L.WEBGL && t.renderTarget.finishRenderPass(), t.renderTarget.pop(), t.globalUniforms.pop()), t.filter.push({
renderPipeId: "filter",
action: "pushFilter",
container: s.maskedContainer,
filterEffect: s.filterEffect,
canBundle: !1
});
} else if (e.action === "popMaskEnd") {
t.filter.pop();
const s = this._activeMaskStage.pop();
r && b.returnTexture(s.filterTexture), S.return(s.filterEffect);
}
}
destroy() {
this._renderer = null, this._activeMaskStage = null;
}
}
xe.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "alphaMask"
};
class _e {
constructor(e) {
this._colorStack = [], this._colorStackIndex = 0, this._currentColor = 0, this._renderer = e;
}
buildStart() {
this._colorStack[0] = 15, this._colorStackIndex = 1, this._currentColor = 15;
}
push(e, t, r) {
this._renderer.renderPipes.batch.break(r);
const n = this._colorStack;
n[this._colorStackIndex] = n[this._colorStackIndex - 1] & e.mask;
const i = this._colorStack[this._colorStackIndex];
i !== this._currentColor && (this._currentColor = i, r.add({
renderPipeId: "colorMask",
colorMask: i,
canBundle: !1
})), this._colorStackIndex++;
}
pop(e, t, r) {
this._renderer.renderPipes.batch.break(r);
const n = this._colorStack;
this._colorStackIndex--;
const i = n[this._colorStackIndex - 1];
i !== this._currentColor && (this._currentColor = i, r.add({
renderPipeId: "colorMask",
colorMask: i,
canBundle: !1
}));
}
execute(e) {
this._renderer.colorMask.setMask(e.colorMask);
}
destroy() {
this._colorStack = null;
}
}
_e.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "colorMask"
};
class be {
constructor(e) {
this._maskStackHash = {}, this._maskHash = /* @__PURE__ */ new WeakMap(), this._renderer = e;
}
push(e, t, r) {
var s;
const n = e, i = this._renderer;
i.renderPipes.batch.break(r), i.renderPipes.blendMode.setBlendMode(n.mask, "none", r), r.add({
renderPipeId: "stencilMask",
action: "pushMaskBegin",
mask: e,
inverse: t._maskOptions.inverse,
canBundle: !1
});
const o = n.mask;
o.includeInBuild = !0, this._maskHash.has(n) || this._maskHash.set(n, {
instructionsStart: 0,
instructionsLength: 0
});
const l = this._maskHash.get(n);
l.instructionsStart = r.instructionSize, o.collectRenderables(
r,
i,
null
), o.includeInBuild = !1, i.renderPipes.batch.break(r), r.add({
renderPipeId: "stencilMask",
action: "pushMaskEnd",
mask: e,
inverse: t._maskOptions.inverse,
canBundle: !1
});
const d = r.instructionSize - l.instructionsStart - 1;
l.instructionsLength = d;
const c = i.renderTarget.renderTarget.uid;
(s = this._maskStackHash)[c] ?? (s[c] = 0);
}
pop(e, t, r) {
const s = e, n = this._renderer;
n.renderPipes.batch.break(r), n.renderPipes.blendMode.setBlendMode(s.mask, "none", r), r.add({
renderPipeId: "stencilMask",
action: "popMaskBegin",
inverse: t._maskOptions.inverse,
canBundle: !1
});
const i = this._maskHash.get(e);
for (let o = 0; o < i.instructionsLength; o++)
r.instructions[r.instructionSize++] = r.instructions[i.instructionsStart++];
r.add({
renderPipeId: "stencilMask",
action: "popMaskEnd",
canBundle: !1
});
}
execute(e) {
var t;
const r = this._renderer, s = r.renderTarget.renderTarget.uid;
let n = (t = this._maskStackHash)[s] ?? (t[s] = 0);
e.action === "pushMaskBegin" ? (r.renderTarget.ensureDepthStencil(), r.stencil.setStencilMode(f.RENDERING_MASK_ADD, n), n++, r.colorMask.setMask(0)) : e.action === "pushMaskEnd" ? (e.inverse ? r.stencil.setStencilMode(f.INVERSE_MASK_ACTIVE, n) : r.stencil.setStencilMode(f.MASK_ACTIVE, n), r.colorMask.setMask(15)) : e.action === "popMaskBegin" ? (r.colorMask.setMask(0), n !== 0 ? r.stencil.setStencilMode(f.RENDERING_MASK_REMOVE, n) : (r.renderTarget.clear(null, B.STENCIL), r.stencil.setStencilMode(f.DISABLED, n)), n--) : e.action === "popMaskEnd" && (e.inverse ? r.stencil.setStencilMode(f.INVERSE_MASK_ACTIVE, n) : r.stencil.setStencilMode(f.MASK_ACTIVE, n), r.colorMask.setMask(15)), this._maskStackHash[s] = n;
}
destroy() {
this._renderer = null, this._maskStackHash = null, this._maskHash = null;
}
}
be.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "stencilMask"
};
function It(a, e) {
for (const t in a.attributes) {
const r = a.attributes[t], s = e[t];
s ? (r.format ?? (r.format = s.format), r.offset ?? (r.offset = s.offset), r.instance ?? (r.instance = s.instance)) : H(`Attribute ${t} is not present in the shader, but is present in the geometry. Unable to infer attribute details.`);
}
it(a);
}
function it(a) {
const { buffers: e, attributes: t } = a, r = {}, s = {};
for (const n in e) {
const i = e[n];
r[i.uid] = 0, s[i.uid] = 0;
}
for (const n in t) {
const i = t[n];
r[i.buffer.uid] += J(i.format).stride;
}
for (const n in t) {
const i = t[n];
i.stride ?? (i.stride = r[i.buffer.uid]), i.start ?? (i.start = s[i.buffer.uid]), s[i.buffer.uid] += J(i.format).stride;
}
}
const x = [];
x[f.NONE] = void 0;
x[f.DISABLED] = {
stencilWriteMask: 0,
stencilReadMask: 0
};
x[f.RENDERING_MASK_ADD] = {
stencilFront: {
compare: "equal",
passOp: "increment-clamp"
},
stencilBack: {
compare: "equal",
passOp: "increment-clamp"
}
};
x[f.RENDERING_MASK_REMOVE] = {
stencilFront: {
compare: "equal",
passOp: "decrement-clamp"
},
stencilBack: {
compare: "equal",
passOp: "decrement-clamp"
}
};
x[f.MASK_ACTIVE] = {
stencilWriteMask: 0,
stencilFront: {
compare: "equal",
passOp: "keep"
},
stencilBack: {
compare: "equal",
passOp: "keep"
}
};
x[f.INVERSE_MASK_ACTIVE] = {
stencilWriteMask: 0,
stencilFront: {
compare: "not-equal",
passOp: "keep"
},
stencilBack: {
compare: "not-equal",
passOp: "keep"
}
};
class Gt {
constructor(e) {
this._syncFunctionHash = /* @__PURE__ */ Object.create(null), this._adaptor = e, this._systemCheck();
}
/**
* Overridable function by `pixi.js/unsafe-eval` to silence
* throwing an error if platform doesn't support unsafe-evals.
* @private
*/
_systemCheck() {
if (!Ve())
throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.");
}
ensureUniformGroup(e) {
const t = this.getUniformGroupData(e);
e.buffer || (e.buffer = new X({
data: new Float32Array(t.layout.size / 4),
usage: k.UNIFORM | k.COPY_DST
}));
}
getUniformGroupData(e) {
return this._syncFunctionHash[e._signature] || this._initUniformGroup(e);
}
_initUniformGroup(e) {
const t = e._signature;
let r = this._syncFunctionHash[t];
if (!r) {
const s = Object.keys(e.uniformStructures).map((o) => e.uniformStructures[o]), n = this._adaptor.createUboElements(s), i = this._generateUboSync(n.uboElements);
r = this._syncFunctionHash[t] = {
layout: n,
syncFunction: i
};
}
return this._syncFunctionHash[t];
}
_generateUboSync(e) {
return this._adaptor.generateUboSync(e);
}
syncUniformGroup(e, t, r) {
const s = this.getUniformGroupData(e);
e.buffer || (e.buffer = new X({
data: new Float32Array(s.layout.size / 4),
usage: k.UNIFORM | k.COPY_DST
}));
let n = null;
return t || (t = e.buffer.data, n = e.buffer.dataInt32), r || (r = 0), s.syncFunction(e.uniforms, t, n, r), !0;
}
updateUniformGroup(e) {
if (e.isStatic && !e._dirtyId)
return !1;
e._dirtyId = 0;
const t = this.syncUniformGroup(e);
return e.buffer.update(), t;
}
destroy() {
this._syncFunctionHash = null;
}
}
const C = [
// uploading pixi matrix object to mat3
{
type: "mat3x3<f32>",
test: (a) => a.value.a !== void 0,
ubo: `
var matrix = uv[name].toArray(true);
data[offset] = matrix[0];
data[offset + 1] = matrix[1];
data[offset + 2] = matrix[2];
data[offset + 4] = matrix[3];
data[offset + 5] = matrix[4];
data[offset + 6] = matrix[5];
data[offset + 8] = matrix[6];
data[offset + 9] = matrix[7];
data[offset + 10] = matrix[8];
`,
uniform: `
gl.uniformMatrix3fv(ud[name].location, false, uv[name].toArray(true));
`
},
// uploading a pixi rectangle as a vec4
{
type: "vec4<f32>",
test: (a) => a.type === "vec4<f32>" && a.size === 1 && a.value.width !== void 0,
ubo: `
v = uv[name];
data[offset] = v.x;
data[offset + 1] = v.y;
data[offset + 2] = v.width;
data[offset + 3] = v.height;
`,
uniform: `
cv = ud[name].value;
v = uv[name];
if (cv[0] !== v.x || cv[1] !== v.y || cv[2] !== v.width || cv[3] !== v.height) {
cv[0] = v.x;
cv[1] = v.y;
cv[2] = v.width;
cv[3] = v.height;
gl.uniform4f(ud[name].location, v.x, v.y, v.width, v.height);
}
`
},
// uploading a pixi point as a vec2
{
type: "vec2<f32>",
test: (a) => a.type === "vec2<f32>" && a.size === 1 && a.value.x !== void 0,
ubo: `
v = uv[name];
data[offset] = v.x;
data[offset + 1] = v.y;
`,
uniform: `
cv = ud[name].value;
v = uv[name];
if (cv[0] !== v.x || cv[1] !== v.y) {
cv[0] = v.x;
cv[1] = v.y;
gl.uniform2f(ud[name].location, v.x, v.y);
}
`
},
// uploading a pixi color as a vec4
{
type: "vec4<f32>",
test: (a) => a.type === "vec4<f32>" && a.size === 1 && a.value.red !== void 0,
ubo: `
v = uv[name];
data[offset] = v.red;
data[offset + 1] = v.green;
data[offset + 2] = v.blue;
data[offset + 3] = v.alpha;
`,
uniform: `
cv = ud[name].value;
v = uv[name];
if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue || cv[3] !== v.alpha) {
cv[0] = v.red;
cv[1] = v.green;
cv[2] = v.blue;
cv[3] = v.alpha;
gl.uniform4f(ud[name].location, v.red, v.green, v.blue, v.alpha);
}
`
},
// uploading a pixi color as a vec3
{
type: "vec3<f32>",
test: (a) => a.type === "vec3<f32>" && a.size === 1 && a.value.red !== void 0,
ubo: `
v = uv[name];
data[offset] = v.red;
data[offset + 1] = v.green;
data[offset + 2] = v.blue;
`,
uniform: `
cv = ud[name].value;
v = uv[name];
if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue) {
cv[0] = v.red;
cv[1] = v.green;
cv[2] = v.blue;
gl.uniform3f(ud[name].location, v.red, v.green, v.blue);
}
`
}
];
function Dt(a, e, t, r) {
const s = [`
var v = null;
var v2 = null;
var t = 0;
var index = 0;
var name = null;
var arrayOffset = null;
`];
let n = 0;
for (let o = 0; o < a.length; o++) {
const l = a[o], d = l.data.name;
let c = !1, h = 0;
for (let p = 0; p < C.length; p++)
if (C[p].test(l.data)) {
h = l.offset / 4, s.push(
`name = "${d}";`,
`offset += ${h - n};`,
C[p][e] || C[p].ubo
), c = !0;
break;
}
if (!c)
if (l.data.size > 1)
h = l.offset / 4, s.push(t(l, h - n));
else {
const p = r[l.data.type];
h = l.offset / 4, s.push(
/* wgsl */
`
v = uv.${d};
offset += ${h - n};
${p};
`
);
}
n = h;
}
const i = s.join(`
`);
return new Function(
"uv",
"data",
"dataInt32",
"offset",
i
);
}
function g(a, e) {
return `
for (let i = 0; i < ${a * e}; i++) {
data[offset + (((i / ${a})|0) * 4) + (i % ${a})] = v[i];
}
`;
}
const ot = {
f32: `
data[offset] = v;`,
i32: `
dataInt32[offset] = v;`,
"vec2<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];`,
"vec3<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];
data[offset + 2] = v[2];`,
"vec4<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];
data[offset + 2] = v[2];
data[offset + 3] = v[3];`,
"vec2<i32>": `
dataInt32[offset] = v[0];
dataInt32[offset + 1] = v[1];`,
"vec3<i32>": `
dataInt32[offset] = v[0];
dataInt32[offset + 1] = v[1];
dataInt32[offset + 2] = v[2];`,
"vec4<i32>": `
dataInt32[offset] = v[0];
dataInt32[offset + 1] = v[1];
dataInt32[offset + 2] = v[2];
dataInt32[offset + 3] = v[3];`,
"mat2x2<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];
data[offset + 4] = v[2];
data[offset + 5] = v[3];`,
"mat3x3<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];
data[offset + 2] = v[2];
data[offset + 4] = v[3];
data[offset + 5] = v[4];
data[offset + 6] = v[5];
data[offset + 8] = v[6];
data[offset + 9] = v[7];
data[offset + 10] = v[8];`,
"mat4x4<f32>": `
for (let i = 0; i < 16; i++) {
data[offset + i] = v[i];
}`,
"mat3x2<f32>": g(3, 2),
"mat4x2<f32>": g(4, 2),
"mat2x3<f32>": g(2, 3),
"mat4x3<f32>": g(4, 3),
"mat2x4<f32>": g(2, 4),
"mat3x4<f32>": g(3, 4)
}, Et = {
...ot,
"mat2x2<f32>": `
data[offset] = v[0];
data[offset + 1] = v[1];
data[offset + 2] = v[2];
data[offset + 3] = v[3];
`
};
function lt(a, e, t, r, s, n) {
const i = n ? 1 : -1;
return a.identity(), a.a = 1 / r * 2, a.d = i * (1 / s * 2), a.tx = -1 - e * a.a, a.ty = -i - t * a.d, a;
}
const _ = /* @__PURE__ */ new Map();
function Te(a, e) {
if (!_.has(a)) {
const t = new m({
source: new U({
resource: a,
...e
})
}), r = () => {
_.get(a) === t && _.delete(a);
};
t.once("destroy", r), t.source.once("destroy", r), _.set(a, t);
}
return _.get(a);
}
function ut(a) {
const e = a.colorTexture.source.resource;
return globalThis.HTMLCanvasElement && e instanceof HTMLCanvasElement && document.body.contains(e);
}
const ye = class ke {
/**
* @param [descriptor] - Options for creating a render target.
*/
constructor(e = {}) {
if (this.uid = M("renderTarget"), this.colorTextures = [], this.dirtyId = 0, this.isRoot = !1, this._size = new Float32Array(2), this._managedColorTextures = !1, e = { ...ke.defaultOptions, ...e }, this.stencil = e.stencil, this.depth = e.depth, this.isRoot = e.isRoot, typeof e.colorTextures == "number") {
this._managedColorTextures = !0;
for (let t = 0; t < e.colorTextures; t++)
this.colorTextures.push(
new T({
width: e.width,
height: e.height,
resolution: e.resolution,
antialias: e.antialias
})
);
} else {
this.colorTextures = [...e.colorTextures.map((r) => r.source)];
const t = this.colorTexture.source;
this.resize(t.width, t.height, t._resolution);
}
this.colorTexture.source.on("resize", this.onSourceResize, this), (e.depthStencilTexture || this.stencil) && (e.depthStencilTexture instanceof m || e.depthStencilTexture instanceof T ? this.depthStencilTexture = e.depthStencilTexture.source : this.ensureDepthStencilTexture());
}
get size() {
const e = this._size;
return e[0] = this.pixelWidth, e[1] = this.pixelHeight, e;
}
get width() {
return this.colorTexture.source.width;
}
get height() {
return this.colorTexture.source.height;
}
get pixelWidth() {
return this.colorTexture.source.pixelWidth;
}
get pixelHeight() {
return this.colorTexture.source.pixelHeight;
}
get resolution() {
return this.colorTexture.source._resolution;
}
get colorTexture() {
return this.colorTextures[0];
}
onSourceResize(e) {
this.resize(e.width, e.height, e._resolution, !0);
}
/**
* This will ensure a depthStencil texture is created for this render target.
* Most likely called by the mask system to make sure we have stencil buffer added.
* @internal
*/
ensureDepthStencilTexture() {
this.depthStencilTexture || (this.depthStencilTexture = new T({
width: this.width,
height: this.height,
resolution: this.resolution,
format: "depth24plus-stencil8",
autoGenerateMipmaps: !1,
antialias: !1,
mipLevelCount: 1
// sampleCount: handled by the render target system..
}));
}
resize(e, t, r = this.resolution, s = !1) {
this.dirtyId++, this.colorTextures.forEach((n, i) => {
s && i === 0 || n.source.resize(e, t, r);
}), this.depthStencilTexture && this.depthStencilTexture.source.resize(e, t, r);
}
destroy() {
this.colorTexture.source.off("resize", this.onSourceResize, this), this._managedColorTextures && this.colorTextures.forEach((e) => {
e.destroy();
}), this.depthStencilTexture && (this.depthStencilTexture.destroy(), delete this.depthStencilTexture);
}
};
ye.defaultOptions = {
/** the width of the RenderTarget */
width: 0,
/** the height of the RenderTarget */
height: 0,
/** the resolution of the RenderTarget */
resolution: 1,
/** an array of textures, or a number indicating how many color textures there should be */
colorTextures: 1,
/** should this render target have a stencil buffer? */
stencil: !1,
/** should this render target have a depth buffer? */
depth: !1,
/** should this render target be antialiased? */
antialias: !1,
// save on perf by default!
/** is this a root element, true if this is gl context owners render target */
isRoot: !1
};
let G = ye;
class Ot {
constructor(e) {
this.rootViewPort = new w(), this.viewport = new w(), this.onRenderTargetChange = new Ne("onRenderTargetChange"), this.projectionMatrix = new v(), this.defaultClearColor = [0, 0, 0, 0], this._renderSurfaceToRenderTargetHash = /* @__PURE__ */ new Map(), this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null), this._renderTargetStack = [], this._renderer = e, e.renderableGC.addManagedHash(this, "_gpuRenderTargetHash");
}
/** called when dev wants to finish a render pass */
finishRenderPass() {
this.adaptor.finishRenderPass(this.renderTarget);
}
/**
* called when the renderer starts to render a scene.
* @param options
* @param options.target - the render target to render to
* @param options.clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param options.clearColor - the color to clear to
* @param options.frame - the frame to render to
*/
renderStart({
target: e,
clear: t,
clearColor: r,
frame: s
}) {
this._renderTargetStack.length = 0, this.push(
e,
t,
r,
s
), this.rootViewPort.copyFrom(this.viewport), this.rootRenderTarget = this.renderTarget, this.renderingToScreen = ut(this.rootRenderTarget), this.adaptor.prerender?.(this.rootRenderTarget);
}
postrender() {
this.adaptor.postrender?.(this.rootRenderTarget);
}
/**
* Binding a render surface! This is the main function of the render target system.
* It will take the RenderSurface (which can be a texture, canvas, or render target) and bind it to the renderer.
* Once bound all draw calls will be rendered to the render surface.
*
* If a frame is not provide and the render surface is a texture, the frame of the texture will be used.
* @param renderSurface - the render surface to bind
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to render to
* @returns the render target that was bound
*/
bind(e, t = !0, r, s) {
const n = this.getRenderTarget(e), i = this.renderTarget !== n;
this.renderTarget = n, this.renderSurface = e;
const o = this.getGpuRenderTarget(n);
(n.pixelWidth !== o.width || n.pixelHeight !== o.height) && (this.adaptor.resizeGpuRenderTarget(n), o.width = n.pixelWidth, o.height = n.pixelHeight);
const l = n.colorTexture, d = this.viewport, c = l.pixelWidth, h = l.pixelHeight;
if (!s && e instanceof m && (s = e.frame), s) {
const p = l._resolution;
d.x = s.x * p + 0.5 | 0, d.y = s.y * p + 0.5 | 0, d.width = s.width * p + 0.5 | 0, d.height = s.height * p + 0.5 | 0;
} else
d.x = 0, d.y = 0, d.width = c, d.height = h;
return lt(
this.projectionMatrix,
0,
0,
d.width / l.resolution,
d.height / l.resolution,
!n.isRoot
), this.adaptor.startRenderPass(n, t, r, d), i && this.onRenderTargetChange.emit(n), n;
}
clear(e, t = B.ALL, r) {
t && (e && (e = this.getRenderTarget(e)), this.adaptor.clear(
e || this.renderTarget,
t,
r,
this.viewport
));
}
contextChange() {
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
/**
* Push a render surface to the renderer. This will bind the render surface to the renderer,
* @param renderSurface - the render surface to push
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to use when rendering to the render surface
*/
push(e, t = B.ALL, r, s) {
const n = this.bind(e, t, r, s);
return this._renderTargetStack.push({
renderTarget: n,
frame: s
}), n;
}
/** Pops the current render target from the renderer and restores the previous render target. */
pop() {
this._renderTargetStack.pop();
const e = this._renderTargetStack[this._renderTargetStack.length - 1];
this.bind(e.renderTarget, !1, null, e.frame);
}
/**
* Gets the render target from the provide render surface. Eg if its a texture,
* it will return the render target for the texture.
* If its a render target, it will return the same render target.
* @param renderSurface - the render surface to get the render target for
* @returns the render target for the render surface
*/
getRenderTarget(e) {
return e.isTexture && (e = e.source), this._renderSurfaceToRenderTargetHash.get(e) ?? this._initRenderTarget(e);
}
/**
* Copies a render surface to another texture.
*
* NOTE:
* for sourceRenderSurfaceTexture, The render target must be something that is written too by the renderer
*
* The following is not valid:
* @example
* const canvas = document.createElement('canvas')
* canvas.width = 200;
* canvas.height = 200;
*
* const ctx = canvas2.getContext('2d')!
* ctx.fillStyle = 'red'
* ctx.fillRect(0, 0, 200, 200);
*
* const texture = RenderTexture.create({
* width: 200,
* height: 200,
* })
* const renderTarget = renderer.renderTarget.getRenderTarget(canvas2);
*
* renderer.renderTarget.copyToTexture(renderTarget,texture, {x:0,y:0},{width:200,height:200},{x:0,y:0});
*
* The best way to copy a canvas is to create a texture from it. Then render with that.
*
* Parsing in a RenderTarget canvas context (with a 2d context)
* @param sourceRenderSurfaceTexture - the render surface to copy from
* @param destinationTexture - the texture to copy to
* @param originSrc - the origin of the copy
* @param originSrc.x - the x origin of the copy
* @param originSrc.y - the y origin of the copy
* @param size - the size of the copy
* @param size.width - the width of the copy
* @param size.height - the height of the copy
* @param originDest - the destination origin (top left to paste from!)
* @param originDest.x - the x origin of the paste
* @param originDest.y - the y origin of the paste
*/
copyToTexture(e, t, r, s, n) {
r.x < 0 && (s.width += r.x, n.x -= r.x, r.x = 0), r.y < 0 && (s.height += r.y, n.y -= r.y, r.y = 0);
const { pixelWidth: i, pixelHeight: o } = e;
return s.width = Math.min(s.width, i - r.x), s.height = Math.min(s.height, o - r.y), this.adaptor.copyToTexture(
e,
t,
r,
s,
n
);
}
/**
* ensures that we have a depth stencil buffer available to render to
* This is used by the mask system to make sure we have a stencil buffer.
*/
ensureDepthStencil() {
this.renderTarget.stencil || (this.renderTarget.stencil = !0, this.adaptor.startRenderPass(this.renderTarget, !1, null, this.viewport));
}
/** nukes the render target system */
destroy() {
this._renderer = null, this._renderSurfaceToRenderTargetHash.forEach((e, t) => {
e !== t && e.destroy();
}), this._renderSurfaceToRenderTargetHash.clear(), this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
_initRenderTarget(e) {
let t = null;
return U.test(e) && (e = Te(e).source), e instanceof G ? t = e : e instanceof T && (t = new G({
colorTextures: [e]
}), e.source instanceof U && (t.isRoot = !0), e.once("destroy", () => {
t.destroy(), this._renderSurfaceToRenderTargetHash.delete(e);
const r = this._gpuRenderTargetHash[t.uid];
r && (this._gpuRenderTargetHash[t.uid] = null, this.adaptor.destroyGpuRenderTarget(r));
})), this._renderSurfaceToRenderTargetHash.set(e, t), t;
}
getGpuRenderTarget(e) {
return this._gpuRenderTargetHash[e.uid] || (this._gpuRenderTargetHash[e.uid] = this.adaptor.initGpuRenderTarget(e));
}
resetState() {
this.renderTarget = null, this.renderSurface = null;
}
}
class Ft extends je {
/**
* Create a new Buffer Resource.
* @param options - The options for the buffer resource
* @param options.buffer - The underlying buffer that this resource is using
* @param options.offset - The offset of the buffer this resource is using.
* If not provided, then it will use the offset of the buffer.
* @param options.size - The size of the buffer this resource is using.
* If not provided, then it will use the size of the buffer.
*/
constructor({ buffer: e, offset: t, size: r }) {
super(), this.uid = M("buffer"), this._resourceType = "bufferResource", this._touched = 0, this._resourceId = M("resource"), this._bufferResource = !0, this.destroyed = !1, this.buffer = e, this.offset = t | 0, this.size = r, this.buffer.on("change", this.onBufferChange, this);
}
onBufferChange() {
this._resourceId = M("resource"), this.emit("change", this);
}
/**
* Destroys this resource. Make sure the underlying buffer is not used anywhere else
* if you want to destroy it as well, or code will explode
* @param destroyBuffer - Should the underlying buffer be destroyed as well?
*/
destroy(e = !1) {
this.destroyed = !0, e && this.buffer.destroy(), this.emit("change", this), this.buffer = null;
}
}
class Ce {
constructor(e) {
this._renderer = e;
}
updateRenderable() {
}
destroyRenderable() {
}
validateRenderable() {
return !1;
}
addRenderable(e, t) {
this._renderer.renderPipes.batch.break(t), t.add(e);
}
execute(e) {
e.isRenderable && e.render(this._renderer);
}
destroy() {
this._renderer = null;
}
}
Ce.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "customRender"
};
function D(a, e) {
const t = a.instructionSet, r = t.instructions;
for (let s = 0; s < t.instructionSize; s++) {
const n = r[s];
e[n.renderPipeId].execute(n);
}
}
const dt = new v();
class Me {
constructor(e) {
this._renderer = e;
}
addRenderGroup(e, t) {
e.isCachedAsTexture ? this._addRenderableCacheAsTexture(e, t) : this._addRenderableDirect(e, t);
}
execute(e) {
e.isRenderable && (e.isCachedAsTexture ? this._executeCacheAsTexture(e) : this._executeDirect(e));
}
destroy() {
this._renderer = null;
}
_addRenderableDirect(e, t) {
this._renderer.renderPipes.batch.break(t), e._batchableRenderGroup && (S.return(e._batchableRenderGroup), e._batchableRenderGroup = null), t.add(e);
}
_addRenderableCacheAsTexture(e, t) {
const r = e._batchableRenderGroup ?? (e._batchableRenderGroup = S.get(pe));
r.renderable = e.root, r.transform = e.root.relativeGroupTransform, r.texture = e.texture, r.bounds = e._textureBounds, t.add(e), this._renderer.renderPipes.batch.addToBatch(r, t);
}
_executeCacheAsTexture(e) {
if (e.textureNeedsUpdate) {
e.textureNeedsUpdate = !1;
const t = dt.identity().translate(
-e._textureBounds.x,
-e._textureBounds.y
);
this._renderer.renderTarget.push(e.texture, !0, null, e.texture.frame), this._renderer.globalUniforms.push({
worldTransformMatrix: t,
worldColor: 4294967295
}), D(e, this._renderer.renderPipes), this._renderer.renderTarget.finishRenderPass(), this._renderer.renderTarget.pop(), this._renderer.globalUniforms.pop();
}
e._batchableRenderGroup._batcher.updateElement(e._batchableRenderGroup), e._batchableRenderGroup._batcher.geometry.buffers[0].update();
}
_executeDirect(e) {
this._renderer.globalUniforms.push({
worldTransformMatrix: e.inverseParentTextureTransform,
worldColor: e.worldColorAlpha
}), D(e, this._renderer.renderPipes), this._renderer.globalUniforms.pop();
}
}
Me.extension = {
type: [
u.WebGLPipes,
u.WebGPUPipes,
u.CanvasPipes
],
name: "renderGroup"
};
function E(a, e) {
e || (e = 0);
for (let t = e; t < a.length && a[t]; t++)
a[t] = null;
}
const ct = new P(), te = de | ce | he;
function Se(a, e = !1) {
ht(a);
const t = a.childrenToUpdate, r = a.updateTick++;
for (const s in t) {
const n = Number(s), i = t[s], o = i.list, l = i.index;
for (let d = 0; d < l; d++) {
const c = o[d];
c.parentRenderGroup === a && c.relativeRenderGroupDepth === n && we(c, r, 0);
}
E(o, l), i.index = 0;
}
if (e)
for (let s = 0; s < a.renderGroupChildren.length; s++)
Se(a.renderGroupChildren[s], e);
}
function ht(a) {
const e = a.root;
let t;
if (a.renderGroupParent) {
const r = a.renderGroupParent;
a.worldTransform.appendFrom(
e.relativeGroupTransform,
r.worldTransform
), a.worldColor = ue(
e.groupColor,
r.worldColor
), t = e.groupAlpha * r.worldAlpha;
} else
a.worldTransform.copyFrom(e.localTransform), a.worldColor = e.localColor, t = e.localAlpha;
t = t < 0 ? 0 : t > 1 ? 1 : t, a.worldAlpha = t, a.worldColorAlpha = a.worldColor + ((t * 255 | 0) << 24);
}
function we(a, e, t) {
if (e === a.updateTick)
return;
a.updateTick = e, a.didChange = !1;
const r = a.localTransform;
a.updateLocalTransform();
const s = a.parent;
if (s && !s.renderGroup ? (t |= a._updateFlags, a.relativeGroupTransform.appendFrom(
r,
s.relativeGroupTransform
), t & te && re(a, s, t)) : (t = a._updateFlags, a.relativeGroupTransform.copyFrom(r), t & te && re(a, ct, t)), !a.renderGroup) {
const n = a.children, i = n.length;
for (let d = 0; d < i; d++)
we(n[d], e, t);
const o = a.parentRenderGroup, l = a;
l.renderPipeId && !o.structureDidChange && o.updateRenderable(l);
}
}
function re(a, e, t) {
if (t & ce) {
a.groupColor = ue(
a.localColor,
e.groupColor
);
let r = a.localAlpha * e.groupAlpha;
r = r < 0 ? 0 : r > 1 ? 1 : r, a.groupAlpha = r, a.groupColorAlpha = a.groupColor + ((r * 255 | 0) << 24);
}
t & he && (a.groupBlendMode = a.localBlendMode === "inherit" ? e.groupBlendMode : a.localBlendMode), t & de && (a.globalDisplayStatus = a.localDisplayStatus & e.globalDisplayStatus), a._updateFlags = 0;
}
function ft(a, e) {
const { list: t, index: r } = a.childrenRenderablesToUpdate;
let s = !1;
for (let n = 0; n < r; n++) {
const i = t[n];
if (s = e[i.renderPipeId].validateRenderable(i), s)
break;
}
return a.structureDidChange = s, s;
}
const pt = new v();
class Pe {
constructor(e) {
this._renderer = e;
}
render({ container: e, transform: t }) {
const r = e.parent, s = e.renderGroup.renderGroupParent;
e.parent = null, e.renderGroup.renderGroupParent = null;
const n = this._renderer;
let i = pt;
t && (i = i.copyFrom(e.renderGroup.localTransform), e.renderGroup.localTransform.copyFrom(t));
const o = n.renderPipes;
this._updateCachedRenderGroups(e.renderGroup, null), this._updateRenderGroups(e.renderGroup), n.globalUniforms.start({
worldTransformMatrix: t ? e.renderGroup.localTransform : e.renderGroup.worldTransform,
worldColor: e.renderGroup.worldColorAlpha
}), D(e.renderGroup, o), o.uniformBatch && o.uniformBatch.renderEnd(), t && e.renderGroup.localTransform.copyFrom(i), e.parent = r, e.renderGroup.renderGroupParent = s;
}
destroy() {
this._renderer = null;
}
_updateCachedRenderGroups(e, t) {
if (e.isCachedAsTexture) {
if (!e.updateCacheTexture)
return;
t = e;
}
e._parentCacheAsTextureRenderGroup = t;
for (let r = e.renderGroupChildren.length - 1; r >= 0; r--)
this._updateCachedRenderGroups(e.renderGroupChildren[r], t);
if (e.invalidateMatrices(), e.isCachedAsTexture) {
if (e.textureNeedsUpdate) {
const r = e.root.getLocalBounds();
r.ceil();
const s = e.texture;
e.texture && b.returnTexture(e.texture, !0);
const n = this._renderer, i = e.textureOptions.resolution || n.view.resolution, o = e.textureOptions.antialias ?? n.view.antialias, l = e.textureOptions.scaleMode ?? "linear", d = b.getOptimalTexture(
r.width,
r.height,
i,
o
);
d._source.style = new $e({ scaleMode: l }), e.texture = d, e._textureBounds || (e._textureBounds = new F()), e._textureBounds.copyFrom(r), s !== e.texture && e.renderGroupParent && (e.renderGroupParent.structureDidChange = !0);
}
} else e.texture && (b.returnTexture(e.texture, !0), e.texture = null);
}
_updateRenderGroups(e) {
const t = this._renderer, r = t.renderPipes;
if (e.runOnRender(t), e.instructionSet.renderPipes = r, e.structureDidChange ? E(e.childrenRenderablesToUpdate.list, 0) : ft(e, r), Se(e), e.structureDidChange ? (e.structureDidChange = !1, this._buildInstructions(e, t)) : this._updateRenderables(e), e.childrenRenderablesToUpdate.index = 0, t.renderPipes.batch.upload(e.instructionSet), !(e.isCachedAsTexture && !e.textureNeedsUpdate))
for (let s = 0; s < e.renderGroupChildren.length; s++)
this._updateRenderGroups(e.renderGroupChildren[s]);
}
_updateRenderables(e) {
const { list: t, index: r } = e.childrenRenderablesToUpdate;
for (let s = 0; s < r; s++) {
const n = t[s];
n.didViewUpdate && e.updateRenderable(n);
}
E(t, r);
}
_buildInstructions(e, t) {
const r = e.root, s = e.instructionSet;
s.reset();
const n = t.renderPipes ? t : t.batch.renderer, i = n.renderPipes;
i.batch.buildStart(s), i.blendMode.buildStart(), i.colorMask.buildStart(), r.sortableChildren && r.sortChildren(), r.collectRenderablesWithEffects(s, n, null), i.batch.buildEnd(s), i.blendMode.buildEnd(s);
}
}
Pe.extension = {
type: [
u.WebGLSystem,
u.WebGPUSystem,
u.CanvasSystem
],
name: "renderGroup"
};
class Re {
constructor(e) {
this._renderer = e;
}
addRenderable(e, t) {
const r = this._getGpuSprite(e);
e.didViewUpdate && this._updateBatchableSprite(e, r), th