@neta-art/cohub-cli 8.3.1 → 8.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +1 -0
  2. package/dist/avatar.js +3 -1
  3. package/dist/board-export.d.ts +4 -8
  4. package/dist/board-export.js +18 -30
  5. package/dist/board-fonts.d.ts +7 -0
  6. package/dist/board-fonts.js +10 -0
  7. package/dist/board-kernel/browserAll.js +2760 -0
  8. package/dist/board-kernel/getPo2TextureFromSource.js +13138 -0
  9. package/dist/board-kernel/init.js +867 -0
  10. package/dist/board-kernel/webworkerAll.js +3 -0
  11. package/dist/board-kernel.d.ts +3 -0
  12. package/dist/board-kernel.js +29154 -0
  13. package/dist/commands/boards.js +11 -1
  14. package/dist/commands/desktop.js +5 -3
  15. package/dist/commands/generations.js +104 -30
  16. package/dist/commands/spaces.js +38 -0
  17. package/dist/fonts/geist-latin-400-normal.woff2 +0 -0
  18. package/dist/fonts/geist-latin-500-normal.woff2 +0 -0
  19. package/dist/fonts/geist-latin-600-normal.woff2 +0 -0
  20. package/dist/fonts/geist-latin-700-normal.woff2 +0 -0
  21. package/dist/fonts/geist-mono-latin-500-normal.woff2 +0 -0
  22. package/dist/fonts/geist-mono-latin-600-normal.woff2 +0 -0
  23. package/dist/fonts/geist-mono-latin-700-normal.woff2 +0 -0
  24. package/dist/runtime/connection.js +13 -7
  25. package/dist/runtime/harness.d.ts +2 -0
  26. package/dist/runtime/harness.js +6 -2
  27. package/dist/runtime/json-rpc.d.ts +4 -0
  28. package/dist/runtime/json-rpc.js +7 -3
  29. package/dist/runtime/native/execution.js +5 -2
  30. package/dist/runtime/native/transcript.js +20 -9
  31. package/dist/runtime/native/translate.js +13 -10
  32. package/dist/runtime/presentation.js +1 -0
  33. package/dist/runtime/process-group.js +2 -2
  34. package/dist/self-update.d.ts +1 -0
  35. package/dist/self-update.js +52 -16
  36. package/package.json +8 -4
@@ -0,0 +1,867 @@
1
+ import { B as Bounds, D as TexturePool, H as Texture, R as warn, a as Geometry, at as extensions, c as Filter, d as RendererType, et as Matrix, f as BindGroup, h as GlProgram, it as ExtensionType, m as GpuProgram, n as CanvasPool, p as UniformGroup, r as canvasUtils, t as getPo2TextureFromSource } from "./getPo2TextureFromSource.js";
2
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/scene/container/bounds/getRenderableBounds.mjs
3
+ const tempProjectionMatrix = new Matrix();
4
+ function getGlobalRenderableBounds(renderables, bounds) {
5
+ bounds.clear();
6
+ const actualMatrix = bounds.matrix;
7
+ for (let i = 0; i < renderables.length; i++) {
8
+ const renderable = renderables[i];
9
+ if (renderable.globalDisplayStatus < 7) continue;
10
+ const renderGroup = renderable.renderGroup ?? renderable.parentRenderGroup;
11
+ if (renderGroup?.isCachedAsTexture) bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup.textureOffsetInverseTransform).append(renderable.worldTransform);
12
+ else if (renderGroup?._parentCacheAsTextureRenderGroup) bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup._parentCacheAsTextureRenderGroup.inverseWorldTransform).append(renderable.groupTransform);
13
+ else bounds.matrix = renderable.worldTransform;
14
+ bounds.addBounds(renderable.bounds);
15
+ }
16
+ bounds.matrix = actualMatrix;
17
+ return bounds;
18
+ }
19
+ //#endregion
20
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/CanvasFilterSystem.mjs
21
+ function isCanvasFilterCapable(filter) {
22
+ return typeof filter.getCanvasFilterString === "function";
23
+ }
24
+ var CanvasFilterFrame = class {
25
+ constructor() {
26
+ this.skip = false;
27
+ this.useClip = false;
28
+ this.filters = null;
29
+ this.container = null;
30
+ this.bounds = new Bounds();
31
+ this.cssFilterString = "";
32
+ }
33
+ };
34
+ var CanvasFilterSystem = class {
35
+ /**
36
+ * @param renderer - The Canvas renderer
37
+ * @param renderer.canvasContext
38
+ * @param renderer.canvasContext.activeContext
39
+ * @param renderer.canvasContext.activeResolution
40
+ */
41
+ constructor(renderer) {
42
+ this._filterStack = [];
43
+ this._filterStackIndex = 0;
44
+ this._savedStates = [];
45
+ this._alphaMultiplier = 1;
46
+ this._warnedFilterTypes = /* @__PURE__ */ new Set();
47
+ this.renderer = renderer;
48
+ }
49
+ /**
50
+ * Push a filter instruction onto the stack.
51
+ * Called when entering a filtered container.
52
+ * @param instruction - The filter instruction from FilterPipe
53
+ */
54
+ push(instruction) {
55
+ const filterFrame = this._pushFilterFrame();
56
+ const filters = instruction.filterEffect.filters;
57
+ filterFrame.skip = false;
58
+ filterFrame.useClip = false;
59
+ filterFrame.filters = filters;
60
+ filterFrame.container = instruction.container;
61
+ filterFrame.cssFilterString = "";
62
+ if (filters.every((filter) => !filter.enabled)) {
63
+ filterFrame.skip = true;
64
+ return;
65
+ }
66
+ const cssFilters = [];
67
+ for (const filter of filters) {
68
+ if (!filter.enabled) continue;
69
+ if (!isCanvasFilterCapable(filter)) {
70
+ this._warnUnsupportedFilter(filter);
71
+ continue;
72
+ }
73
+ const cssString = filter.getCanvasFilterString();
74
+ if (cssString === null) {
75
+ this._warnUnsupportedFilter(filter);
76
+ continue;
77
+ }
78
+ if (cssString) cssFilters.push(cssString);
79
+ }
80
+ if (cssFilters.length === 0 && true) {
81
+ filterFrame.skip = true;
82
+ return;
83
+ }
84
+ filterFrame.cssFilterString = cssFilters.join(" ");
85
+ this._calculateFilterArea(instruction, filterFrame.bounds);
86
+ filterFrame.useClip = !!instruction.filterEffect.filterArea;
87
+ const context = this.renderer.canvasContext.activeContext;
88
+ const previousFilter = context.filter || "none";
89
+ this._savedStates.push({
90
+ filter: previousFilter,
91
+ alphaMultiplier: this._alphaMultiplier
92
+ });
93
+ if (filterFrame.useClip && Number.isFinite(filterFrame.bounds.width) && Number.isFinite(filterFrame.bounds.height) && filterFrame.bounds.width > 0 && filterFrame.bounds.height > 0) {
94
+ const resolution = this.renderer.canvasContext.activeResolution || 1;
95
+ context.save();
96
+ context.setTransform(1, 0, 0, 1, 0, 0);
97
+ context.beginPath();
98
+ context.rect(filterFrame.bounds.x * resolution, filterFrame.bounds.y * resolution, filterFrame.bounds.width * resolution, filterFrame.bounds.height * resolution);
99
+ context.clip();
100
+ } else filterFrame.useClip = false;
101
+ if (filterFrame.cssFilterString) context.filter = previousFilter !== "none" ? `${previousFilter} ${filterFrame.cssFilterString}` : filterFrame.cssFilterString;
102
+ }
103
+ /** Pop a filter from the stack. Called when exiting a filtered container. */
104
+ pop() {
105
+ const filterFrame = this._popFilterFrame();
106
+ if (filterFrame.skip) return;
107
+ const savedState = this._savedStates.pop();
108
+ if (!savedState) return;
109
+ const context = this.renderer.canvasContext.activeContext;
110
+ if (filterFrame.useClip) context.restore();
111
+ else context.filter = savedState.filter;
112
+ this._alphaMultiplier = savedState.alphaMultiplier;
113
+ }
114
+ /**
115
+ * Applies supported filters to a texture and returns a new texture.
116
+ * Unsupported filters are skipped with a warn-once message.
117
+ * @param params - The parameters for applying filters.
118
+ * @param params.texture
119
+ * @param params.filters
120
+ * @returns The resulting texture after filters are applied.
121
+ */
122
+ generateFilteredTexture({ texture, filters }) {
123
+ if (!filters?.length || filters.every((filter) => !filter.enabled)) return texture;
124
+ const cssFilters = [];
125
+ for (const filter of filters) {
126
+ if (!filter.enabled) continue;
127
+ if (!isCanvasFilterCapable(filter)) {
128
+ this._warnUnsupportedFilter(filter);
129
+ continue;
130
+ }
131
+ const cssString = filter.getCanvasFilterString();
132
+ if (cssString === null) {
133
+ this._warnUnsupportedFilter(filter);
134
+ continue;
135
+ }
136
+ if (cssString) cssFilters.push(cssString);
137
+ }
138
+ if (cssFilters.length === 0 && true) return texture;
139
+ const source = canvasUtils.getCanvasSource(texture);
140
+ if (!source) return texture;
141
+ const frame = texture.frame;
142
+ const resolution = texture.source._resolution ?? texture.source.resolution ?? 1;
143
+ const width = frame.width;
144
+ const height = frame.height;
145
+ const { canvas, context } = CanvasPool.getOptimalCanvasAndContext(width, height, resolution);
146
+ context.setTransform(1, 0, 0, 1, 0, 0);
147
+ context.clearRect(0, 0, canvas.width, canvas.height);
148
+ if (cssFilters.length) context.filter = cssFilters.join(" ");
149
+ const sx = frame.x * resolution;
150
+ const sy = frame.y * resolution;
151
+ const sw = width * resolution;
152
+ const sh = height * resolution;
153
+ context.drawImage(source, sx, sy, sw, sh, 0, 0, sw, sh);
154
+ context.filter = "none";
155
+ context.globalAlpha = 1;
156
+ return getPo2TextureFromSource(canvas, width, height, resolution);
157
+ }
158
+ /**
159
+ * Calculate the filter area bounds.
160
+ * @param instruction - Filter instruction
161
+ * @param bounds - Bounds object to populate
162
+ */
163
+ _calculateFilterArea(instruction, bounds) {
164
+ if (instruction.renderables) getGlobalRenderableBounds(instruction.renderables, bounds);
165
+ else if (instruction.filterEffect.filterArea) {
166
+ bounds.clear();
167
+ bounds.addRect(instruction.filterEffect.filterArea);
168
+ bounds.applyMatrix(instruction.container.worldTransform);
169
+ } else instruction.container.getFastGlobalBounds(true, bounds);
170
+ if (instruction.container) {
171
+ const filterFrameTransform = (instruction.container.renderGroup || instruction.container.parentRenderGroup)?.cacheToLocalTransform;
172
+ if (filterFrameTransform) bounds.applyMatrix(filterFrameTransform);
173
+ }
174
+ }
175
+ _warnUnsupportedFilter(filter) {
176
+ const filterName = filter?.constructor?.name || "Filter";
177
+ if (this._warnedFilterTypes.has(filterName)) return;
178
+ this._warnedFilterTypes.add(filterName);
179
+ console.warn(`CanvasRenderer: filter "${filterName}" is not supported in Canvas2D and will be skipped.`);
180
+ }
181
+ get alphaMultiplier() {
182
+ return this._alphaMultiplier;
183
+ }
184
+ _pushFilterFrame() {
185
+ let filterFrame = this._filterStack[this._filterStackIndex];
186
+ if (!filterFrame) filterFrame = this._filterStack[this._filterStackIndex] = new CanvasFilterFrame();
187
+ this._filterStackIndex++;
188
+ return filterFrame;
189
+ }
190
+ _popFilterFrame() {
191
+ if (this._filterStackIndex <= 0) return this._filterStack[0];
192
+ this._filterStackIndex--;
193
+ return this._filterStack[this._filterStackIndex];
194
+ }
195
+ /** Destroys the system */
196
+ destroy() {
197
+ this._filterStack = null;
198
+ this._savedStates = null;
199
+ this._warnedFilterTypes = null;
200
+ this._alphaMultiplier = 1;
201
+ }
202
+ };
203
+ /** @ignore */
204
+ CanvasFilterSystem.extension = {
205
+ type: [ExtensionType.CanvasSystem],
206
+ name: "filter"
207
+ };
208
+ //#endregion
209
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/defaults/defaultFilter.vert.mjs
210
+ var vertex = "in vec2 aPosition;\nout vec2 vTextureCoord;\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n \n position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvoid main(void)\n{\n gl_Position = filterVertexPosition();\n vTextureCoord = filterTextureCoord();\n}\n";
211
+ //#endregion
212
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/defaults/passthrough/passthrough.frag.mjs
213
+ var fragment = "in vec2 vTextureCoord;\nout vec4 finalColor;\nuniform sampler2D uTexture;\nvoid main() {\n finalColor = texture(uTexture, vTextureCoord);\n}\n";
214
+ //#endregion
215
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/defaults/passthrough/passthrough.wgsl.mjs
216
+ var source = "struct GlobalFilterUniforms {\n uInputSize: vec4<f32>,\n uInputPixel: vec4<f32>,\n uInputClamp: vec4<f32>,\n uOutputFrame: vec4<f32>,\n uGlobalFrame: vec4<f32>,\n uOutputTexture: vec4<f32>,\n};\n\n@group(0) @binding(0) var <uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler: sampler;\n\nstruct VSOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) uv: vec2<f32>\n};\n\nfn filterVertexPosition(aPosition: vec2<f32>) -> vec4<f32>\n{\n var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord(aPosition: vec2<f32>) -> vec2<f32>\n{\n return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\n@vertex\nfn mainVertex(\n @location(0) aPosition: vec2<f32>,\n) -> VSOutput {\n return VSOutput(\n filterVertexPosition(aPosition),\n filterTextureCoord(aPosition)\n );\n}\n\n@fragment\nfn mainFragment(\n @location(0) uv: vec2<f32>,\n) -> @location(0) vec4<f32> {\n return textureSample(uTexture, uSampler, uv);\n}\n";
217
+ //#endregion
218
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/defaults/passthrough/PassthroughFilter.mjs
219
+ var PassthroughFilter = class extends Filter {
220
+ constructor() {
221
+ const gpuProgram = GpuProgram.from({
222
+ vertex: {
223
+ source,
224
+ entryPoint: "mainVertex"
225
+ },
226
+ fragment: {
227
+ source,
228
+ entryPoint: "mainFragment"
229
+ },
230
+ name: "passthrough-filter"
231
+ });
232
+ const glProgram = GlProgram.from({
233
+ vertex,
234
+ fragment,
235
+ name: "passthrough-filter"
236
+ });
237
+ super({
238
+ gpuProgram,
239
+ glProgram
240
+ });
241
+ }
242
+ };
243
+ //#endregion
244
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/FilterPipe.mjs
245
+ var FilterPipe = class {
246
+ constructor(renderer) {
247
+ this._renderer = renderer;
248
+ }
249
+ push(filterEffect, container, instructionSet) {
250
+ this._renderer.renderPipes.batch.break(instructionSet);
251
+ instructionSet.add({
252
+ renderPipeId: "filter",
253
+ canBundle: false,
254
+ action: "pushFilter",
255
+ container,
256
+ filterEffect
257
+ });
258
+ }
259
+ pop(_filterEffect, _container, instructionSet) {
260
+ this._renderer.renderPipes.batch.break(instructionSet);
261
+ instructionSet.add({
262
+ renderPipeId: "filter",
263
+ action: "popFilter",
264
+ canBundle: false
265
+ });
266
+ }
267
+ execute(instruction) {
268
+ if (instruction.action === "pushFilter") this._renderer.filter.push(instruction);
269
+ else if (instruction.action === "popFilter") this._renderer.filter.pop();
270
+ }
271
+ destroy() {
272
+ this._renderer = null;
273
+ }
274
+ };
275
+ FilterPipe.extension = {
276
+ type: [
277
+ ExtensionType.WebGLPipes,
278
+ ExtensionType.WebGPUPipes,
279
+ ExtensionType.CanvasPipes
280
+ ],
281
+ name: "filter"
282
+ };
283
+ //#endregion
284
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/FilterSystem.mjs
285
+ const quadGeometry = new Geometry({
286
+ attributes: { aPosition: {
287
+ buffer: new Float32Array([
288
+ 0,
289
+ 0,
290
+ 1,
291
+ 0,
292
+ 1,
293
+ 1,
294
+ 0,
295
+ 1
296
+ ]),
297
+ format: "float32x2",
298
+ stride: 8,
299
+ offset: 0
300
+ } },
301
+ indexBuffer: new Uint32Array([
302
+ 0,
303
+ 1,
304
+ 2,
305
+ 0,
306
+ 2,
307
+ 3
308
+ ])
309
+ });
310
+ var FilterData = class {
311
+ constructor() {
312
+ /**
313
+ * Indicates whether the filter should be skipped.
314
+ * @type {boolean}
315
+ */
316
+ this.skip = false;
317
+ /**
318
+ * The texture to which the filter is applied.
319
+ * @type {Texture}
320
+ */
321
+ this.inputTexture = null;
322
+ /**
323
+ * The back texture used for blending, if required.
324
+ * @type {Texture | null}
325
+ */
326
+ this.backTexture = null;
327
+ /**
328
+ * The list of filters to be applied.
329
+ * @type {Filter[]}
330
+ */
331
+ this.filters = null;
332
+ /**
333
+ * The bounds of the filter area.
334
+ * @type {Bounds}
335
+ */
336
+ this.bounds = new Bounds();
337
+ /**
338
+ * The container to which the filter is applied.
339
+ * @type {Container}
340
+ */
341
+ this.container = null;
342
+ /**
343
+ * Indicates whether blending is required for the filter.
344
+ * @type {boolean}
345
+ */
346
+ this.blendRequired = false;
347
+ /**
348
+ * The render surface where the output of the filter is rendered.
349
+ * @type {RenderSurface}
350
+ */
351
+ this.outputRenderSurface = null;
352
+ /**
353
+ * The global frame of the filter area.
354
+ * @type {{ x: number, y: number, width: number, height: number }}
355
+ */
356
+ this.globalFrame = {
357
+ x: 0,
358
+ y: 0,
359
+ width: 0,
360
+ height: 0
361
+ };
362
+ /** The first enabled filter index in the current filter list. */
363
+ this.firstEnabledIndex = -1;
364
+ /** The last enabled filter index in the current filter list. */
365
+ this.lastEnabledIndex = -1;
366
+ }
367
+ };
368
+ var FilterSystem = class {
369
+ constructor(renderer) {
370
+ this._filterStackIndex = 0;
371
+ this._filterStack = [];
372
+ this._filterGlobalUniforms = new UniformGroup({
373
+ uInputSize: {
374
+ value: /* @__PURE__ */ new Float32Array(4),
375
+ type: "vec4<f32>"
376
+ },
377
+ uInputPixel: {
378
+ value: /* @__PURE__ */ new Float32Array(4),
379
+ type: "vec4<f32>"
380
+ },
381
+ uInputClamp: {
382
+ value: /* @__PURE__ */ new Float32Array(4),
383
+ type: "vec4<f32>"
384
+ },
385
+ uOutputFrame: {
386
+ value: /* @__PURE__ */ new Float32Array(4),
387
+ type: "vec4<f32>"
388
+ },
389
+ uGlobalFrame: {
390
+ value: /* @__PURE__ */ new Float32Array(4),
391
+ type: "vec4<f32>"
392
+ },
393
+ uOutputTexture: {
394
+ value: /* @__PURE__ */ new Float32Array(4),
395
+ type: "vec4<f32>"
396
+ }
397
+ });
398
+ this._globalFilterBindGroup = new BindGroup({});
399
+ this.renderer = renderer;
400
+ }
401
+ /**
402
+ * The back texture of the currently active filter. Requires the filter to have `blendRequired` set to true.
403
+ * @readonly
404
+ */
405
+ get activeBackTexture() {
406
+ return this._activeFilterData?.backTexture;
407
+ }
408
+ /**
409
+ * Pushes a filter instruction onto the filter stack.
410
+ * @param instruction - The instruction containing the filter effect and container.
411
+ * @internal
412
+ */
413
+ push(instruction) {
414
+ const renderer = this.renderer;
415
+ const filters = instruction.filterEffect.filters;
416
+ const filterData = this._pushFilterData();
417
+ filterData.skip = false;
418
+ filterData.filters = filters;
419
+ filterData.container = instruction.container;
420
+ filterData.outputRenderSurface = renderer.renderTarget.renderSurface;
421
+ const colorTextureSource = renderer.renderTarget.renderTarget.colorTexture.source;
422
+ const rootResolution = colorTextureSource.resolution;
423
+ const rootAntialias = colorTextureSource.antialias;
424
+ if (filters.every((filter) => !filter.enabled)) {
425
+ filterData.skip = true;
426
+ return;
427
+ }
428
+ const bounds = filterData.bounds;
429
+ this._calculateFilterArea(instruction, bounds);
430
+ this._calculateFilterBounds(filterData, renderer.renderTarget.rootViewPort, rootAntialias, rootResolution, 1);
431
+ if (filterData.skip) return;
432
+ const previousFilterData = this._getPreviousFilterData();
433
+ const globalResolution = this._findFilterResolution(rootResolution);
434
+ let offsetX = 0;
435
+ let offsetY = 0;
436
+ if (previousFilterData) {
437
+ offsetX = previousFilterData.bounds.minX;
438
+ offsetY = previousFilterData.bounds.minY;
439
+ }
440
+ this._calculateGlobalFrame(filterData, offsetX, offsetY, globalResolution, colorTextureSource.width, colorTextureSource.height);
441
+ this._setupFilterTextures(filterData, bounds, renderer, previousFilterData);
442
+ }
443
+ /**
444
+ * Applies filters to a texture.
445
+ *
446
+ * This method takes a texture and a list of filters, applies the filters to the texture,
447
+ * and returns the resulting texture.
448
+ * @param {object} params - The parameters for applying filters.
449
+ * @param {Texture} params.texture - The texture to apply filters to.
450
+ * @param {Filter[]} params.filters - The filters to apply.
451
+ * @returns {Texture} The resulting texture after all filters have been applied.
452
+ * @example
453
+ *
454
+ * ```ts
455
+ * // Create a texture and a list of filters
456
+ * const texture = new Texture(...);
457
+ * const filters = [new BlurFilter(), new ColorMatrixFilter()];
458
+ *
459
+ * // Apply the filters to the texture
460
+ * const resultTexture = filterSystem.applyToTexture({ texture, filters });
461
+ *
462
+ * // Use the resulting texture
463
+ * sprite.texture = resultTexture;
464
+ * ```
465
+ *
466
+ * Key Points:
467
+ * 1. padding is not currently supported here - so clipping may occur with filters that use padding.
468
+ * 2. If all filters are disabled or skipped, the original texture is returned.
469
+ */
470
+ generateFilteredTexture({ texture, filters }) {
471
+ const filterData = this._pushFilterData();
472
+ this._activeFilterData = filterData;
473
+ filterData.skip = false;
474
+ filterData.filters = filters;
475
+ const colorTextureSource = texture.source;
476
+ const rootResolution = colorTextureSource.resolution;
477
+ const rootAntialias = colorTextureSource.antialias;
478
+ if (filters.every((filter) => !filter.enabled)) {
479
+ filterData.skip = true;
480
+ return texture;
481
+ }
482
+ const bounds = filterData.bounds;
483
+ bounds.addRect(texture.frame);
484
+ this._calculateFilterBounds(filterData, bounds.rectangle, rootAntialias, rootResolution, 0);
485
+ if (filterData.skip) return texture;
486
+ const globalResolution = rootResolution;
487
+ this._calculateGlobalFrame(filterData, 0, 0, globalResolution, colorTextureSource.width, colorTextureSource.height);
488
+ filterData.outputRenderSurface = TexturePool.getOptimalTexture(bounds.width, bounds.height, filterData.resolution, filterData.antialias);
489
+ filterData.backTexture = Texture.EMPTY;
490
+ filterData.inputTexture = texture;
491
+ this.renderer.renderTarget.finishRenderPass();
492
+ this._applyFiltersToTexture(filterData, true);
493
+ const outputTexture = filterData.outputRenderSurface;
494
+ outputTexture.source.alphaMode = "premultiplied-alpha";
495
+ return outputTexture;
496
+ }
497
+ /** @internal */
498
+ pop() {
499
+ const renderer = this.renderer;
500
+ const filterData = this._popFilterData();
501
+ if (filterData.skip) return;
502
+ renderer.globalUniforms.pop();
503
+ renderer.renderTarget.finishRenderPass();
504
+ this._activeFilterData = filterData;
505
+ this._applyFiltersToTexture(filterData, false);
506
+ if (filterData.blendRequired) TexturePool.returnTexture(filterData.backTexture);
507
+ TexturePool.returnTexture(filterData.inputTexture);
508
+ }
509
+ /**
510
+ * Copies the last render surface to a texture.
511
+ * @param lastRenderSurface - The last render surface to copy from.
512
+ * @param bounds - The bounds of the area to copy.
513
+ * @param previousBounds - The previous bounds to use for offsetting the copy.
514
+ */
515
+ getBackTexture(lastRenderSurface, bounds, previousBounds) {
516
+ const backgroundResolution = lastRenderSurface.colorTexture.source._resolution;
517
+ const backTexture = TexturePool.getOptimalTexture(bounds.width, bounds.height, backgroundResolution, false);
518
+ let x = bounds.minX;
519
+ let y = bounds.minY;
520
+ if (previousBounds) {
521
+ x -= previousBounds.minX;
522
+ y -= previousBounds.minY;
523
+ }
524
+ x = Math.floor(x * backgroundResolution);
525
+ y = Math.floor(y * backgroundResolution);
526
+ const width = Math.ceil(bounds.width * backgroundResolution);
527
+ const height = Math.ceil(bounds.height * backgroundResolution);
528
+ this.renderer.renderTarget.copyToTexture(lastRenderSurface, backTexture, {
529
+ x,
530
+ y
531
+ }, {
532
+ width,
533
+ height
534
+ }, {
535
+ x: 0,
536
+ y: 0
537
+ });
538
+ return backTexture;
539
+ }
540
+ /**
541
+ * Applies a filter to a texture.
542
+ * @param filter - The filter to apply.
543
+ * @param input - The input texture.
544
+ * @param output - The output render surface.
545
+ * @param clear - Whether to clear the output surface before applying the filter.
546
+ */
547
+ applyFilter(filter, input, output, clear) {
548
+ const renderer = this.renderer;
549
+ const filterData = this._activeFilterData;
550
+ const isFinalTarget = filterData.outputRenderSurface === output;
551
+ const rootResolution = renderer.renderTarget.rootRenderTarget.colorTexture.source._resolution;
552
+ const resolution = this._findFilterResolution(rootResolution);
553
+ let offsetX = 0;
554
+ let offsetY = 0;
555
+ if (isFinalTarget) {
556
+ const offset = this._findPreviousFilterOffset();
557
+ offsetX = offset.x;
558
+ offsetY = offset.y;
559
+ }
560
+ this._updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear);
561
+ const filterToApply = filter.enabled ? filter : this._getPassthroughFilter();
562
+ this._setupBindGroupsAndRender(filterToApply, input, renderer);
563
+ }
564
+ /**
565
+ * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_.
566
+ *
567
+ * Use `outputMatrix * vTextureCoord` in the shader.
568
+ * @param outputMatrix - The matrix to output to.
569
+ * @param {Sprite} sprite - The sprite to map to.
570
+ * @returns The mapped matrix.
571
+ */
572
+ calculateSpriteMatrix(outputMatrix, sprite) {
573
+ const data = this._activeFilterData;
574
+ const mappedMatrix = outputMatrix.set(data.inputTexture._source.width, 0, 0, data.inputTexture._source.height, data.bounds.minX, data.bounds.minY);
575
+ const worldTransform = sprite.worldTransform.copyTo(Matrix.shared);
576
+ const renderGroup = sprite.renderGroup || sprite.parentRenderGroup;
577
+ if (renderGroup && renderGroup.cacheToLocalTransform) worldTransform.prepend(renderGroup.cacheToLocalTransform);
578
+ worldTransform.invert();
579
+ mappedMatrix.prepend(worldTransform);
580
+ mappedMatrix.scale(1 / sprite.texture.orig.width, 1 / sprite.texture.orig.height);
581
+ mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);
582
+ return mappedMatrix;
583
+ }
584
+ destroy() {
585
+ this._passthroughFilter?.destroy(true);
586
+ this._passthroughFilter = null;
587
+ }
588
+ _getPassthroughFilter() {
589
+ this._passthroughFilter ?? (this._passthroughFilter = new PassthroughFilter());
590
+ return this._passthroughFilter;
591
+ }
592
+ /**
593
+ * Sets up the bind groups and renders the filter.
594
+ * @param filter - The filter to apply
595
+ * @param input - The input texture
596
+ * @param renderer - The renderer instance
597
+ */
598
+ _setupBindGroupsAndRender(filter, input, renderer) {
599
+ if (renderer.renderPipes.uniformBatch) {
600
+ const batchUniforms = renderer.renderPipes.uniformBatch.getUboResource(this._filterGlobalUniforms);
601
+ this._globalFilterBindGroup.setResource(batchUniforms, 0);
602
+ } else this._globalFilterBindGroup.setResource(this._filterGlobalUniforms, 0);
603
+ this._globalFilterBindGroup.setResource(input.source, 1);
604
+ this._globalFilterBindGroup.setResource(input.source.style, 2);
605
+ filter.groups[0] = this._globalFilterBindGroup;
606
+ renderer.encoder.draw({
607
+ geometry: quadGeometry,
608
+ shader: filter,
609
+ state: filter._state,
610
+ topology: "triangle-list"
611
+ });
612
+ if (renderer.type === RendererType.WEBGL) renderer.renderTarget.finishRenderPass();
613
+ }
614
+ /**
615
+ * Sets up the filter textures including input texture and back texture if needed.
616
+ * @param filterData - The filter data to update
617
+ * @param bounds - The bounds for the texture
618
+ * @param renderer - The renderer instance
619
+ * @param previousFilterData - The previous filter data for back texture calculation
620
+ */
621
+ _setupFilterTextures(filterData, bounds, renderer, previousFilterData) {
622
+ filterData.backTexture = Texture.EMPTY;
623
+ filterData.inputTexture = TexturePool.getOptimalTexture(bounds.width, bounds.height, filterData.resolution, filterData.antialias);
624
+ if (filterData.blendRequired) {
625
+ renderer.renderTarget.finishRenderPass();
626
+ const renderTarget = renderer.renderTarget.getRenderTarget(filterData.outputRenderSurface);
627
+ filterData.backTexture = this.getBackTexture(renderTarget, bounds, previousFilterData?.bounds);
628
+ }
629
+ renderer.renderTarget.bind({
630
+ target: filterData.inputTexture,
631
+ clear: true
632
+ });
633
+ renderer.globalUniforms.push({ offset: bounds });
634
+ }
635
+ /**
636
+ * Calculates and sets the global frame for the filter.
637
+ * @param filterData - The filter data to update
638
+ * @param offsetX - The X offset
639
+ * @param offsetY - The Y offset
640
+ * @param globalResolution - The global resolution
641
+ * @param sourceWidth - The source texture width
642
+ * @param sourceHeight - The source texture height
643
+ */
644
+ _calculateGlobalFrame(filterData, offsetX, offsetY, globalResolution, sourceWidth, sourceHeight) {
645
+ const globalFrame = filterData.globalFrame;
646
+ globalFrame.x = offsetX * globalResolution;
647
+ globalFrame.y = offsetY * globalResolution;
648
+ globalFrame.width = sourceWidth * globalResolution;
649
+ globalFrame.height = sourceHeight * globalResolution;
650
+ }
651
+ /**
652
+ * Updates the filter uniforms with the current filter state.
653
+ * @param input - The input texture
654
+ * @param output - The output render surface
655
+ * @param filterData - The current filter data
656
+ * @param offsetX - The X offset for positioning
657
+ * @param offsetY - The Y offset for positioning
658
+ * @param resolution - The current resolution
659
+ * @param isFinalTarget - Whether this is the final render target
660
+ * @param clear - Whether to clear the output surface
661
+ */
662
+ _updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear) {
663
+ const uniforms = this._filterGlobalUniforms.uniforms;
664
+ const outputFrame = uniforms.uOutputFrame;
665
+ const inputSize = uniforms.uInputSize;
666
+ const inputPixel = uniforms.uInputPixel;
667
+ const inputClamp = uniforms.uInputClamp;
668
+ const globalFrame = uniforms.uGlobalFrame;
669
+ const outputTexture = uniforms.uOutputTexture;
670
+ if (isFinalTarget) {
671
+ outputFrame[0] = filterData.bounds.minX - offsetX;
672
+ outputFrame[1] = filterData.bounds.minY - offsetY;
673
+ } else {
674
+ outputFrame[0] = 0;
675
+ outputFrame[1] = 0;
676
+ }
677
+ outputFrame[2] = input.frame.width;
678
+ outputFrame[3] = input.frame.height;
679
+ inputSize[0] = input.source.width;
680
+ inputSize[1] = input.source.height;
681
+ inputSize[2] = 1 / inputSize[0];
682
+ inputSize[3] = 1 / inputSize[1];
683
+ inputPixel[0] = input.source.pixelWidth;
684
+ inputPixel[1] = input.source.pixelHeight;
685
+ inputPixel[2] = 1 / inputPixel[0];
686
+ inputPixel[3] = 1 / inputPixel[1];
687
+ inputClamp[0] = .5 * inputPixel[2];
688
+ inputClamp[1] = .5 * inputPixel[3];
689
+ inputClamp[2] = input.frame.width * inputSize[2] - .5 * inputPixel[2];
690
+ inputClamp[3] = input.frame.height * inputSize[3] - .5 * inputPixel[3];
691
+ const rootTexture = this.renderer.renderTarget.rootRenderTarget.colorTexture;
692
+ globalFrame[0] = offsetX * resolution;
693
+ globalFrame[1] = offsetY * resolution;
694
+ globalFrame[2] = rootTexture.source.width * resolution;
695
+ globalFrame[3] = rootTexture.source.height * resolution;
696
+ if (output instanceof Texture) output.source.resource = null;
697
+ const renderTarget = this.renderer.renderTarget.getRenderTarget(output);
698
+ this.renderer.renderTarget.bind({
699
+ target: output,
700
+ clear: !!clear
701
+ });
702
+ if (output instanceof Texture) {
703
+ outputTexture[0] = output.frame.width;
704
+ outputTexture[1] = output.frame.height;
705
+ } else {
706
+ outputTexture[0] = renderTarget.width;
707
+ outputTexture[1] = renderTarget.height;
708
+ }
709
+ outputTexture[2] = renderTarget.isRoot ? -1 : 1;
710
+ this._filterGlobalUniforms.update();
711
+ }
712
+ /**
713
+ * Finds the correct resolution by looking back through the filter stack.
714
+ * @param rootResolution - The fallback root resolution to use
715
+ * @returns The resolution from the previous filter or root resolution
716
+ */
717
+ _findFilterResolution(rootResolution) {
718
+ let currentIndex = this._filterStackIndex - 1;
719
+ while (currentIndex > 0 && this._filterStack[currentIndex].skip) --currentIndex;
720
+ return currentIndex > 0 && this._filterStack[currentIndex].inputTexture ? this._filterStack[currentIndex].inputTexture.source._resolution : rootResolution;
721
+ }
722
+ /**
723
+ * Finds the offset from the previous non-skipped filter in the stack.
724
+ * @returns The offset coordinates from the previous filter
725
+ */
726
+ _findPreviousFilterOffset() {
727
+ let offsetX = 0;
728
+ let offsetY = 0;
729
+ let lastIndex = this._filterStackIndex;
730
+ while (lastIndex > 0) {
731
+ lastIndex--;
732
+ const prevFilterData = this._filterStack[lastIndex];
733
+ if (!prevFilterData.skip) {
734
+ offsetX = prevFilterData.bounds.minX;
735
+ offsetY = prevFilterData.bounds.minY;
736
+ break;
737
+ }
738
+ }
739
+ return {
740
+ x: offsetX,
741
+ y: offsetY
742
+ };
743
+ }
744
+ /**
745
+ * Calculates the filter area bounds based on the instruction type.
746
+ * @param instruction - The filter instruction
747
+ * @param bounds - The bounds object to populate
748
+ */
749
+ _calculateFilterArea(instruction, bounds) {
750
+ if (instruction.renderables) getGlobalRenderableBounds(instruction.renderables, bounds);
751
+ else if (instruction.filterEffect.filterArea) {
752
+ bounds.clear();
753
+ bounds.addRect(instruction.filterEffect.filterArea);
754
+ bounds.applyMatrix(instruction.container.worldTransform);
755
+ } else instruction.container.getFastGlobalBounds(true, bounds);
756
+ if (instruction.container) {
757
+ const filterFrameTransform = (instruction.container.renderGroup || instruction.container.parentRenderGroup).cacheToLocalTransform;
758
+ if (filterFrameTransform) bounds.applyMatrix(filterFrameTransform);
759
+ }
760
+ }
761
+ _applyFiltersToTexture(filterData, clear) {
762
+ const inputTexture = filterData.inputTexture;
763
+ const bounds = filterData.bounds;
764
+ const filters = filterData.filters;
765
+ const firstEnabled = filterData.firstEnabledIndex;
766
+ const lastEnabled = filterData.lastEnabledIndex;
767
+ this._globalFilterBindGroup.setResource(inputTexture.source.style, 2);
768
+ this._globalFilterBindGroup.setResource(filterData.backTexture.source, 3);
769
+ if (firstEnabled === lastEnabled) filters[firstEnabled].apply(this, inputTexture, filterData.outputRenderSurface, clear);
770
+ else {
771
+ let flip = filterData.inputTexture;
772
+ const tempTexture = TexturePool.getOptimalTexture(bounds.width, bounds.height, flip.source._resolution, false);
773
+ let flop = tempTexture;
774
+ for (let i = firstEnabled; i < lastEnabled; i++) {
775
+ const filter = filters[i];
776
+ if (!filter.enabled) continue;
777
+ filter.apply(this, flip, flop, true);
778
+ const t = flip;
779
+ flip = flop;
780
+ flop = t;
781
+ }
782
+ filters[lastEnabled].apply(this, flip, filterData.outputRenderSurface, clear);
783
+ TexturePool.returnTexture(tempTexture);
784
+ }
785
+ }
786
+ _calculateFilterBounds(filterData, viewPort, rootAntialias, rootResolution, paddingMultiplier) {
787
+ const renderer = this.renderer;
788
+ const bounds = filterData.bounds;
789
+ const filters = filterData.filters;
790
+ let resolution = Infinity;
791
+ let padding = 0;
792
+ let antialias = true;
793
+ let blendRequired = false;
794
+ let enabled = false;
795
+ let clipToViewport = true;
796
+ let firstEnabledIndex = -1;
797
+ let lastEnabledIndex = -1;
798
+ for (let i = 0; i < filters.length; i++) {
799
+ const filter = filters[i];
800
+ if (!filter.enabled) continue;
801
+ if (firstEnabledIndex === -1) firstEnabledIndex = i;
802
+ lastEnabledIndex = i;
803
+ resolution = Math.min(resolution, filter.resolution === "inherit" ? rootResolution : filter.resolution);
804
+ padding += filter.padding;
805
+ if (filter.antialias === "off") antialias = false;
806
+ else if (filter.antialias === "inherit") antialias && (antialias = rootAntialias);
807
+ if (!filter.clipToViewport) clipToViewport = false;
808
+ if (!!!(filter.compatibleRenderers & renderer.type)) {
809
+ enabled = false;
810
+ break;
811
+ }
812
+ if (filter.blendRequired && !(renderer.backBuffer?.useBackBuffer ?? true)) {
813
+ warn("Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options.");
814
+ enabled = false;
815
+ break;
816
+ }
817
+ enabled = true;
818
+ blendRequired || (blendRequired = filter.blendRequired);
819
+ }
820
+ if (!enabled) {
821
+ filterData.skip = true;
822
+ return;
823
+ }
824
+ if (clipToViewport) bounds.fitBounds(0, viewPort.width / rootResolution, 0, viewPort.height / rootResolution);
825
+ bounds.scale(resolution).ceil().scale(1 / resolution).pad((padding | 0) * paddingMultiplier);
826
+ if (!bounds.isPositive) {
827
+ filterData.skip = true;
828
+ return;
829
+ }
830
+ filterData.antialias = antialias;
831
+ filterData.resolution = resolution;
832
+ filterData.blendRequired = blendRequired;
833
+ filterData.firstEnabledIndex = firstEnabledIndex;
834
+ filterData.lastEnabledIndex = lastEnabledIndex;
835
+ }
836
+ _popFilterData() {
837
+ this._filterStackIndex--;
838
+ return this._filterStack[this._filterStackIndex];
839
+ }
840
+ _getPreviousFilterData() {
841
+ let previousFilterData;
842
+ let index = this._filterStackIndex - 1;
843
+ while (index > 0) {
844
+ index--;
845
+ previousFilterData = this._filterStack[index];
846
+ if (!previousFilterData.skip) break;
847
+ }
848
+ return previousFilterData;
849
+ }
850
+ _pushFilterData() {
851
+ let filterData = this._filterStack[this._filterStackIndex];
852
+ if (!filterData) filterData = this._filterStack[this._filterStackIndex] = new FilterData();
853
+ this._filterStackIndex++;
854
+ return filterData;
855
+ }
856
+ };
857
+ /** @ignore */
858
+ FilterSystem.extension = {
859
+ type: [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem],
860
+ name: "filter"
861
+ };
862
+ //#endregion
863
+ //#region ../../node_modules/.pnpm/pixi.js@8.20.1/node_modules/pixi.js/lib/filters/init.mjs
864
+ extensions.add(FilterSystem, CanvasFilterSystem);
865
+ extensions.add(FilterPipe);
866
+ //#endregion
867
+ export {};